John Leidel
unread,Mar 16, 2022, 10:54:57 AM3/16/22Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to RISC-V SW Dev
RV SW: We are in the process of porting some runtime code that
contains some dynamic symbol table magic that allows higher level
runtimes to overlay specific libc functionality using dynamically
loaded libraries. We're building/running on a RV64G platform running
Ubuntu 21.04 (just for reference) and GCC 10.3.0.
The code in question looks up the symbol table and strtab entries
using the `dl_phdr_info->phdr_info` structure. We appear to resolve
these fine. We then attempt to grab a reference to the DT_JMPREL
table using the same lookup method. We get what appears to be a valid
address back for DT_JMPREL from the loaded library. However, when we
attempt to walk the set of `r_info` blocks from the address specified
by DT_JMPREL, we start wandering off into bad memory. The library is
dynamically loaded with (RTLD_NOW | RTLD_LOCAL) enabled.
I'm curious whether the DT_JMPREL is resolving the correct address per
the RISC-V ELF spec. It should resolve to the address of relocation
entries associated solely with the PLT. DT_JMPREL is technically an
optional component, but it shows up in the ELF headers:
JMPREL 0x0000000000011ba8
The code is wrapped in a bunch of library specific functions, but I'll
try to paraphrase as follows. I know this is a rather obscure
question....
static uintptr_t
my_reloc_get_entry(ElfW(Addr) base, const ElfW(Phdr) *dphdr, ElfW(Sxword) tag)
{
ElfW(Dyn) *entry;
for (entry = (void*)(base + dphdr->p_vaddr); entry->d_tag != 0; ++entry) {
if (entry->d_tag == tag) {
return entry->d_un.d_val;
}
}
return 0;
}
static unsigned
my_dl_populate_symbols(ucm_dl_info_t *dl_info, uintptr_t dlpi_addr, void *table,
size_t table_size, void *strtab, ElfW(Sym) *symtab,
const char *dl_name)
{
ElfW(Rela) *reloc;
khiter_t khiter;
unsigned count;
char *elf_sym;
int ret;
count = 0;
for (reloc = table; (void*)reloc < UCS_PTR_BYTE_OFFSET(table, table_size);
++reloc) {
// the seg fault occurs below when trying to access r_info
elf_sym = (char*)strtab + symtab[ELF64_R_SYM(reloc->r_info)].st_name;
// the rest is omitted for brevity...
}
}
ElfW(Sym) *symtab = (void*)my_reloc_get_entry(dlpi_addr, dphdr, DT_SYMTAB);
void *strtab = (void*)my_reloc_get_entry(dlpi_addr, dphdr, DT_STRTAB);
void *jmprel = (void*)my_reloc_get_entry(dlpi_addr, dphdr, DT_JMPREL);
size_t pltrelsz = my_reloc_get_entry(dlpi_addr, dphdr, DT_PLTRELSZ);
unsigned num_symbols = my_dl_populate_symbols(dl_info, dlpi_addr, jmprel,
pltrelsz, strtab,
symtab, dl_name);