diff options
author | eutarass | 2010-04-28 01:34:49 +0000 |
---|---|---|
committer | eutarass | 2010-04-28 01:34:49 +0000 |
commit | e31b89443a95816ab97062355d6bcc9af107f2c1 (patch) | |
tree | aa803197e941cf58a3952c86103ebb85629a1c89 | |
parent | f1017722bccf19a6510d84d10a86aa494822b18b (diff) | |
download | org.eclipse.tcf.agent-e31b89443a95816ab97062355d6bcc9af107f2c1.tar.gz org.eclipse.tcf.agent-e31b89443a95816ab97062355d6bcc9af107f2c1.tar.xz org.eclipse.tcf.agent-e31b89443a95816ab97062355d6bcc9af107f2c1.zip |
Bug 310607: C agent not correctly handling the endianness of the symbol table entries
-rw-r--r-- | services/dwarfcache.c | 125 | ||||
-rw-r--r-- | services/dwarfcache.h | 21 | ||||
-rw-r--r-- | services/symbols_elf.c | 119 |
3 files changed, 105 insertions, 160 deletions
diff --git a/services/dwarfcache.c b/services/dwarfcache.c index 4fbed9be..692d6564 100644 --- a/services/dwarfcache.c +++ b/services/dwarfcache.c @@ -37,7 +37,6 @@ static ELF_Section * sDebugSection; static DIO_UnitDescriptor sUnitDesc; static ObjectInfo * sObjectList; static ObjectInfo * sObjectListTail; -static unsigned sSymbolTableLen; static CompUnit * sCompUnit; static unsigned sCompUnitsMax; static ObjectInfo * sParentObject; @@ -45,7 +44,7 @@ static ObjectInfo * sPrevSibling; static int sCloseListenerOK = 0; -unsigned calc_symbol_name_hash(char * s) { +unsigned calc_symbol_name_hash(const char * s) { unsigned h = 0; while (*s) { unsigned g; @@ -57,24 +56,53 @@ unsigned calc_symbol_name_hash(char * s) { return h % SYM_HASH_SIZE; } -static U8_T get_elf_symbol_address(ElfX_Sym * x) { - if (sCache->mFile->elf64) { - Elf64_Sym * s = (Elf64_Sym *)x; - switch (ELF64_ST_TYPE(s->st_info)) { - case STT_OBJECT: - case STT_FUNC: - return s->st_value; - } +void unpack_elf_symbol_info(SymbolSection * section, U4_T index, SymbolInfo * info) { + memset(info, 0, sizeof(SymbolInfo)); + if (index >= section->mSymCount) exception(ERR_INV_FORMAT); + info->mSymSection = section; + if (section->mFile->elf64) { + Elf64_Sym s = ((Elf64_Sym *)section->mSymPool)[index]; + if (section->mFile->byte_swap) { + SWAP(s.st_name); + SWAP(s.st_shndx); + SWAP(s.st_size); + SWAP(s.st_value); + } + info->mSectionIndex = s.st_shndx; + if (s.st_shndx > 0 && s.st_shndx < section->mFile->section_cnt) { + info->mSection = section->mFile->sections + s.st_shndx; + } + if (s.st_name > 0) { + if (s.st_name >= section->mStrPoolSize) exception(ERR_INV_FORMAT); + info->mName = section->mStrPool + s.st_name; + } + info->mBind = ELF64_ST_BIND(s.st_info); + info->mType = ELF64_ST_TYPE(s.st_info); + info->mValue = s.st_value; + info->mSize = s.st_size; } else { - Elf32_Sym * s = (Elf32_Sym *)x; - switch (ELF32_ST_TYPE(s->st_info)) { - case STT_OBJECT: - case STT_FUNC: - return s->st_value; - } + Elf32_Sym s = ((Elf32_Sym *)section->mSymPool)[index]; + if (section->mFile->byte_swap) { + SWAP(s.st_name); + SWAP(s.st_shndx); + SWAP(s.st_size); + SWAP(s.st_value); + } + info->mSectionIndex = s.st_shndx; + if (s.st_shndx > 0 && s.st_shndx < section->mFile->section_cnt) { + info->mSection = section->mFile->sections + s.st_shndx; + } + if (s.st_name > 0) { + if (s.st_name >= section->mStrPoolSize) exception(ERR_INV_FORMAT); + info->mName = section->mStrPool + s.st_name; + } + info->mBind = ELF32_ST_BIND(s.st_info); + info->mType = ELF32_ST_TYPE(s.st_info); + info->mValue = s.st_value; + info->mSize = s.st_size; } - return 0; + } static CompUnit * find_comp_unit(U8_T ID) { @@ -302,17 +330,8 @@ static void entry_callback(U2_T Tag, U2_T Attr, U2_T Form) { } } -static int symbol_sort_func(const void * X, const void * Y) { - U8_T AddrX = get_elf_symbol_address(*(ElfX_Sym **)X); - U8_T AddrY = get_elf_symbol_address(*(ElfX_Sym **)Y); - if (AddrX < AddrY) return -1; - if (AddrX > AddrY) return +1; - return 0; -} - static void load_symbol_tables(void) { unsigned idx; - unsigned cnt = 0; ELF_File * File = sCache->mFile; unsigned sym_size = File->elf64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym); @@ -322,8 +341,6 @@ static void load_symbol_tables(void) { if (sym_sec->type == SHT_SYMTAB) { unsigned i; ELF_Section * str_sec; - U1_T * str_data = NULL; - U1_T * sym_data = NULL; SymbolSection * tbl = (SymbolSection *)loc_alloc_zero(sizeof(SymbolSection)); if (sCache->mSymSections == NULL) { sCache->mSymSectionsLen = 8; @@ -339,58 +356,27 @@ static void load_symbol_tables(void) { str_sec = File->sections + sym_sec->link; if (elf_load(sym_sec) < 0) exception(errno); if (elf_load(str_sec) < 0) exception(errno); - sym_data = (U1_T *)sym_sec->data; - str_data = (U1_T *)str_sec->data; tbl->mFile = File; - tbl->mStrPool = (char *)str_data; + tbl->mStrPool = (char *)str_sec->data; tbl->mStrPoolSize = (size_t)str_sec->size; - tbl->mSymPool = (ElfX_Sym *)sym_data; + tbl->mSymPool = (ElfX_Sym *)sym_sec->data; tbl->mSymPoolSize = (size_t)sym_sec->size; - tbl->sym_cnt = (unsigned)(sym_sec->size / sym_size); - tbl->mHashNext = (unsigned *)loc_alloc(tbl->sym_cnt * sizeof(unsigned)); - for (i = 0; i < tbl->sym_cnt; i++) { - U8_T Name = 0; - if (File->elf64) { - Elf64_Sym * s = (Elf64_Sym *)tbl->mSymPool + i; - if (get_elf_symbol_address((ElfX_Sym *)s) != 0) cnt++; - Name = s->st_name; - } - else { - Elf32_Sym * s = (Elf32_Sym *)tbl->mSymPool + i; - if (get_elf_symbol_address((ElfX_Sym *)s) != 0) cnt++; - Name = s->st_name; - } - assert(Name < tbl->mStrPoolSize); - if (Name == 0) { + tbl->mSymCount = (unsigned)(sym_sec->size / sym_size); + tbl->mHashNext = (unsigned *)loc_alloc(tbl->mSymCount * sizeof(unsigned)); + for (i = 0; i < tbl->mSymCount; i++) { + SymbolInfo sym; + unpack_elf_symbol_info(tbl, i, &sym); + if (sym.mName == NULL) { tbl->mHashNext[i] = 0; } else { - unsigned h = calc_symbol_name_hash(tbl->mStrPool + Name); + unsigned h = calc_symbol_name_hash(sym.mName); tbl->mHashNext[i] = tbl->mSymbolHash[h]; tbl->mSymbolHash[h] = i; } } } } - sCache->mSymbolHash = (ElfX_Sym **)loc_alloc(sizeof(void *) * cnt); - sCache->mSymbolTableLen = cnt; - cnt = 0; - for (idx = 0; idx < sCache->mSymSectionsCnt; idx++) { - SymbolSection * tbl = sCache->mSymSections[idx]; - unsigned i; - for (i = 0; i < tbl->sym_cnt; i++) { - if (File->elf64) { - ElfX_Sym * s = (ElfX_Sym *)((Elf64_Sym *)tbl->mSymPool + i); - if (get_elf_symbol_address(s) != 0) sCache->mSymbolHash[cnt++] = s; - } - else { - ElfX_Sym * s = (ElfX_Sym *)((Elf32_Sym *)tbl->mSymPool + i); - if (get_elf_symbol_address(s) != 0) sCache->mSymbolHash[cnt++] = s; - } - } - } - assert(sCache->mSymbolTableLen == cnt); - qsort(sCache->mSymbolHash, sCache->mSymbolTableLen, sizeof(ElfX_Sym *), symbol_sort_func); } static void load_debug_sections(void) { @@ -399,7 +385,6 @@ static void load_debug_sections(void) { ELF_File * File = sCache->mFile; memset(&trap, 0, sizeof(trap)); - sSymbolTableLen = sCache->mSymbolTableLen; sObjectList = NULL; sObjectListTail = NULL; sCompUnitsMax = 0; @@ -452,7 +437,6 @@ static void load_debug_sections(void) { sCache->mObjectHash = NULL; } sCache->mObjectList = sObjectList; - sSymbolTableLen = 0; sObjectList = NULL; sObjectListTail = NULL; sCompUnitsMax = 0; @@ -652,7 +636,6 @@ static void free_dwarf_cache(ELF_File * File) { loc_free(Info); } loc_free(Cache->mObjectHash); - loc_free(Cache->mSymbolHash); loc_free(Cache->mSymSections); loc_free(Cache); File->dwarf_dt_cache = NULL; diff --git a/services/dwarfcache.h b/services/dwarfcache.h index 73b5f54c..d854a7a2 100644 --- a/services/dwarfcache.h +++ b/services/dwarfcache.h @@ -34,6 +34,7 @@ typedef struct FileInfo FileInfo; typedef struct LocationInfo LocationInfo; typedef struct ObjectInfo ObjectInfo; +typedef struct SymbolInfo SymbolInfo; typedef struct PropertyValue PropertyValue; typedef struct LineNumbersState LineNumbersState; typedef struct CompUnit CompUnit; @@ -54,13 +55,24 @@ struct SymbolSection { unsigned mIndex; char * mStrPool; size_t mStrPoolSize; - unsigned sym_cnt; + unsigned mSymCount; ElfX_Sym * mSymPool; /* pointer to ELF section data: array of Elf32_Sym or Elf64_Sym */ size_t mSymPoolSize; unsigned mSymbolHash[SYM_HASH_SIZE]; unsigned * mHashNext; }; +struct SymbolInfo { + SymbolSection * mSymSection; + U4_T mSectionIndex; + ELF_Section * mSection; + char * mName; + U1_T mBind; + U1_T mType; + U8_T mValue; + U8_T mSize; +}; + #define TAG_fund_type 0x2000 struct ObjectInfo { @@ -158,15 +170,13 @@ struct DWARFCache { unsigned mSymSectionsLen; ObjectInfo ** mObjectHash; ObjectInfo * mObjectList; - ElfX_Sym ** mSymbolHash; - unsigned mSymbolTableLen; DWARFCache * mLineInfoNext; }; /* Return DWARF cache for given file, create and populate the cache if needed, throw an exception if error */ extern DWARFCache * get_dwarf_cache(ELF_File * file); -extern unsigned calc_symbol_name_hash(char * s); +extern unsigned calc_symbol_name_hash(const char * s); /* Load line number information for given compilation unit, throw an exception if error */ extern void load_line_numbers(DWARFCache * cache, CompUnit * unit); @@ -174,6 +184,9 @@ extern void load_line_numbers(DWARFCache * cache, CompUnit * unit); /* Find ObjectInfo by ID */ extern ObjectInfo * find_object(DWARFCache * cache, U8_T ID); +/* Get SymbolInfo */ +extern void unpack_elf_symbol_info(SymbolSection * section, U4_T index, SymbolInfo * info); + /* * Read and evaluate a property of a DWARF object, perform ELF relocations if any. * FORM_ADDR values are mapped to run-time address space. diff --git a/services/symbols_elf.c b/services/symbols_elf.c index 4214eecb..05f876fc 100644 --- a/services/symbols_elf.c +++ b/services/symbols_elf.c @@ -212,18 +212,14 @@ static int find_in_sym_table(DWARFCache * cache, char * name, Symbol ** res) { SymbolSection * tbl = cache->mSymSections[m]; unsigned n = tbl->mSymbolHash[h]; while (n) { - U8_T st_name = cache->mFile->elf64 ? - ((Elf64_Sym *)tbl->mSymPool + n)->st_name : - ((Elf32_Sym *)tbl->mSymPool + n)->st_name; - if (strcmp(name, tbl->mStrPool + st_name) == 0) { + SymbolInfo sym_info; + unpack_elf_symbol_info(tbl, n, &sym_info); + if (strcmp(name, sym_info.mName) == 0) { Context * ctx = sym_ctx; Symbol * sym = alloc_symbol(); - int st_type = cache->mFile->elf64 ? - ELF64_ST_TYPE(((Elf64_Sym *)tbl->mSymPool + n)->st_info) : - ELF32_ST_TYPE(((Elf32_Sym *)tbl->mSymPool + n)->st_info); while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent; sym->ctx = ctx; - switch (st_type) { + switch (sym_info.mType) { case STT_FUNC: sym->sym_class = SYM_CLASS_FUNCTION; break; @@ -658,8 +654,7 @@ static ObjectInfo * obj; static SymbolSection * tbl; static unsigned sym_index; static unsigned dimension; -static Elf32_Sym * sym32; -static Elf64_Sym * sym64; +static SymbolInfo * sym_info; static int unpack(const Symbol * sym) { assert(sym->base == NULL); @@ -671,8 +666,7 @@ static int unpack(const Symbol * sym) { tbl = sym->tbl; sym_index = sym->index; dimension = sym->dimension; - sym32 = NULL; - sym64 = NULL; + sym_info = NULL; if (obj != NULL) file = obj->mCompUnit->mFile; if (tbl != NULL) file = tbl->mFile; if (file != NULL) { @@ -682,12 +676,9 @@ static int unpack(const Symbol * sym) { return -1; } if (tbl != NULL) { - if (file->elf64) { - sym64 = (Elf64_Sym *)tbl->mSymPool + sym_index; - } - else { - sym32 = (Elf32_Sym *)tbl->mSymPool + sym_index; - } + static SymbolInfo info; + unpack_elf_symbol_info(tbl, sym_index, &info); + sym_info = &info; } } return 0; @@ -930,11 +921,8 @@ int get_symbol_name(const Symbol * sym, char ** name) { if (obj != NULL) { *name = obj->mName; } - else if (sym32 != NULL) { - *name = sym32->st_name == 0 ? NULL : tbl->mStrPool + sym32->st_name; - } - else if (sym64 != NULL) { - *name = sym64->st_name == 0 ? NULL : tbl->mStrPool + sym64->st_name; + else if (sym_info != NULL) { + *name = sym_info->mName; } else { *name = NULL; @@ -977,7 +965,7 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) { if (dimension == 0) ok = get_num_prop(obj, AT_byte_size, &sz); } if (!ok && obj->mTag == TAG_array_type) { - size_t length = 1; + U8_T length = 1; int i = dimension; ObjectInfo * idx = obj->mChildren; while (i > 0 && idx != NULL) { @@ -986,7 +974,7 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) { } if (idx == NULL) exception(ERR_INV_CONTEXT); while (idx != NULL) { - length *= (size_t)get_object_length(idx); + length *= get_object_length(idx); idx = idx->mSibling; } if (obj->mType == NULL) exception(ERR_INV_CONTEXT); @@ -999,14 +987,11 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) { } if (ok) sz *= length; } - if (ok) *size = (size_t)sz; + if (ok) *size = (ContextAddress)sz; clear_trap(&trap); } - else if (sym32 != NULL) { - *size = (size_t)sym32->st_size; - } - else if (sym64 != NULL) { - *size = (size_t)sym64->st_size; + else if (sym_info != NULL) { + *size = (ContextAddress)sym_info->mSize; } return 0; } @@ -1253,64 +1238,28 @@ int get_symbol_address(const Symbol * sym, ContextAddress * address) { return 0; } } - if (sym32 != NULL) { - switch (ELF32_ST_TYPE(sym32->st_info)) { - case STT_OBJECT: - case STT_FUNC: - { - U4_T x = sym32->st_value; - ELF_Section * sec = NULL; - if (file->type != ET_EXEC) { - switch (sym32->st_shndx) { - case SHN_ABS: - break; - case SHN_COMMON: - case SHN_UNDEF: - errno = ERR_INV_ADDRESS; - return -1; - default: - if (sym32->st_shndx >= file->section_cnt) { - errno = ERR_INV_ADDRESS; - return -1; - } - sec = file->sections + sym32->st_shndx; - x += (U4_T)sec->addr; - break; - } - } - *address = elf_map_to_run_time_address(sym_ctx, file, sec, (ContextAddress)x); - return 0; - } - } - } - if (sym64 != NULL) { - switch (ELF64_ST_TYPE(sym64->st_info)) { + if (sym_info != NULL) { + U8_T x = sym_info->mValue; + ELF_Section * sec = NULL; + switch (sym_info->mType) { case STT_OBJECT: case STT_FUNC: - { - U8_T x = sym64->st_value; - ELF_Section * sec = NULL; - if (file->type != ET_EXEC) { - switch (sym64->st_shndx) { - case SHN_ABS: - break; - case SHN_COMMON: - case SHN_UNDEF: - errno = ERR_INV_ADDRESS; - return -1; - default: - if (sym64->st_shndx >= file->section_cnt) { - errno = ERR_INV_ADDRESS; - return -1; - } - sec = file->sections + sym64->st_shndx; - x += (U4_T)sec->addr; - break; - } + if (file->type != ET_EXEC) { + switch (sym_info->mSectionIndex) { + case SHN_ABS: + break; + case SHN_COMMON: + case SHN_UNDEF: + errno = ERR_INV_ADDRESS; + return -1; + default: + sec = sym_info->mSection; + x += (U4_T)sec->addr; + break; } - *address = elf_map_to_run_time_address(sym_ctx, file, sec, (ContextAddress)x); - return 0; } + *address = elf_map_to_run_time_address(sym_ctx, file, sec, (ContextAddress)x); + return 0; } } |