Commit 33252803 authored by Micha Müller's avatar Micha Müller
Browse files

Caliper-service rework WIP4

-fixed symbol address calculation
parent 1d7cb19a
......@@ -171,11 +171,13 @@ private:
const uintptr_t offset,
fsym_data*& dest_ptr,
Channel* chn) {
Elf *elf;
Elf_Scn *scn = NULL;
GElf_Shdr shdr;
Elf_Data *data;
int fd;
Elf *elf;
Elf_Scn *scn = NULL;
GElf_Ehdr ehdr;
GElf_Shdr shdr;
Elf_Data *data;
int fd;
uintptr_t sym_offset;
elf_version(EV_CURRENT);
......@@ -188,6 +190,10 @@ private:
//search ELF header for symbol table
elf = elf_begin(fd, ELF_C_READ, NULL);
gelf_getehdr(elf, &ehdr);
sym_offset = (ehdr.e_type == ET_DYN ? (start_addr - offset) : 0);
while ((scn = elf_nextscn(elf, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
if (shdr.sh_type == SHT_SYMTAB) {
......@@ -202,9 +208,9 @@ private:
return 0;
}
//retrieve symbol data
size_t entryCnt = 0;
int count = shdr.sh_size / (shdr.sh_entsize ?: 1);
/* print the symbol names */
for (int ii = 0; ii < count; ++ii) {
GElf_Sym sym;
......@@ -213,79 +219,62 @@ private:
// Log(1).stream() << chn->name() << ": DcdbPusher: Got no symbol" << std::endl;
// continue;
//}
if (sym.st_info == STT_FUNC) {
char* symstr;
char* dsymstr;
int status = -1;
fsym_data symdat;
//TODO sym.st_name == STN_UNDEF?
symstr = elf_strptr(elf, shdr.sh_link, sym.st_name);
/* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
if (symstr[0] == '_' && symstr[1] == 'Z') {
dsymstr = abi::__cxa_demangle(symstr, NULL, NULL, &status);
}
if (status == 0) {
strncpy(symdat.name, dsymstr, 512);
free((void*) dsymstr);
} else {
strncpy(symdat.name, symstr, 512);
}
symdat.name[511] = '\0';
//TODO calculated symbol addresses must be wrong...
//see example: https://wiki.osdev.org/ELF_Tutorial#Accessing_the_Value_of_a_Symbol
if (sym.st_shndx == SHN_UNDEF) {
//external symbol
//look up should not be necessary as we also parse all other
//mapped files...
continue;
} else if (sym.st_shndx == SHN_ABS) {
//absolute symbol
symdat.start_addr = sym.st_value;
} else {
//internally defined symbol
Elf_Scn *tmp_scn;
GElf_Shdr tmp_shdr;
tmp_scn = elf_getscn(elf, sym.st_shndx);
//debug
if (tmp_scn == NULL) {
printf("Symbol %s has invalid section!\n", symdat.name);
continue;
}
gelf_getshdr(tmp_scn, &tmp_shdr);
//debug
// printf("Symbol %s: start %llx; sh_offset %llx; value %llx)\n", symdat.name,
// (start_addr-offset),
// tmp_shdr.sh_offset,
// sym.st_value);
symdat.start_addr = (start_addr - offset) + tmp_shdr.sh_offset + sym.st_value;
}
symdat.end_addr = symdat.start_addr + sym.st_size;
//only interested in symbols related to executable code
if (sym.st_info != STT_FUNC) {
continue;
}
//resolve symbol name
char* symstr;
char* dsymstr;
int status = -1;
fsym_data symdat;
if (symdat.start_addr >= start_addr &&
symdat.start_addr <= end_addr) {
//TODO sym.st_name == STN_UNDEF?
symstr = elf_strptr(elf, shdr.sh_link, sym.st_name);
//debug
/* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */
if (symstr[0] == '_' && symstr[1] == 'Z') {
dsymstr = abi::__cxa_demangle(symstr, NULL, NULL, &status);
}
if (status == 0) {
strncpy(symdat.name, dsymstr, 512);
free((void*) dsymstr);
} else {
strncpy(symdat.name, symstr, 512);
}
symdat.name[511] = '\0';
//resolve symbol value aka its address in this' process virtual memory
if (sym.st_shndx == SHN_UNDEF || sym.st_shndx == SHN_ABS) {
//external or absolute symbol
//are usually not encountered for sym.st_info == STT_FUNC
continue;
} else {
//internally defined symbol
symdat.start_addr = sym_offset + sym.st_value;
}
symdat.end_addr = symdat.start_addr + sym.st_size - 1;
if (symdat.start_addr >= start_addr &&
symdat.start_addr <= end_addr) {
//debug
// printf("Symbol %s in mem range (%llx-%llx, size %llx)\n", symdat.name,
// symdat.start_addr,
// symdat.end_addr,
// sym.st_size);
memcpy(dest_ptr, &symdat, sizeof(addr_data));
++dest_ptr;
++entryCnt;
} else {
memcpy(dest_ptr, &symdat, sizeof(addr_data));
++dest_ptr;
++entryCnt;
} else {
// printf("Symbol %s out of mem range (%llx-%llx, size %llx)\n", symdat.name,
// symdat.start_addr,
// symdat.end_addr,
// sym.st_size);
}
}
}
......@@ -360,7 +349,6 @@ private:
size_t fsym_offset = addr_cnt * sizeof(addr_data);
addr_ptr = addr_start;
//TODO replace '/' with something unambiguous
for(size_t i = 0; i < addr_cnt; ++i) {
addr_ptr->fsym_offset = fsym_offset;
if (addr_ptr->pathname[0] == '/') {
......@@ -374,6 +362,14 @@ private:
chn);
fsym_offset += addr_ptr->fsym_count * sizeof(fsym_data);
}
//forward slashes are reserved for MQTT topics, use double colon instead
for (char* i = addr_ptr->pathname; *i != '\0'; ++i) {
if (*i == '/') {
*i = ':';
}
}
fsym_offset -= sizeof(addr_data);
++addr_ptr;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment