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