From ccb3592f51c9333b9332c59102c11eae61c973c0 Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Mon, 12 Aug 2013 11:31:57 +0100 Subject: [PATCH] elf: Redone the symbol loader Old symbol loader had been geared for the 'trace' functionality, and was partitularly bad since it didnt know the size of the code it was loading. New version loads a (sorted) array of symbols, and let the firmware loader code deal with the old 'codeline' array. The new loaded symbol table can be used separately (board code can look into it). Also changed the avr_symbol_t to inline the symbol name, instead of using a separate pointer. Signed-off-by: Michel Pollet --- simavr/sim/sim_avr.h | 2 +- simavr/sim/sim_elf.c | 68 ++++++++++++++++++++++++++------------------ simavr/sim/sim_elf.h | 4 +-- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index f391902..dde8873 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -298,8 +298,8 @@ typedef struct avr_kind_t { // a symbol loaded from the .elf file typedef struct avr_symbol_t { - const char * symbol; uint32_t addr; + const char symbol[0]; } avr_symbol_t; // locate the maker for mcu "name" and allocates a new avr instance diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index af4ab2d..37cd653 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -50,8 +50,23 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware) avr->avcc = firmware->avcc; if (firmware->aref) avr->aref = firmware->aref; -#if CONFIG_SIMAVR_TRACE - avr->trace_data->codeline = firmware->codeline; +#if CONFIG_SIMAVR_TRACE && ELF_SYMBOLS + int scount = firmware->flashsize >> 1; + avr->trace_data->codeline = malloc(scount * sizeof(avr_symbol_t*)); + memset(avr->trace_data->codeline, 0, scount * sizeof(avr_symbol_t*)); + + for (int i = 0; i < firmware->symbolcount; i++) + if (!(firmware->symbol[i]->addr >> 20)) // code address + avr->trace_data->codeline[firmware->symbol[i]->addr >> 1] = + firmware->symbol[i]; + // "spread" the pointers for known symbols forward + avr_symbol_t * last = NULL; + for (int i = 0; i < scount; i++) { + if (!avr->trace_data->codeline[i]) + avr->trace_data->codeline[i] = last; + else + last = avr->trace_data->codeline[i]; + } #endif avr_loadcode(avr, firmware->flash, firmware->flashsize, firmware->flashbase); @@ -199,11 +214,8 @@ int elf_read_firmware(const char * file, elf_firmware_t * firmware) memset(firmware, 0, sizeof(*firmware)); #if ELF_SYMBOLS - //int bitesize = ((avr->flashend+1) >> 1) * sizeof(avr_symbol_t); - firmware->codesize = 32768; - int bitesize = firmware->codesize * sizeof(avr_symbol_t); - firmware->codeline = malloc(bitesize); - memset(firmware->codeline,0, bitesize); + firmware->symbolcount = 0; + firmware->symbol = NULL; #endif /* this is actually mandatory !! otherwise elf_begin() fails */ @@ -254,37 +266,37 @@ int elf_read_firmware(const char * file, elf_firmware_t * firmware) gelf_getsym(edata, i, &sym); // print out the value and size - // printf("%08x %08d ", sym.st_value, sym.st_size); if (ELF32_ST_BIND(sym.st_info) == STB_GLOBAL || ELF32_ST_TYPE(sym.st_info) == STT_FUNC || ELF32_ST_TYPE(sym.st_info) == STT_OBJECT) { const char * name = elf_strptr(elf, shdr.sh_link, sym.st_name); - // type of symbol - if (sym.st_value & 0xfff00000) { - - } else { - // code - if (firmware->codeline[sym.st_value >> 1] == NULL) { - avr_symbol_t * s = firmware->codeline[sym.st_value >> 1] = malloc(sizeof(avr_symbol_t)); - s->symbol = strdup(name); - s->addr = sym.st_value; - } - } + avr_symbol_t * s = malloc(sizeof(avr_symbol_t) + strlen(name) + 1); + strcpy((char*)s->symbol, name); + s->addr = sym.st_value; + if (!(firmware->symbolcount % 8)) + firmware->symbol = realloc( + firmware->symbol, + (firmware->symbolcount + 8) * sizeof(firmware->symbol[0])); + + // insert new element, keep the array sorted + int insert = -1; + for (int si = 0; si < firmware->symbolcount && insert == -1; si++) + if (firmware->symbol[si]->addr >= s->addr) + insert = si; + if (insert == -1) + insert = firmware->symbolcount; + else + memmove(firmware->symbol + insert + 1, + firmware->symbol + insert, + (firmware->symbolcount - insert) * sizeof(firmware->symbol[0])); + firmware->symbol[insert] = s; + firmware->symbolcount++; } } } #endif } -#if ELF_SYMBOLS - avr_symbol_t * last = NULL; - for (int i = 0; i < firmware->codesize; i++) { - if (!firmware->codeline[i]) - firmware->codeline[i] = last; - else - last = firmware->codeline[i]; - } -#endif uint32_t offset = 0; firmware->flashsize = (data_text ? data_text->d_size : 0) + diff --git a/simavr/sim/sim_elf.h b/simavr/sim/sim_elf.h index ed760d5..d91b0e5 100644 --- a/simavr/sim/sim_elf.h +++ b/simavr/sim/sim_elf.h @@ -68,8 +68,8 @@ typedef struct elf_firmware_t { uint32_t eesize; #if ELF_SYMBOLS - avr_symbol_t ** codeline; - uint32_t codesize; // in elements + avr_symbol_t ** symbol; + uint32_t symbolcount; #endif } elf_firmware_t ; -- 2.39.5