mirror of
https://github.com/apache/nuttx.git
synced 2026-10-03 20:27:53 +00:00
libs/libc/elf: Read the dynamic relocations at their file offset.
DT_REL and DT_JMPREL hold the link-time address of their table, and the loader read the table at that value as a file offset. The two are equal only when the segment that holds it starts at file offset 0. An object linked with its text at file offset 0x1000, as the tree's gnu-elf.ld does, had its relocations read from padding, so none were applied and the module called through unrelocated pointers. Translate the address through the PT_LOAD headers first. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
parent
ec78241ebe
commit
4db7594eb6
1 changed files with 32 additions and 2 deletions
|
|
@ -643,6 +643,34 @@ static int libelf_relocateadd(FAR struct module_s *modp,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: libelf_fileoff
|
||||
*
|
||||
* Description:
|
||||
* Translate a link-time address named by a dynamic tag into its offset in
|
||||
* the file. They are the same only when its segment starts at offset 0.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static off_t libelf_fileoff(FAR struct mod_loadinfo_s *loadinfo,
|
||||
uintptr_t vaddr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; loadinfo->phdr != NULL && i < loadinfo->ehdr.e_phnum; i++)
|
||||
{
|
||||
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
|
||||
|
||||
if (phdr->p_type == PT_LOAD && vaddr >= phdr->p_vaddr &&
|
||||
vaddr - phdr->p_vaddr < phdr->p_filesz)
|
||||
{
|
||||
return phdr->p_offset + (vaddr - phdr->p_vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: libelf_relocatedyn
|
||||
*
|
||||
|
|
@ -714,7 +742,8 @@ static int libelf_relocatedyn(FAR struct module_s *modp,
|
|||
switch (dyn[i].d_tag)
|
||||
{
|
||||
case DT_REL:
|
||||
reldata.reloff[I_REL] = dyn[i].d_un.d_val;
|
||||
reldata.reloff[I_REL] = libelf_fileoff(loadinfo,
|
||||
dyn[i].d_un.d_ptr);
|
||||
break;
|
||||
case DT_RELSZ:
|
||||
reldata.relsz[I_REL] = dyn[i].d_un.d_val;
|
||||
|
|
@ -729,7 +758,8 @@ static int libelf_relocatedyn(FAR struct module_s *modp,
|
|||
reldata.stroff = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_JMPREL:
|
||||
reldata.reloff[I_PLT] = dyn[i].d_un.d_val;
|
||||
reldata.reloff[I_PLT] = libelf_fileoff(loadinfo,
|
||||
dyn[i].d_un.d_ptr);
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
reldata.relsz[I_PLT] = dyn[i].d_un.d_val;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue