I was wondering if anyone can think of a reason how a read from a pointer could cause a segmentation when the pointer is: 1. non NULL pointer.
The thing I'm trying to do is walk the shared library and access their symbol table. The segmentation happens when I try to access the ELF hash table to get the amount of symbols within the symbol table.
This is not noticed in x86 platform. It happens only when executing on MIPS64 platform.
The code are based on from this link: How to interpret the dynamic symbol table in an ELF executable?
static void
btrace_dl_symtab_walk(struct dl_phdr_info *info,
btrace_dl_lib_t *ctx) {
ElfW(Dyn*) dyn;
ElfW(Sym*) sym = NULL;
ElfW(Word*) hash;
ElfW(Word) sym_cnt = 0;
char* strtab = NULL;
char* sym_name = NULL;
unsigned int i;
int j;
/*
* Make indicator to show all of them acomplished before going forward
*/
for (j = 0; j < info->dlpi_phnum; j++) {
if (info->dlpi_phdr[j].p_type == PT_DYNAMIC) {
dyn = (ElfW(Dyn)*)(info->dlpi_addr + info->dlpi_phdr[j].p_vaddr);
while(dyn->d_tag != DT_NULL) {
if (dyn->d_tag == DT_HASH) {
hash = (ElfW(Word*))dyn->d_un.d_ptr;
if (!hash) {
return;
}
/*
* SEGFAULT happens here
*/
printf("Before Seg Fault\n");
sym_cnt = *(hash + 1); //<=============== This line causes seg fault
printf("Never reached here\n");
} else if(dyn->d_tag == DT_GNU_HASH) {
/*
* Since there is no simply way to find entry count
* in GNU hash table, we have no choice but to
* count by hand
*/
uint32_t *buckets;
uint32_t *hashval;
hash = (ElfW(Word*))dyn->d_un.d_ptr;
buckets = hash + 4 + (hash[2]*sizeof(size_t)/4);
for (i = sym_cnt = 0; i < hash[0]; i++) {
if (buckets[i] > sym_cnt) {
sym_cnt = buckets[i];
}
}
if (sym_cnt) {
sym_cnt -= hash[1];
hashval = buckets + hash[0] + sym_cnt;
do {
sym_cnt++;
} while (!(*hashval++ & 1));
}
sym_cnt += hash[1];
}else if (dyn->d_tag == DT_STRTAB) {
strtab = (char*)dyn->d_un.d_ptr;
} else if (dyn->d_tag == DT_SYMTAB) {
sym = (ElfW(Sym*))dyn->d_un.d_ptr;
break;
}
dyn++;
}
break;
}
}
// Other acitivities
}
Any guidance are welcome. Thank you