Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2010-04-28 01:34:49 +0000
committereutarass2010-04-28 01:34:49 +0000
commite31b89443a95816ab97062355d6bcc9af107f2c1 (patch)
treeaa803197e941cf58a3952c86103ebb85629a1c89
parentf1017722bccf19a6510d84d10a86aa494822b18b (diff)
downloadorg.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.c125
-rw-r--r--services/dwarfcache.h21
-rw-r--r--services/symbols_elf.c119
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;
}
}

Back to the top