1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - bin2obj
3   File:     object.c
4 
5   Copyright 2005-2008, 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 void header_init(ELF32_ElfHeader * h, u16 machine, u8 endian);
20 /*---------------------------------------------------------------------------*
21   Name:         object_init
22 
23   Description:  Initializes object information.
24 
25   Arguments:    obj    Object
26 
27   Returns:      TRUE for success; FALSE for failure.
28  *---------------------------------------------------------------------------*/
object_init(Object * obj,u16 machine,u8 endian)29 void object_init(Object * obj, u16 machine, u8 endian)
30 {
31     ELF32_SectionHeader *s;
32     ELF32_ElfHeader *h;
33 
34     //-----------------------------------------------------------------------
35     // Initialize area ZERO
36     //-----------------------------------------------------------------------
37     memset(obj, 0, sizeof(Object));
38 
39     //-----------------------------------------------------------------------
40     // Initialization of Elf Header
41     //-----------------------------------------------------------------------
42     h = &obj->header;
43     header_init(h, machine, endian);
44 
45     //-----------------------------------------------------------------------
46     // Register default section
47     //-----------------------------------------------------------------------
48 
49     // The section with index=0 is dummy=NULL
50     (void)add_section(obj, NULL, SHT_NULL, 0, 0, 0);
51 
52     // index=1 section name table
53     h->e_shstrndx = add_section(obj, ".shstrtab", SHT_STRTAB, SHF_NULL, obj->section_name.size, 0);
54 
55     // index=2 symbol info structure
56     obj->symbol_index = add_section(obj, ".symtab", SHT_SYMTAB, SHF_NULL, 0, 4);
57 
58     // index=3 symbol name table
59     obj->symbol_name_index =
60         add_section(obj, ".strtab", SHT_STRTAB, SHF_NULL, obj->symbol_name.size, 1);
61 
62     // Add symbol information setting
63     s = &obj->section[obj->symbol_index];
64     s->sh_link = obj->symbol_name_index;        // symbol name table link
65     s->sh_info = -1;                   // Initialization of symbol's last index value
66     s->sh_entsize = sizeof(ELF32_Symbol);       // symbol entry size
67 
68     //-----------------------------------------------------------------------
69     // Symbol table initialization
70     //-----------------------------------------------------------------------
71 
72     // Register index=0 NULL symbol
73     (void)add_symbol(obj, NULL, 0, 0, 0);
74 }
75 
76 /*---------------------------------------------------------------------------*
77   Name:         header_init
78 
79   Description:  Creates ELF header info.
80 
81   Arguments:    elfHeader  ELF header info
82                 machine    Machine code
83                               EM_ARM // ARM
84                               EM_PPC // PPC
85                 endian     ELF's endian
86                               ELFDATA2LSB // Little Endian
87                               ELFDATA2MSB // Big    Endian
88   Returns:      None.
89  *---------------------------------------------------------------------------*/
header_init(ELF32_ElfHeader * h,u16 machine,u8 endian)90 static void header_init(ELF32_ElfHeader * h, u16 machine, u8 endian)
91 {
92     memset(h, 0, sizeof(ELF32_ElfHeader));
93     h->e_ident[0] = ELFMAG0;           // 0x7f
94     h->e_ident[1] = ELFMAG1;           // 'E'
95     h->e_ident[2] = ELFMAG2;           // 'L'
96     h->e_ident[3] = ELFMAG3;           // 'F'
97     h->e_ident[4] = ELFCLASS32;        // 32 bit
98     h->e_ident[5] = endian;            // ELFDATA2MSB/ELFDATA2LSB
99     h->e_ident[6] = EV_CURRENT;        // CURRENT
100     h->e_type = ET_REL;
101     h->e_machine = machine;
102     h->e_version = EV_CURRENT;
103     h->e_entry = 0;
104     h->e_phoff = 0;
105     h->e_shoff = 0;                    // Fill in with correct values later
106     h->e_flags = 0;
107     h->e_ehsize = sizeof(ELF32_ElfHeader);
108     h->e_phentsize = 0;
109     h->e_phnum = 0;
110     h->e_shentsize = sizeof(ELF32_SectionHeader);
111     h->e_shnum = 0;                    // +1 each time section increases
112     h->e_shstrndx = 0;                 // Fill in with correct values later
113 
114     return;
115 }
116 
117 /*---------------------------------------------------------------------------*
118   Name:         map_section
119 
120   Description:  Writes the section's location information.
121 
122   Arguments:    obj    Object
123 
124   Returns:      None.
125  *---------------------------------------------------------------------------*/
map_section(Object * obj)126 void map_section(Object * obj)
127 {
128     ELF32_ElfHeader *h;
129     ELF32_SectionHeader *s;
130     u32     offset;
131     int     i;
132 
133     // ELF HEADER/SECTION HEADER position calculation
134     h = &obj->header;
135     offset = h->e_ehsize;
136     h->e_shoff = roundup(offset, 4);
137     offset = h->e_shoff + h->e_shentsize * h->e_shnum;
138 
139     // Section's position calculation
140     for (i = 1; i < obj->header.e_shnum; i++)
141     {
142         s = &obj->section[i];
143         s->sh_offset = roundup(offset, s->sh_addralign);
144         offset = s->sh_offset + s->sh_size;
145     }
146     return;
147 }
148 
149 /*---------------------------------------------------------------------------*
150   Name:         roundup
151 
152   Description:  Rounds up integers.
153 
154   Arguments:    val       Value
155                 align     Boundary value
156 
157   Returns:      Result
158  *---------------------------------------------------------------------------*/
roundup(u32 val,u32 align)159 u32 roundup(u32 val, u32 align)
160 {
161     if (align > 1)
162     {
163         u32     n = val % align;
164 
165         if (n > 0)
166         {
167             val += (align - n);
168         }
169     }
170     return val;
171 }
172 
173 
174 /*---------------------------------------------------------------------------*
175   Name:         conv_to_big_endian
176 
177   Description:  Convert to big endian
178 
179   Arguments:    src  before conversion
180                 dest  after conversion
181 
182   Returns:      Result
183  *---------------------------------------------------------------------------*/
Be32(u32 x)184 static u32 Be32(u32 x)
185 {
186     return (u32)(((x) >> 24) & 0x000000ff) | (((x) >> 8) & 0x0000ff00) |
187         (((x) << 8) & 0x00ff0000) | (((x) << 24) & 0xff000000);
188 }
189 
Be16(u16 x)190 static u16 Be16(u16 x)
191 {
192     return (u16)(((x) >> 8) & 0x00ff) | (((x) << 8) & 0xff00);
193 }
194 
conv_to_big_endian_header(const ELF32_ElfHeader * src,ELF32_ElfHeader * dest)195 static void conv_to_big_endian_header(const ELF32_ElfHeader * src, ELF32_ElfHeader * dest)
196 {
197     memcpy(dest->e_ident, src->e_ident, EI_NIDENT);
198     dest->e_type = Be16(src->e_type);
199     dest->e_machine = Be16(src->e_machine);
200     dest->e_version = Be32(src->e_version);
201     dest->e_entry = Be32(src->e_entry);
202     dest->e_phoff = Be32(src->e_phoff);
203     dest->e_shoff = Be32(src->e_shoff);
204     dest->e_flags = Be32(src->e_flags);
205     dest->e_ehsize = Be16(src->e_ehsize);
206     dest->e_phentsize = Be16(src->e_phentsize);
207     dest->e_phnum = Be16(src->e_phnum);
208     dest->e_shentsize = Be16(src->e_shentsize);
209     dest->e_shnum = Be16(src->e_shnum);
210     dest->e_shstrndx = Be16(src->e_shstrndx);
211 }
212 
conv_to_big_endian_section(const ELF32_SectionHeader * src,ELF32_SectionHeader * dest)213 static void conv_to_big_endian_section(const ELF32_SectionHeader * src, ELF32_SectionHeader * dest)
214 {
215     dest->sh_name = Be32(src->sh_name);
216     dest->sh_type = Be32(src->sh_type);
217     dest->sh_flags = Be32(src->sh_flags);
218     dest->sh_addr = Be32(src->sh_addr);
219     dest->sh_offset = Be32(src->sh_offset);
220     dest->sh_size = Be32(src->sh_size);
221     dest->sh_link = Be32(src->sh_link);
222     dest->sh_info = Be32(src->sh_info);
223     dest->sh_addralign = Be32(src->sh_addralign);
224     dest->sh_entsize = Be32(src->sh_entsize);
225 }
226 
conv_to_big_endian_symbol(const ELF32_Symbol * src,ELF32_Symbol * dest)227 static void conv_to_big_endian_symbol(const ELF32_Symbol * src, ELF32_Symbol * dest)
228 {
229     dest->st_name = Be32(src->st_name);
230     dest->st_value = Be32(src->st_value);
231     dest->st_size = Be32(src->st_size);
232     dest->st_info = src->st_info;
233     dest->st_other = src->st_other;
234     dest->st_shndx = Be16(src->st_shndx);
235 }
236 
conv_to_big_endian(const Object * src,Object * dest)237 void conv_to_big_endian(const Object * src, Object * dest)
238 {
239     int     i, n;
240 
241     conv_to_big_endian_header(&src->header, &dest->header);
242 
243     for (i = 0; i < src->header.e_shnum; i++)
244     {
245         conv_to_big_endian_section(&src->section[i], &dest->section[i]);
246     }
247 
248     n = src->section[src->symbol_index].sh_size / sizeof(src->symbol[0]);
249     for (i = 0; i < n; i++)
250     {
251         conv_to_big_endian_symbol(&src->symbol[i], &dest->symbol[i]);
252     }
253 }
254