Skip to content

Commit

Permalink
libs/modlib.c: Set VMA for empty and unallocated sections
Browse files Browse the repository at this point in the history
This fixes issue where empty and unallocated sections are left without
a VMA. Some relocations depend on the section VMA being set even if there
is no data there, as the binary can refer to the symbols. Linker defined
symbols do not contain data -> they can produce empty sections.

This issue is seen when building a loadable file which declares _sctors /
_sdtors linker defined symbols for ctor/dtor sections which are empty.
crt0 references these symbols, so they need to be relocated, but the
section VMA is not set -> they go outside of the addressable range of the
user binary causing a potential crash.
  • Loading branch information
pussuw committed Oct 16, 2024
1 parent 2a99490 commit de35028
Showing 1 changed file with 38 additions and 7 deletions.
45 changes: 38 additions & 7 deletions libs/libc/modlib/modlib_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ static int modlib_section_alloc(FAR struct mod_loadinfo_s *loadinfo,
}
}

return 0;
return OK;
}
#endif

Expand Down Expand Up @@ -255,14 +255,47 @@ static int modlib_vma2lma(FAR struct mod_loadinfo_s *loadinfo,
shdr->sh_offset <= phdr->p_offset + phdr->p_filesz)
{
*lma = phdr->p_paddr + shdr->sh_addr - phdr->p_vaddr;
return 0;
return OK;
}
}

return -ENOENT;
}
#endif

/****************************************************************************
* Name: modlib_set_emptysect_vma
*
* Description:
* Set VMA for empty and unallocated sections, some relocations might
* depend on this.
*
* Returned Value:
* None.
*
****************************************************************************/

static void modlib_set_emptysect_vma(FAR struct mod_loadinfo_s *loadinfo,
int section)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[section];

/* Set the section as data or text, depending on SHF_WRITE */

if ((shdr->sh_flags & SHF_WRITE) != 0
#ifdef CONFIG_ARCH_HAVE_TEXT_HEAP_WORD_ALIGNED_READ
|| (shdr->sh_flags & SHF_EXECINSTR) == 0
#endif
)
{
shdr->sh_addr = loadinfo->datastart;
}
else
{
shdr->sh_addr = loadinfo->textalloc;
}
}

/****************************************************************************
* Name: modlib_loadfile
*
Expand Down Expand Up @@ -328,13 +361,11 @@ static inline int modlib_loadfile(FAR struct mod_loadinfo_s *loadinfo)
* execution
*/

if (shdr->sh_size == 0)
if ((shdr->sh_flags & SHF_ALLOC) == 0 || shdr->sh_size == 0)
{
continue;
}
/* Set the VMA regardless */

if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
modlib_set_emptysect_vma(loadinfo, i);
continue;
}

Expand Down

0 comments on commit de35028

Please sign in to comment.