binfmt: ELF support load to LMA
Load all sections to LMA not VMA, so the startup code(e.g. start.S) need relocate .data section to the final address(VMA) and zero .bss section by self. For example, SiFli and Actions: Background: Device with small sram, Bootloader run in sram and psram, need boot to Application, with memory overlap and without XIP. VMA of .data is in "psram" and LMA in "rom", if not enable `ELF_LOADTO_LMA`, ELF loader will load the section to VMA (will fill bootloader itself). Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
parent
d7359bf076
commit
c749e4bfbd
17
binfmt/elf.c
17
binfmt/elf.c
@ -142,6 +142,23 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo)
|
||||
binfo(" e_shnum: %d\n", loadinfo->ehdr.e_shnum);
|
||||
binfo(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx);
|
||||
|
||||
if (loadinfo->phdr && loadinfo->ehdr.e_phnum > 0)
|
||||
{
|
||||
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
|
||||
{
|
||||
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
|
||||
binfo("Programs %d:\n", i);
|
||||
binfo(" p_type: %08jx\n", (uintmax_t)phdr->p_type);
|
||||
binfo(" p_offset: %08jx\n", (uintmax_t)phdr->p_offset);
|
||||
binfo(" p_vaddr: %08jx\n", (uintmax_t)phdr->p_vaddr);
|
||||
binfo(" p_paddr: %08jx\n", (uintmax_t)phdr->p_paddr);
|
||||
binfo(" p_filesz: %08jx\n", (uintmax_t)phdr->p_filesz);
|
||||
binfo(" p_memsz: %08jx\n", (uintmax_t)phdr->p_memsz);
|
||||
binfo(" p_flags: %08jx\n", (uintmax_t)phdr->p_flags);
|
||||
binfo(" p_align: %08x\n", phdr->p_align);
|
||||
}
|
||||
}
|
||||
|
||||
if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0)
|
||||
{
|
||||
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
||||
|
@ -73,3 +73,11 @@ config ELF_COREDUMP
|
||||
The memory state embeds a snapshot of all segments mapped in the
|
||||
memory space of the program. The CPU state contains register values
|
||||
when the core dump has been generated.
|
||||
|
||||
config ELF_LOADTO_LMA
|
||||
bool "ELF load sections to LMA"
|
||||
default n
|
||||
---help---
|
||||
Load all section to LMA not VMA, so the startup code(e.g. start.S) need
|
||||
relocate .data section to the final address(VMA) and zero .bss section
|
||||
by self.
|
||||
|
@ -65,6 +65,20 @@ int elf_verifyheader(FAR const Elf_Ehdr *header);
|
||||
int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer,
|
||||
size_t readsize, off_t offset);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: elf_loadphdrs
|
||||
*
|
||||
* Description:
|
||||
* Loads program headers into memory.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 (OK) is returned on success and a negated errno is returned on
|
||||
* failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int elf_loadphdrs(FAR struct elf_loadinfo_s *loadinfo);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: elf_loadshdrs
|
||||
*
|
||||
|
@ -123,6 +123,41 @@ static void elf_elfsize(FAR struct elf_loadinfo_s *loadinfo)
|
||||
loadinfo->datasize = datasize;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ELF_LOADTO_LMA
|
||||
/****************************************************************************
|
||||
* Name: elf_vma2lma
|
||||
*
|
||||
* Description:
|
||||
* Convert section`s VMA to LMA according to PhysAddr(p_paddr) of
|
||||
* Program Header.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 (OK) is returned on success and a negated errno is returned on
|
||||
* failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int elf_vma2lma(FAR struct elf_loadinfo_s *loadinfo,
|
||||
FAR Elf_Shdr *shdr, FAR Elf_Addr *lma)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
|
||||
{
|
||||
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
|
||||
|
||||
if (shdr->sh_addr >= phdr->p_vaddr &&
|
||||
shdr->sh_addr < phdr->p_vaddr + phdr->p_memsz)
|
||||
{
|
||||
*lma = phdr->p_paddr + shdr->sh_addr - phdr->p_vaddr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: elf_loadfile
|
||||
*
|
||||
@ -178,9 +213,20 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
{
|
||||
if (shdr->sh_type != SHT_NOBITS)
|
||||
{
|
||||
Elf_Addr addr = shdr->sh_addr;
|
||||
|
||||
#ifdef CONFIG_ELF_LOADTO_LMA
|
||||
ret = elf_vma2lma(loadinfo, shdr, &addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
berr("ERROR: Failed to convert addr %d: %d\n", i, ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read the section data from sh_offset to specified region */
|
||||
|
||||
ret = elf_read(loadinfo, (FAR uint8_t *)shdr->sh_addr,
|
||||
ret = elf_read(loadinfo, (FAR uint8_t *)addr,
|
||||
shdr->sh_size, shdr->sh_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -189,6 +235,7 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ELF_LOADTO_LMA
|
||||
/* If there is no data in an allocated section, then the
|
||||
* allocated section must be cleared.
|
||||
*/
|
||||
@ -197,6 +244,7 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
||||
{
|
||||
memset((FAR uint8_t *)shdr->sh_addr, 0, shdr->sh_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -284,6 +332,15 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
|
||||
binfo("loadinfo: %p\n", loadinfo);
|
||||
DEBUGASSERT(loadinfo && loadinfo->file.f_inode);
|
||||
|
||||
/* Load program headers into memory */
|
||||
|
||||
ret = elf_loadphdrs(loadinfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
berr("ERROR: elf_loadphdrs failed: %d\n", ret);
|
||||
goto errout_with_buffers;
|
||||
}
|
||||
|
||||
/* Load section headers into memory */
|
||||
|
||||
ret = elf_loadshdrs(loadinfo);
|
||||
|
@ -165,6 +165,65 @@ static inline int elf_sectname(FAR struct elf_loadinfo_s *loadinfo,
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: elf_loadphdrs
|
||||
*
|
||||
* Description:
|
||||
* Loads program headers into memory.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 (OK) is returned on success and a negated errno is returned on
|
||||
* failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int elf_loadphdrs(FAR struct elf_loadinfo_s *loadinfo)
|
||||
{
|
||||
size_t phdrsize;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(loadinfo->phdr == NULL);
|
||||
|
||||
/* Verify that there are programs */
|
||||
|
||||
if (loadinfo->ehdr.e_phnum < 1)
|
||||
{
|
||||
berr("No programs(?)\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the total size of the program header table */
|
||||
|
||||
phdrsize = (size_t)loadinfo->ehdr.e_phentsize *
|
||||
(size_t)loadinfo->ehdr.e_phnum;
|
||||
if (loadinfo->ehdr.e_phoff + phdrsize > loadinfo->filelen)
|
||||
{
|
||||
berr("Insufficient space in file for program header table\n");
|
||||
return -ESPIPE;
|
||||
}
|
||||
|
||||
/* Allocate memory to hold a working copy of the program header table */
|
||||
|
||||
loadinfo->phdr = (FAR FAR Elf_Phdr *)kmm_malloc(phdrsize);
|
||||
if (!loadinfo->phdr)
|
||||
{
|
||||
berr("Failed to allocate the program header table. Size: %ld\n",
|
||||
(long)phdrsize);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Read the program header table into memory */
|
||||
|
||||
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->phdr, phdrsize,
|
||||
loadinfo->ehdr.e_phoff);
|
||||
if (ret < 0)
|
||||
{
|
||||
berr("Failed to read program header table: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: elf_loadshdrs
|
||||
*
|
||||
|
@ -94,6 +94,12 @@ int elf_freebuffers(FAR struct elf_loadinfo_s *loadinfo)
|
||||
{
|
||||
/* Release all working allocations */
|
||||
|
||||
if (loadinfo->phdr)
|
||||
{
|
||||
kmm_free((FAR void *)loadinfo->phdr);
|
||||
loadinfo->phdr = NULL;
|
||||
}
|
||||
|
||||
if (loadinfo->shdr)
|
||||
{
|
||||
kmm_free(loadinfo->shdr);
|
||||
|
@ -91,6 +91,7 @@ struct elf_loadinfo_s
|
||||
int filemode; /* Mode of the file system */
|
||||
|
||||
Elf_Ehdr ehdr; /* Buffered ELF file header */
|
||||
FAR Elf_Phdr *phdr; /* Buffered ELF program headers */
|
||||
FAR Elf_Shdr *shdr; /* Buffered ELF section headers */
|
||||
uint8_t *iobuffer; /* File I/O buffer */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user