1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - bin2obj
3   File:     output.c
4 
5   Copyright 2005–2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 #include "bin2obj.h"
18 
19 static BOOL output_region(FILE * fp, u32 offset, const u8 *ptr, u32 size);
20 
21 /*---------------------------------------------------------------------------*
22   Name:         output_object
23 
24   Description:  Output object to file
25 
26   Arguments:    obj		Object information
27                 filename	Output file name
28 
29   Returns:      None.
30  *---------------------------------------------------------------------------*/
output_object(const Object * obj,const char * filename)31 BOOL output_object(const Object * obj, const char *filename)
32 {
33     FILE   *fp;
34     u32     i, n;
35     u32     offset;
36     u32     size;
37     u8     *ptr;
38     Object const *cooked_obj;
39     Object object;
40 
41     if (NULL == (fp = fopen(filename, "wb")))
42     {
43         fprintf(stderr, "Error: Cannot open file %s.\n", filename);
44         return FALSE;
45     }
46 
47     if (obj->header.e_ident[5] == ELFDATA2MSB)
48     {
49         // Big Endian: Clone & Swap byte order
50         conv_to_big_endian(obj, &object);
51         cooked_obj = &object;
52     }
53     else
54     {
55         // Little Endian: Just make shortcut
56         cooked_obj = obj;
57     }
58 
59     // Elf Header
60     offset = 0;
61     size = obj->header.e_ehsize;
62     ptr = (u8 *)&cooked_obj->header;
63     if (!output_region(fp, offset, ptr, size))
64     {
65         return FALSE;
66     }
67 
68     // Section Header
69     offset = obj->header.e_shoff;
70     size = obj->header.e_shentsize * obj->header.e_shnum;
71     ptr = (u8 *)&cooked_obj->section[0];
72     if (!output_region(fp, offset, ptr, size))
73     {
74         return FALSE;
75     }
76 
77     // Section: ShStrTab
78     n = obj->header.e_shstrndx;
79     offset = obj->section[n].sh_offset;
80     size = obj->section[n].sh_size;
81     ptr = (u8 *)obj->section_name.ptr;
82     if (!output_region(fp, offset, ptr, size))
83     {
84         return FALSE;
85     }
86 
87     // Section: Symbol
88     n = obj->symbol_index;
89     offset = obj->section[n].sh_offset;
90     size = obj->section[n].sh_size;
91     ptr = (u8 *)&cooked_obj->symbol[0];
92     if (!output_region(fp, offset, ptr, size))
93     {
94         return FALSE;
95     }
96 
97     // Section: StrTab
98     n = obj->symbol_name_index;
99     offset = obj->section[n].sh_offset;
100     size = obj->section[n].sh_size;
101     ptr = (u8 *)obj->symbol_name.ptr;
102     if (!output_region(fp, offset, ptr, size))
103     {
104         return FALSE;
105     }
106 
107     // Section: Object
108     for (i = 0; i < obj->num_data; i++)
109     {
110         n = obj->data[i].index;
111         offset = obj->section[n].sh_offset;
112         size = obj->section[n].sh_size;
113         ptr = (u8 *)obj->data[i].section.ptr;
114         if (!output_region(fp, offset, ptr, size))
115         {
116             return FALSE;
117         }
118     }
119     return TRUE;
120 }
121 
122 
123 /*---------------------------------------------------------------------------*
124   Name:         output_region
125 
126   Description:  Outputs the data with memory sorting attached
127 
128   Arguments:    fp               File pointer
129                 ptr              Data
130                 size             Memory block size
131                 offset           Write start offset
132   Returns:      TRUE for success; FALSE for failure.
133  *---------------------------------------------------------------------------*/
output_region(FILE * fp,u32 offset,const u8 * ptr,u32 size)134 static BOOL output_region(FILE * fp, u32 offset, const u8 *ptr, u32 size)
135 {
136     static u8 zero[1] = { '\0' };
137 
138     while (ftell(fp) < offset)
139     {
140         if (1 != fwrite(zero, sizeof(u8), 1, fp))
141         {
142             return FALSE;
143         }
144     }
145     return 1 == fwrite(ptr, size, 1, fp) ? TRUE : FALSE;
146 }
147