1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - bin2obj
3 File: section.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 s32 read_datasec(Object * obj, const char *filename);
20 static u32 section_add_string(Section * s, const char *string);
21
22 /*---------------------------------------------------------------------------*
23 Name: add_datasec
24
25 Description: Adds data section
26
27 Arguments: obj Pointer to object
28 section_rodata Name of data section dedicated to reading
29 section_rwdata Name of readable/writeable data section
30 symbol_format_begin Head of symbol name (before %f conversion)
31 symbol_format_end End of symbol name (before %f conversion)
32 filename Input binary file name
33 writable TRUE .data FALSE .rodata
34 align Alignment
35 Returns: TRUE for success; FALSE for failure.
36 *---------------------------------------------------------------------------*/
add_datasec(Object * obj,const char * section_rodata,const char * section_rwdata,const char * symbol_format_begin,const char * symbol_format_end,const char * filename,BOOL writable,u32 align)37 BOOL add_datasec(Object * obj,
38 const char *section_rodata, const char *section_rwdata,
39 const char *symbol_format_begin, const char *symbol_format_end,
40 const char *filename, BOOL writable, u32 align)
41 {
42 s32 n;
43 DataSection *d;
44 char *symbol_begin; // Head of symbol name (after %f conversion)
45 char *symbol_end; // End of symbol name (after %f conversion)
46
47 //
48 // Data section read
49 //
50 if (0 > (n = read_datasec(obj, filename)))
51 {
52 return FALSE;
53 }
54
55 //
56 // Registration of data section
57 //
58 d = &obj->data[n];
59 if (writable) // .rodata or .data processing
60 {
61 d->index =
62 add_section(obj, section_rwdata, SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, d->section.size,
63 align);
64 }
65 else
66 {
67 d->index =
68 add_section(obj, section_rodata, SHT_PROGBITS, SHF_ALLOC, d->section.size, align);
69 }
70
71 //
72 // Symbol registration
73 //
74 symbol_begin = create_symbol_string(filename, symbol_format_begin);
75 symbol_end = create_symbol_string(filename, symbol_format_end);
76 (void)add_symbol(obj, symbol_begin, 0, d->section.size, d->index);
77 (void)add_symbol(obj, symbol_end, d->section.size, 0, d->index);
78 free(symbol_begin);
79 free(symbol_end);
80
81 return TRUE;
82 }
83
84 /*---------------------------------------------------------------------------*
85 Name: read_datasec
86
87 Description: Reads the data section.
88
89 Arguments: obj Pointer to object
90 filename Input binary file name
91
92 Returns: TRUE for success; FALSE for failure.
93 *---------------------------------------------------------------------------*/
read_datasec(Object * obj,const char * filename)94 static s32 read_datasec(Object * obj, const char *filename)
95 {
96 struct stat st;
97 FILE *fp;
98 u32 n = obj->num_data;
99 Section *s = &obj->data[n].section;
100
101 //
102 // Allocate a data section area from the heap with a size enough for the input file and load the input file "filename" there.
103 //
104 //
105 if (stat(filename, &st) || !S_ISREG(st.st_mode) || st.st_size < 0
106 || NULL == (fp = fopen(filename, "rb")))
107 {
108 fprintf(stderr, "Error: Cannot open file %s.\n", filename);
109 return -1;
110 }
111
112 s->size = st.st_size;
113
114 if (NULL == (s->ptr = malloc(s->size)))
115 {
116 fprintf(stderr, "Error: No memory.\n");
117 fclose(fp);
118 return -1;
119 }
120
121 if (s->size != fread(s->ptr, sizeof(u8), s->size, fp))
122 {
123 fprintf(stderr, "Error: Cannot read file %s.\n", filename);
124 free(s->ptr);
125 fclose(fp);
126 return -1;
127 }
128 fclose(fp);
129
130 obj->num_data = n + 1;
131 return n;
132 }
133
134 /*---------------------------------------------------------------------------*
135 Name: add_section_name
136
137 Description: Adds the section name.
138
139 Arguments: obj Object
140 name Section name
141
142 Returns: Start position in the section name table of the added section name
143 *---------------------------------------------------------------------------*/
add_section_name(Object * obj,const char * name)144 u32 add_section_name(Object * obj, const char *name)
145 {
146 // Register internally in the section
147 u32 pos = section_add_string(&obj->section_name, name);
148
149 // Update section information (size)
150 if (obj->header.e_shstrndx > 0)
151 {
152 obj->section[obj->header.e_shstrndx].sh_size = obj->section_name.size;
153 }
154 return pos;
155 }
156
157 /*---------------------------------------------------------------------------*
158 Name: add_section
159
160 Description: Add the section.
161
162 Arguments: obj Pointer to object
163 name Symbol name (If NULL, make it NULL SECTION)
164 type SHT_*
165 flags SHF_*
166 size Section size
167 align Section alignment
168
169 Returns: Registered index
170 *---------------------------------------------------------------------------*/
add_section(Object * obj,const char * name,u32 type,u32 flags,u32 size,u32 align)171 u32 add_section(Object * obj, const char *name, u32 type, u32 flags, u32 size, u32 align)
172 {
173 ELF32_SectionHeader *s;
174 u32 n;
175
176 n = obj->header.e_shnum;
177 s = &obj->section[n];
178
179 if (name)
180 {
181 s->sh_name = add_section_name(obj, name);
182 s->sh_type = type;
183 s->sh_flags = flags;
184 s->sh_addr = 0;
185 s->sh_offset = 0;
186 s->sh_size = size;
187 s->sh_link = 0;
188 s->sh_info = 0;
189 s->sh_addralign = align;
190 s->sh_entsize = 0;
191 }
192 else
193 {
194 (void)add_section_name(obj, "");
195 memset(s, 0, sizeof(ELF32_SectionHeader));
196 }
197 obj->header.e_shnum = n + 1;
198
199 return n;
200 }
201
202 /*---------------------------------------------------------------------------*
203 Name: add_symbol_name
204
205 Description: Adds the symbol name.
206
207 Arguments: obj Object
208 name Symbol name
209
210 Returns: Start position in the section name table of the added symbol name
211 *---------------------------------------------------------------------------*/
add_symbol_name(Object * obj,const char * name)212 u32 add_symbol_name(Object * obj, const char *name)
213 {
214 u32 pos;
215
216 // Register internally in the section
217 // When the name is NULL, this is handled as "".
218 pos = section_add_string(&obj->symbol_name, name ? name : "");
219
220 // Update section information (size)
221 if (obj->symbol_name_index > 0)
222 {
223 obj->section[obj->symbol_name_index].sh_size = obj->symbol_name.size;
224 }
225 return pos;
226 }
227
228 /*---------------------------------------------------------------------------*
229 Name: add_symbol
230
231 Description: Adds symbol.
232
233 Arguments: obj Pointer to the object
234 symbol Symbol name (If NULL, make it NULL SECTION)
235 value Symbol value
236 size Symbol size
237 section Related section
238
239 Returns: Registered index
240 *---------------------------------------------------------------------------*/
add_symbol(Object * obj,const char * symbol,u32 value,u32 size,u32 section)241 u32 add_symbol(Object * obj, const char *symbol, u32 value, u32 size, u32 section)
242 {
243 ELF32_SectionHeader *symtab = &obj->section[obj->symbol_index];
244 u32 n = symtab->sh_info + 1;
245 ELF32_Symbol *l = &obj->symbol[n];
246
247 if (obj->symbol_index > 0)
248 {
249 if (symbol)
250 {
251 // Symbols in the C language have a '_' appended to the front of the normal function name
252 l->st_name = add_symbol_name(obj, symbol);
253 l->st_value = value;
254 l->st_size = size;
255 l->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
256 l->st_other = 0;
257 l->st_shndx = section;
258 }
259 else
260 {
261 (void)add_symbol_name(obj, NULL);
262 memset(l, 0, sizeof(ELF32_Symbol));
263 }
264
265 // Update symbol table
266 symtab->sh_info = n;
267 symtab->sh_size = (n + 1) * symtab->sh_entsize;
268 }
269 else
270 {
271 fprintf(stderr, "Warning: no symbol section. [%s] is skipped.\n", symbol);
272 }
273 return n;
274 }
275
276 /*---------------------------------------------------------------------------*
277 Name: section_add_string
278
279 Description: Adds string to section.
280
281 Arguments: section: Section
282 string: Characters
283
284 Returns: Start position of the added string's table (i.e. the size before the function was called)
285 *---------------------------------------------------------------------------*/
section_add_string(Section * s,const char * string)286 static u32 section_add_string(Section * s, const char *string)
287 {
288 int new_size = s->size + strlen(string) + 1;
289 u8 *new_ptr;
290 int size;
291
292 if (NULL == (new_ptr = malloc(new_size)))
293 {
294 fprintf(stderr, "Error: No memory.\n");
295 exit(1);
296 }
297 memcpy(new_ptr, s->ptr, s->size);
298 strcpy(new_ptr + s->size, string);
299 free(s->ptr);
300
301 size = s->size;
302 s->ptr = new_ptr;
303 s->size = new_size;
304
305 return size;
306 }
307