summaryrefslogtreecommitdiff
path: root/utils/rknanoutils/rkboottool/elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rknanoutils/rkboottool/elf.c')
-rw-r--r--utils/rknanoutils/rkboottool/elf.c73
1 files changed, 43 insertions, 30 deletions
diff --git a/utils/rknanoutils/rkboottool/elf.c b/utils/rknanoutils/rkboottool/elf.c
index 481ab98dd6..78b29506a2 100644
--- a/utils/rknanoutils/rkboottool/elf.c
+++ b/utils/rknanoutils/rkboottool/elf.c
@@ -21,6 +21,14 @@
21#include "elf.h" 21#include "elf.h"
22#include "misc.h" 22#include "misc.h"
23 23
24static char *strdup(const char *str)
25{
26 int len = strlen(str);
27 char *s = malloc(len + 1);
28 memcpy(s, str, len + 1);
29 return s;
30}
31
24/** 32/**
25 * Definitions 33 * Definitions
26 * taken from elf.h linux header 34 * taken from elf.h linux header
@@ -189,43 +197,55 @@ static struct elf_segment_t *elf_add_segment(struct elf_params_t *params)
189} 197}
190 198
191void elf_add_load_section(struct elf_params_t *params, 199void elf_add_load_section(struct elf_params_t *params,
192 uint32_t load_addr, uint32_t size, const void *section) 200 uint32_t load_addr, uint32_t size, const void *section, const char *name)
193{ 201{
194 struct elf_section_t *sec = elf_add_section(params); 202 struct elf_section_t *sec = elf_add_section(params);
203 char buffer[32];
204 if(name == NULL)
205 {
206 sprintf(buffer, ".text%d", params->unique_index++);
207 name = buffer;
208 }
195 209
196 sec->type = EST_LOAD; 210 sec->type = EST_LOAD;
197 sec->addr = load_addr; 211 sec->addr = load_addr;
198 sec->size = size; 212 sec->size = size;
199 sec->section = xmalloc(size); 213 sec->section = xmalloc(size);
214 sec->name = strdup(name);
200 memcpy(sec->section, section, size); 215 memcpy(sec->section, section, size);
201} 216}
202 217
203void elf_add_fill_section(struct elf_params_t *params, 218void elf_add_fill_section(struct elf_params_t *params,
204 uint32_t fill_addr, uint32_t size, uint32_t pattern) 219 uint32_t fill_addr, uint32_t size, uint32_t pattern)
205{ 220{
221 char buffer[32];
222 sprintf(buffer, ".bss%d", params->unique_index++);
223
206 if(pattern != 0x00) 224 if(pattern != 0x00)
207 { 225 {
208 printf("oops, non-zero filling, ignore fill section\n"); 226 printf("oops, non-zero filling, ignore fill section\n");
209 return; 227 return;
210 } 228 }
211 229
212 struct elf_section_t *sec = elf_add_section(params); 230 struct elf_section_t *sec = elf_add_section(params);
213 231
214 sec->type = EST_FILL; 232 sec->type = EST_FILL;
215 sec->addr = fill_addr; 233 sec->addr = fill_addr;
216 sec->size = size; 234 sec->size = size;
217 sec->pattern = pattern; 235 sec->pattern = pattern;
236 sec->name = strdup(buffer);
218} 237}
219 238
220void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, 239void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
221 elf_printf_fn_t printf, void *user) 240 elf_printf_fn_t printf, void *user)
222{ 241{
223 (void) printf; 242 (void) printf;
224 243
225 Elf32_Ehdr ehdr; 244 Elf32_Ehdr ehdr;
226 uint32_t phnum = 0; 245 uint32_t phnum = 0;
227 struct elf_section_t *sec = params->first_section; 246 struct elf_section_t *sec = params->first_section;
228 uint32_t offset = 0; 247 uint32_t offset = 0;
248 uint32_t strtbl_size = 1; /* offset 0 is for the NULL name */
229 Elf32_Phdr phdr; 249 Elf32_Phdr phdr;
230 Elf32_Shdr shdr; 250 Elf32_Shdr shdr;
231 memset(&ehdr, 0, EI_NIDENT); 251 memset(&ehdr, 0, EI_NIDENT);
@@ -241,7 +261,9 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
241 { 261 {
242 sec->offset = 0; 262 sec->offset = 0;
243 } 263 }
244 264 sec->name_offset = strtbl_size;
265 strtbl_size += strlen(sec->name) + 1;
266
245 phnum++; 267 phnum++;
246 sec = sec->next; 268 sec = sec->next;
247 } 269 }
@@ -275,16 +297,14 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
275 297
276 write(user, 0, &ehdr, sizeof ehdr); 298 write(user, 0, &ehdr, sizeof ehdr);
277 299
278 /* allocate enough size to hold any combinaison of .text/.bss in the string table: 300 /* the last name offset gives the size of the section, we need to add a small
279 * - one empty name ("\0") 301 * amount of .shstrtab name */
280 * - at most N names of the form ".textXXXX\0" or ".bssXXXX\0" 302 uint32_t shstrtab_index = strtbl_size;
281 * - one name ".shstrtab\0" */ 303 strtbl_size += strlen(".shstrtab") + 1;
282 char *strtbl_content = malloc(1 + strlen(".shstrtab") + 1 + 304 char *strtbl_content = malloc(strtbl_size);
283 phnum * (strlen(".textXXXX") + 1)); 305 /* create NULL and shstrtab names */
284
285 strtbl_content[0] = '\0'; 306 strtbl_content[0] = '\0';
286 strcpy(&strtbl_content[1], ".shstrtab"); 307 strcpy(&strtbl_content[shstrtab_index], ".shstrtab");
287 uint32_t strtbl_index = 1 + strlen(".shstrtab") + 1;
288 308
289 uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize + 309 uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize +
290 ehdr.e_shnum * ehdr.e_shentsize; 310 ehdr.e_shnum * ehdr.e_shentsize;
@@ -294,7 +314,8 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
294 while(sec) 314 while(sec)
295 { 315 {
296 sec->offset += data_offset; 316 sec->offset += data_offset;
297 317 strcpy(&strtbl_content[sec->name_offset], sec->name);
318
298 phdr.p_type = PT_LOAD; 319 phdr.p_type = PT_LOAD;
299 if(sec->type == EST_LOAD) 320 if(sec->type == EST_LOAD)
300 phdr.p_offset = sec->offset; 321 phdr.p_offset = sec->offset;
@@ -336,21 +357,13 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
336 offset += sizeof(Elf32_Shdr); 357 offset += sizeof(Elf32_Shdr);
337 } 358 }
338 359
339 uint32_t text_idx = 0;
340 uint32_t bss_idx = 0;
341 while(sec) 360 while(sec)
342 { 361 {
343 shdr.sh_name = strtbl_index; 362 shdr.sh_name = sec->name_offset;
344 if(sec->type == EST_LOAD) 363 if(sec->type == EST_LOAD)
345 {
346 strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".text%d", text_idx++);
347 shdr.sh_type = SHT_PROGBITS; 364 shdr.sh_type = SHT_PROGBITS;
348 }
349 else 365 else
350 {
351 strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".bss%d", bss_idx++);
352 shdr.sh_type = SHT_NOBITS; 366 shdr.sh_type = SHT_NOBITS;
353 }
354 shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; 367 shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
355 shdr.sh_addr = sec->addr; 368 shdr.sh_addr = sec->addr;
356 shdr.sh_offset = sec->offset; 369 shdr.sh_offset = sec->offset;
@@ -367,12 +380,12 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
367 } 380 }
368 381
369 { 382 {
370 shdr.sh_name = 1; 383 shdr.sh_name = shstrtab_index;
371 shdr.sh_type = SHT_STRTAB; 384 shdr.sh_type = SHT_STRTAB;
372 shdr.sh_flags = 0; 385 shdr.sh_flags = 0;
373 shdr.sh_addr = 0; 386 shdr.sh_addr = 0;
374 shdr.sh_offset = strtbl_offset + data_offset; 387 shdr.sh_offset = strtbl_offset + data_offset;
375 shdr.sh_size = strtbl_index; 388 shdr.sh_size = strtbl_size;
376 shdr.sh_link = SHN_UNDEF; 389 shdr.sh_link = SHN_UNDEF;
377 shdr.sh_info = 0; 390 shdr.sh_info = 0;
378 shdr.sh_addralign = 1; 391 shdr.sh_addralign = 1;
@@ -391,7 +404,7 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
391 sec = sec->next; 404 sec = sec->next;
392 } 405 }
393 406
394 write(user, strtbl_offset + data_offset, strtbl_content, strtbl_index); 407 write(user, strtbl_offset + data_offset, strtbl_content, strtbl_size);
395 free(strtbl_content); 408 free(strtbl_content);
396} 409}
397 410
@@ -399,7 +412,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
399 elf_printf_fn_t printf, void *user) 412 elf_printf_fn_t printf, void *user)
400{ 413{
401 #define error_printf(...) ({printf(user, true, __VA_ARGS__); return false;}) 414 #define error_printf(...) ({printf(user, true, __VA_ARGS__); return false;})
402 415
403 /* read header */ 416 /* read header */
404 Elf32_Ehdr ehdr; 417 Elf32_Ehdr ehdr;
405 if(!read(user, 0, &ehdr, sizeof(ehdr))) 418 if(!read(user, 0, &ehdr, sizeof(ehdr)))
@@ -459,7 +472,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
459 void *data = xmalloc(shdr.sh_size); 472 void *data = xmalloc(shdr.sh_size);
460 if(!read(user, shdr.sh_offset, data, shdr.sh_size)) 473 if(!read(user, shdr.sh_offset, data, shdr.sh_size))
461 error_printf("error read self section data\n"); 474 error_printf("error read self section data\n");
462 elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data); 475 elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data, NULL);
463 free(data); 476 free(data);
464 477
465 if(strtab) 478 if(strtab)
@@ -476,7 +489,6 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
476 if(strtab) 489 if(strtab)
477 printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type); 490 printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type);
478 } 491 }
479
480 } 492 }
481 free(strtab); 493 free(strtab);
482 /* run through segments */ 494 /* run through segments */
@@ -562,6 +574,7 @@ void elf_release(struct elf_params_t *params)
562 struct elf_section_t *next_sec = sec->next; 574 struct elf_section_t *next_sec = sec->next;
563 if(sec->type == EST_LOAD) 575 if(sec->type == EST_LOAD)
564 free(sec->section); 576 free(sec->section);
577 free(sec->name);
565 free(sec); 578 free(sec);
566 sec = next_sec; 579 sec = next_sec;
567 } 580 }