X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=ao-tools%2Flib%2Fao-elf.c;h=cc127b62a8a7e73515313dc4cce7d425c4d3a259;hb=3fd320ea38f2945f5611a09a0e48d16db467d105;hp=932dc85371b355a1e006f60c4011208c009e1cc2;hpb=95a8180f3d7929dbad65c80421f99c925f245af0;p=fw%2Faltos diff --git a/ao-tools/lib/ao-elf.c b/ao-tools/lib/ao-elf.c index 932dc853..cc127b62 100644 --- a/ao-tools/lib/ao-elf.c +++ b/ao-tools/lib/ao-elf.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,21 +28,26 @@ #include #include "ao-elf.h" #include "ao-hex.h" +#include "ao-verbose.h" /* * Look through the Elf file for symbols that can be adjusted before * the image is written to the device */ -static bool -find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols) +static struct ao_sym * +load_symbols (Elf *e, int *num_symbolsp) { Elf_Scn *scn; Elf_Data *symbol_data = NULL; GElf_Shdr shdr; GElf_Sym sym; - int i, symbol_count, s; + int i, symbol_count; char *symbol_name; size_t shstrndx; + struct ao_sym *symbols = NULL; + struct ao_sym *symbol; + int num_symbols = 0; + int size_symbols = 0; if (elf_getshdrstrndx(e, &shstrndx) < 0) return false; @@ -64,23 +70,46 @@ find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols) } if (!symbol_data) - return false; + return NULL; for (i = 0; i < symbol_count; i++) { gelf_getsym(symbol_data, i, &sym); symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name); + if (!symbol_name[0]) + continue; - for (s = 0; s < num_symbols; s++) - if (!strcmp (symbols[s].name, symbol_name)) { - symbols[s].addr = sym.st_value; - symbols[s].found = true; - } + if (num_symbols == size_symbols) { + struct ao_sym *new_symbols; + int new_size; + + if (!size_symbols) + new_size = 16; + else + new_size = size_symbols * 2; + new_symbols = realloc(symbols, new_size * sizeof (struct ao_sym)); + if (!new_symbols) + goto bail; + + symbols = new_symbols; + size_symbols = new_size; + } + symbol = &symbols[num_symbols]; + memset(symbol, 0, sizeof (struct ao_sym)); + symbol->name = strdup(symbol_name); + if (!symbol->name) + goto bail; + symbol->addr = sym.st_value; + ao_printf(AO_VERBOSE_EXE, "Add symbol %s: %08x\n", symbol->name, symbol->addr); + num_symbols++; } - for (s = 0; s < num_symbols; s++) - if (symbols[s].required && !symbols[s].found) - return false; - return true; + *num_symbolsp = num_symbols; + return symbols; +bail: + for (i = 0; i < num_symbols; i++) + free(symbols[i].name); + free(symbols); + return NULL; } static uint32_t @@ -157,6 +186,7 @@ load_write(struct ao_hex_image *from, uint32_t address, uint32_t length, void *d return new; } +#define DBG 0 /* * Construct a large in-memory block for all * of the loaded sections of the program @@ -173,10 +203,12 @@ get_load(Elf *e) GElf_Phdr phdr; GElf_Addr sh_paddr; struct ao_hex_image *load = NULL; +#if DBG char *section_name; +#endif size_t nshdr; size_t s; - + if (elf_getshdrstrndx(e, &shstrndx) < 0) return 0; @@ -200,41 +232,43 @@ get_load(Elf *e) /* Get the associated file section */ -#if 0 - printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", - (uint32_t) phdr.p_offset, - (uint32_t) phdr.p_vaddr, - (uint32_t) phdr.p_paddr, - (uint32_t) phdr.p_filesz, - (uint32_t) phdr.p_memsz); +#if DBG + fprintf (stderr, "offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", + (uint32_t) phdr.p_offset, + (uint32_t) phdr.p_vaddr, + (uint32_t) phdr.p_paddr, + (uint32_t) phdr.p_filesz, + (uint32_t) phdr.p_memsz); #endif - + for (s = 0; s < nshdr; s++) { scn = elf_getscn(e, s); if (!scn) { - printf ("getscn failed\n"); + fprintf (stderr, "getscn failed\n"); abort(); } if (gelf_getshdr(scn, &shdr) != &shdr) { - printf ("gelf_getshdr failed\n"); + fprintf (stderr, "gelf_getshdr failed\n"); abort(); } +#if DBG section_name = elf_strptr(e, shstrndx, shdr.sh_name); +#endif - if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) { - - if (shdr.sh_size == 0) - continue; - + if (shdr.sh_size != 0 && shdr.sh_type != SHT_NOBITS && (shdr.sh_flags & SHF_ALLOC) && + phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) + { sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset; - printf ("\tsize %08x rom %08x exec %08x %s\n", - (uint32_t) shdr.sh_size, - (uint32_t) sh_paddr, - (uint32_t) shdr.sh_addr, - section_name); +#if DBG + fprintf (stderr, "\tsize %08x rom %08x exec %08x %s\n", + (uint32_t) shdr.sh_size, + (uint32_t) sh_paddr, + (uint32_t) shdr.sh_addr, + section_name); +#endif data = elf_getdata(scn, NULL); @@ -252,7 +286,7 @@ get_load(Elf *e) */ struct ao_hex_image * -ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols) +ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols) { int fd; Elf *e; @@ -278,10 +312,8 @@ ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols) if (elf_getshdrstrndx(e, &shstrndx) != 0) return NULL; - if (!find_symbols(e, symbols, num_symbols)) { - fprintf (stderr, "Cannot find required symbols\n"); - return NULL; - } + if (symbols) + *symbols = load_symbols(e, num_symbols); image = get_load(e); if (!image) {