diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-04-17 01:43:44 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-04-17 01:43:44 +0000 |
commit | f6208bde4630571ae75a43ea39a25a746f08bcfb (patch) | |
tree | cd585e94b9a91c832668569798dd07e0b0fca66b /utils/sbtools/elf.c | |
parent | 02118edb997112234798c4f3d3e978659e7a8836 (diff) | |
download | rockbox-f6208bde4630571ae75a43ea39a25a746f08bcfb.tar.gz rockbox-f6208bde4630571ae75a43ea39a25a746f08bcfb.zip |
Rename sbinfo to sbtools and sbinfo.c to sbtoelf.c; preparing for future elftosb
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29733 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/sbtools/elf.c')
-rw-r--r-- | utils/sbtools/elf.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/utils/sbtools/elf.c b/utils/sbtools/elf.c new file mode 100644 index 0000000000..f146bcc111 --- /dev/null +++ b/utils/sbtools/elf.c | |||
@@ -0,0 +1,237 @@ | |||
1 | #include "elf.h" | ||
2 | |||
3 | void elf_init(struct elf_params_t *params) | ||
4 | { | ||
5 | params->has_start_addr = false; | ||
6 | params->start_addr = 0; | ||
7 | params->first_section = NULL; | ||
8 | params->last_section = NULL; | ||
9 | } | ||
10 | |||
11 | extern void *xmalloc(size_t s); | ||
12 | |||
13 | static struct elf_section_t *elf_add_section(struct elf_params_t *params) | ||
14 | { | ||
15 | struct elf_section_t *sec = xmalloc(sizeof(struct elf_section_t)); | ||
16 | if(params->first_section == NULL) | ||
17 | params->first_section = params->last_section = sec; | ||
18 | else | ||
19 | { | ||
20 | params->last_section->next = sec; | ||
21 | params->last_section = sec; | ||
22 | } | ||
23 | sec->next = NULL; | ||
24 | |||
25 | return sec; | ||
26 | } | ||
27 | |||
28 | void elf_add_load_section(struct elf_params_t *params, | ||
29 | uint32_t load_addr, uint32_t size, const void *section) | ||
30 | { | ||
31 | struct elf_section_t *sec = elf_add_section(params); | ||
32 | |||
33 | sec->type = EST_LOAD; | ||
34 | sec->addr = load_addr; | ||
35 | sec->size = size; | ||
36 | sec->section = xmalloc(size); | ||
37 | memcpy(sec->section, section, size); | ||
38 | } | ||
39 | |||
40 | void elf_add_fill_section(struct elf_params_t *params, | ||
41 | uint32_t fill_addr, uint32_t size, uint32_t pattern) | ||
42 | { | ||
43 | if(pattern != 0x00) | ||
44 | { | ||
45 | printf("oops, non-zero filling, ignore fill section\n"); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | struct elf_section_t *sec = elf_add_section(params); | ||
50 | |||
51 | sec->type = EST_FILL; | ||
52 | sec->addr = fill_addr; | ||
53 | sec->size = size; | ||
54 | sec->pattern = pattern; | ||
55 | } | ||
56 | |||
57 | void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) | ||
58 | { | ||
59 | Elf32_Ehdr ehdr; | ||
60 | uint32_t phnum = 0; | ||
61 | struct elf_section_t *sec = params->first_section; | ||
62 | uint32_t offset = 0; | ||
63 | Elf32_Phdr phdr; | ||
64 | Elf32_Shdr shdr; | ||
65 | memset(&ehdr, 0, EI_NIDENT); | ||
66 | |||
67 | uint32_t bss_strtbl = 0; | ||
68 | uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1; | ||
69 | uint32_t strtbl_size = text_strtbl + strlen(".text") + 1; | ||
70 | |||
71 | while(sec) | ||
72 | { | ||
73 | if(sec->type == EST_LOAD) | ||
74 | { | ||
75 | sec->offset = offset; | ||
76 | offset += sec->size; | ||
77 | } | ||
78 | |||
79 | phnum++; | ||
80 | sec = sec->next; | ||
81 | } | ||
82 | |||
83 | uint32_t strtbl_offset = offset; | ||
84 | |||
85 | ehdr.e_ident[EI_MAG0] = ELFMAG0; | ||
86 | ehdr.e_ident[EI_MAG1] = ELFMAG1; | ||
87 | ehdr.e_ident[EI_MAG2] = ELFMAG2; | ||
88 | ehdr.e_ident[EI_MAG3] = ELFMAG3; | ||
89 | ehdr.e_ident[EI_CLASS] = ELFCLASS32; | ||
90 | ehdr.e_ident[EI_DATA] = ELFDATA2LSB; | ||
91 | ehdr.e_ident[EI_VERSION] = EV_CURRENT; | ||
92 | ehdr.e_ident[EI_OSABI] = ELFOSABI_NONE; | ||
93 | ehdr.e_ident[EI_ABIVERSION] = 0; | ||
94 | ehdr.e_type = ET_EXEC; | ||
95 | ehdr.e_machine = EM_ARM; | ||
96 | ehdr.e_version = EV_CURRENT; | ||
97 | ehdr.e_entry = params->start_addr; | ||
98 | ehdr.e_flags = 0; | ||
99 | if(params->has_start_addr) | ||
100 | ehdr.e_flags |= EF_ARM_HASENTRY; | ||
101 | ehdr.e_ehsize = sizeof ehdr; | ||
102 | ehdr.e_phentsize = sizeof phdr; | ||
103 | ehdr.e_phnum = phnum; | ||
104 | ehdr.e_shentsize = sizeof shdr; | ||
105 | ehdr.e_shnum = phnum + 2; /* one for section 0 and one for string table */ | ||
106 | ehdr.e_shstrndx = ehdr.e_shnum - 1; | ||
107 | ehdr.e_phoff = ehdr.e_ehsize; | ||
108 | ehdr.e_shoff = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize; | ||
109 | |||
110 | write(user, 0, &ehdr, sizeof ehdr); | ||
111 | |||
112 | uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize + | ||
113 | ehdr.e_shnum * ehdr.e_shentsize; | ||
114 | |||
115 | sec = params->first_section; | ||
116 | offset = ehdr.e_phoff; | ||
117 | while(sec) | ||
118 | { | ||
119 | sec->offset += data_offset; | ||
120 | |||
121 | phdr.p_type = PT_LOAD; | ||
122 | if(sec->type == EST_LOAD) | ||
123 | phdr.p_offset = sec->offset; | ||
124 | else | ||
125 | phdr.p_offset = 0; | ||
126 | phdr.p_paddr = sec->addr; | ||
127 | phdr.p_vaddr = phdr.p_paddr; /* assume identity map ? */ | ||
128 | phdr.p_memsz = sec->size; | ||
129 | if(sec->type == EST_LOAD) | ||
130 | phdr.p_filesz = phdr.p_memsz; | ||
131 | else | ||
132 | phdr.p_filesz = 0; | ||
133 | phdr.p_flags = PF_X | PF_W | PF_R; | ||
134 | phdr.p_align = 0; | ||
135 | |||
136 | write(user, offset, &phdr, sizeof phdr); | ||
137 | |||
138 | offset += sizeof(Elf32_Phdr); | ||
139 | sec = sec->next; | ||
140 | } | ||
141 | |||
142 | sec = params->first_section; | ||
143 | offset = ehdr.e_shoff; | ||
144 | |||
145 | { | ||
146 | shdr.sh_name = 0; | ||
147 | shdr.sh_type = SHT_NULL; | ||
148 | shdr.sh_flags = 0; | ||
149 | shdr.sh_addr = 0; | ||
150 | shdr.sh_offset = 0; | ||
151 | shdr.sh_size = 0; | ||
152 | shdr.sh_link = SHN_UNDEF; | ||
153 | shdr.sh_info = 0; | ||
154 | shdr.sh_addralign = 0; | ||
155 | shdr.sh_entsize = 0; | ||
156 | |||
157 | write(user, offset, &shdr, sizeof shdr); | ||
158 | |||
159 | offset += sizeof(Elf32_Shdr); | ||
160 | } | ||
161 | |||
162 | while(sec) | ||
163 | { | ||
164 | shdr.sh_name = text_strtbl; | ||
165 | if(sec->type == EST_LOAD) | ||
166 | shdr.sh_type = SHT_PROGBITS; | ||
167 | else | ||
168 | shdr.sh_type = SHT_NOBITS; | ||
169 | shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; | ||
170 | shdr.sh_addr = sec->addr; | ||
171 | shdr.sh_offset = sec->offset; | ||
172 | shdr.sh_size = sec->size; | ||
173 | shdr.sh_link = SHN_UNDEF; | ||
174 | shdr.sh_info = 0; | ||
175 | shdr.sh_addralign = 1; | ||
176 | shdr.sh_entsize = 0; | ||
177 | |||
178 | write(user, offset, &shdr, sizeof shdr); | ||
179 | |||
180 | offset += sizeof(Elf32_Shdr); | ||
181 | sec = sec->next; | ||
182 | } | ||
183 | |||
184 | { | ||
185 | shdr.sh_name = bss_strtbl; | ||
186 | shdr.sh_type = SHT_STRTAB; | ||
187 | shdr.sh_flags = 0; | ||
188 | shdr.sh_addr = 0; | ||
189 | shdr.sh_offset = strtbl_offset + data_offset; | ||
190 | shdr.sh_size = strtbl_size; | ||
191 | shdr.sh_link = SHN_UNDEF; | ||
192 | shdr.sh_info = 0; | ||
193 | shdr.sh_addralign = 1; | ||
194 | shdr.sh_entsize = 0; | ||
195 | |||
196 | write(user, offset, &shdr, sizeof shdr); | ||
197 | |||
198 | offset += sizeof(Elf32_Shdr); | ||
199 | } | ||
200 | |||
201 | sec = params->first_section; | ||
202 | while(sec) | ||
203 | { | ||
204 | if(sec->type == EST_LOAD) | ||
205 | write(user, sec->offset, sec->section, sec->size); | ||
206 | sec = sec->next; | ||
207 | } | ||
208 | |||
209 | write(user, strtbl_offset + data_offset, ".bss\0.text\0", strtbl_size); | ||
210 | } | ||
211 | |||
212 | bool elf_is_empty(struct elf_params_t *params) | ||
213 | { | ||
214 | return params->first_section == NULL; | ||
215 | } | ||
216 | |||
217 | void elf_set_start_addr(struct elf_params_t *params, uint32_t addr) | ||
218 | { | ||
219 | params->has_start_addr = true; | ||
220 | params->start_addr = addr; | ||
221 | } | ||
222 | |||
223 | void elf_release(struct elf_params_t *params) | ||
224 | { | ||
225 | struct elf_section_t *sec, *next_sec; | ||
226 | sec = params->first_section; | ||
227 | while(sec) | ||
228 | { | ||
229 | next_sec = sec->next; | ||
230 | if(sec->type == EST_LOAD) | ||
231 | free(sec->section); | ||
232 | free(sec); | ||
233 | sec = next_sec; | ||
234 | } | ||
235 | params->first_section = NULL; | ||
236 | params->last_section = NULL; | ||
237 | } | ||