mirror of
https://github.com/apache/nuttx.git
synced 2026-09-09 18:36:37 +00:00
libs/libc/elf: Place an FDPIC object's segments independently.
An ET_DYN object is loaded into one allocation with its data behind its text, because its data references sit at a fixed distance from the code that makes them. An FDPIC object does not work that way: it reaches its data through a base register, so the two segments can be placed wherever suits, and the point of the format is that the read-only one is left on the media and executed there while only the writable one is copied. One copy of the text then serves every instance. So libelf_load() grows a second case. The object announces itself in the OS/ABI byte, which is noted once in libelf_loadhdrs() rather than re-derived; e_flags cannot be used for this, as an FDPIC object's are an unremarkable EABI version and testing them would reject every valid module. Text is taken from the media address plus the segment's own file offset -- the same arithmetic the ET_REL path already does with sh_offset -- and libelf_loadfile() does not read it. If the filesystem cannot show its media, the loader copies the text to RAM instead. The module then loses the shared text and the flash saving, but it runs. Obtaining that address needs two mechanisms, and they are not interchangeable. A compacting filesystem can move a file's blocks, so it hands out an address only with a pin that holds them still and expects the pin back; xipfs is the one in tree. A filesystem whose layout never changes has nothing to hold and answers FIOC_XIPBASE with a bare address; romfs and tmpfs are those. libelf_xipacquire() asks for the pin first, because a filesystem that needs one is not safe without it, and libelf_unload() gives it back. The loader asks for a pin only if it can hold one, or the pin would stay for ever. The pin is thus not specific to FDPIC. Any module that executes in place from a compacting filesystem takes one, and gives it back at unload. mmap() is not used, though both filesystems implement it. The mapping would be recorded against whichever task called the loader, while the release happens when the module's own task exits, which is a different group -- so the pin would outlive the module and the extent would never become movable again. Unloading has to change with placement: the existing path frees only textalloc because ET_DYN had a single allocation, which would leak an FDPIC object's data and free media the filesystem only lent us. Nothing here runs for a non-FDPIC object; every branch is behind the flag and the single-allocation path is untouched. Built and booted mps3-an547:picostest, which is CONFIG_ELF with CONFIG_PIC, with no change in behaviour. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
parent
9f1107862b
commit
1aa32bbc07
10 changed files with 342 additions and 25 deletions
|
|
@ -41,6 +41,11 @@
|
|||
|
||||
#define EM_ARCH EM_ARM
|
||||
|
||||
/* An object built for the FDPIC ABI says so in the OS/ABI byte. */
|
||||
|
||||
#define ELF_IS_FDPIC(ehdr) \
|
||||
((ehdr)->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC)
|
||||
|
||||
/* Table 4-2, ARM-specific e_flags */
|
||||
|
||||
#define EF_ARM_EABI_MASK 0xff000000
|
||||
|
|
@ -206,6 +211,18 @@
|
|||
#define R_ARM_THM_TLS_DESCSEQ16 129 /* Thumb16 */
|
||||
#define R_ARM_THM_TLS_DESCSEQ32 130 /* Thumb32 */
|
||||
|
||||
/* FDPIC relocations. Values from the ARM FDPIC ABI as implemented by
|
||||
* binutils (include/elf/arm.h).
|
||||
*/
|
||||
|
||||
#define R_ARM_GOTFUNCDESC 161 /* Data GOT entry holding a descriptor */
|
||||
#define R_ARM_GOTOFFFUNCDESC 162 /* Data GOT-relative descriptor */
|
||||
#define R_ARM_FUNCDESC 163 /* Data Address of a descriptor */
|
||||
#define R_ARM_FUNCDESC_VALUE 164 /* Data The descriptor itself: {code, GOT} */
|
||||
#define R_ARM_TLS_GD32_FDPIC 165 /* Data */
|
||||
#define R_ARM_TLS_LDM32_FDPIC 166 /* Data */
|
||||
#define R_ARM_TLS_IE32_FDPIC 167 /* Data */
|
||||
|
||||
/* Processor specific values for the Phdr p_type field. */
|
||||
|
||||
#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */
|
||||
|
|
|
|||
11
fs/Kconfig
11
fs/Kconfig
|
|
@ -94,6 +94,17 @@ config PSEUDOFS_ATTRIBUTES
|
|||
Enable support for attributes(e.g. mode, uid, gid and time)
|
||||
in the pseudo file system.
|
||||
|
||||
config FS_PIN
|
||||
bool
|
||||
default n
|
||||
---help---
|
||||
Selected by a file system that can pin a file's blocks in place and
|
||||
hand out their media address, so that a module's read-only segment
|
||||
can be executed where it already lies instead of being copied.
|
||||
|
||||
The pin is held for as long as the module is loaded and given back
|
||||
when it is unloaded.
|
||||
|
||||
config FS_PERMISSION
|
||||
bool "Enable UNIX Filesystem Permission Support"
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ config FS_XIPFS
|
|||
bool "XIPFS contiguous execute-in-place file system"
|
||||
default n
|
||||
depends on !DISABLE_MOUNTPOINT && MTD
|
||||
select FS_PIN
|
||||
---help---
|
||||
Enable support for XIPFS, a file system that stores each file as a
|
||||
single physically contiguous, erase-block aligned extent on memory
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@
|
|||
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
|
||||
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
|
||||
#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
|
||||
#define ELFOSABI_ARM_FDPIC 65 /* ARM FDPIC */
|
||||
#define ELFOSABI_ARM 97 /* ARM */
|
||||
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@
|
|||
|
||||
#define ELF_PRARGSZ (80) /* Number of chars for args */
|
||||
|
||||
/* An architecture that has no FDPIC ABI recognises no FDPIC object. */
|
||||
|
||||
#ifndef ELF_IS_FDPIC
|
||||
# define ELF_IS_FDPIC(ehdr) false
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -44,6 +44,19 @@
|
|||
# define CONFIG_LIBC_ELF_MAXDEPEND 0
|
||||
#endif
|
||||
|
||||
/* A compacting filesystem gives its media address with a pin that holds the
|
||||
* blocks in place. The loader holds the pin through a file reference,
|
||||
* because the unload runs on another task.
|
||||
*
|
||||
* That reference is taken with file_get() and file_dup2(), which are kernel
|
||||
* side, so this is for the copy of libc that runs there.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_FS_PIN) && \
|
||||
(defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__))
|
||||
# define HAVE_LIBC_ELF_PIN 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_LIBC_ELF_ALIGN_LOG2
|
||||
# define CONFIG_LIBC_ELF_ALIGN_LOG2 2
|
||||
#endif
|
||||
|
|
@ -123,6 +136,7 @@ typedef CODE int (*mod_uninitializer_t)(FAR void *arg);
|
|||
* nexports - The number of symbols in the exported symbol table.
|
||||
*/
|
||||
|
||||
struct file;
|
||||
struct symtab_s;
|
||||
struct mod_info_s
|
||||
{
|
||||
|
|
@ -252,6 +266,16 @@ struct mod_loadinfo_s
|
|||
* skip the copy.
|
||||
*/
|
||||
|
||||
/* True if e_ident[EI_OSABI] marked this an FDPIC object. */
|
||||
|
||||
bool fdpic;
|
||||
|
||||
#ifdef HAVE_LIBC_ELF_PIN
|
||||
/* The file the pin is held through, handed to the module once it loads. */
|
||||
|
||||
FAR struct file *pinfile;
|
||||
#endif
|
||||
|
||||
/* Address environment.
|
||||
*
|
||||
* addrenv - This is the handle created by addrenv_allocate() that can be
|
||||
|
|
|
|||
|
|
@ -349,4 +349,26 @@ int libelf_addrenv_restore(FAR struct mod_loadinfo_s *loadinfo);
|
|||
void libelf_addrenv_free(FAR struct mod_loadinfo_s *loadinfo);
|
||||
|
||||
#endif /* CONFIG_ARCH_ADDRENV */
|
||||
|
||||
#ifdef HAVE_LIBC_ELF_PIN
|
||||
|
||||
/****************************************************************************
|
||||
* Name: libelf_pinrelease
|
||||
*
|
||||
* Description:
|
||||
* Give back an XIP pin that the loader took, and the file that holds it.
|
||||
* Does nothing if the loader took no pin.
|
||||
*
|
||||
* Input Parameters:
|
||||
* pinfile - The held file. Cleared on return.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void libelf_pinrelease(FAR struct file **pinfile);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __LIBS_LIBC_LIBC_ELF_LIBC_ELF_H */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/lib/elf.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
#include "libc.h"
|
||||
|
|
@ -364,6 +366,13 @@ static inline int libelf_loadfile(FAR struct mod_loadinfo_s *loadinfo)
|
|||
{
|
||||
if (phdr->p_flags & PF_X)
|
||||
{
|
||||
if (loadinfo->fdpic && loadinfo->xipbase != 0)
|
||||
{
|
||||
/* Mapped, not copied. */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = libelf_read(loadinfo, buffer_data_address(text),
|
||||
phdr->p_filesz,
|
||||
phdr->p_offset);
|
||||
|
|
@ -539,10 +548,113 @@ skipload:
|
|||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: libelf_xipacquire
|
||||
*
|
||||
* Description:
|
||||
* Ask the filesystem for the address of this file on its media, so the
|
||||
* read-only part of the object can run where it lies. Ask for a pin
|
||||
* first: a compacting filesystem is not safe without one. Do not ask at
|
||||
* all if this build cannot hold a pin.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero if an address was obtained, a negated errno otherwise. Callers
|
||||
* that can live without one may ignore the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_LIBC_ELF_PIN
|
||||
static int libelf_pinhold(FAR struct mod_loadinfo_s *loadinfo)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
int ret;
|
||||
|
||||
/* The descriptor belongs to the task that called the loader, and the
|
||||
* unload runs on another task. Hold the file instead.
|
||||
*/
|
||||
|
||||
loadinfo->pinfile = lib_zalloc(sizeof(struct file));
|
||||
if (loadinfo->pinfile == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = file_get(loadinfo->filfd, &filep);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = file_dup2(filep, loadinfo->pinfile);
|
||||
file_put(filep);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
lib_free(loadinfo->pinfile);
|
||||
loadinfo->pinfile = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int libelf_xipacquire(FAR struct mod_loadinfo_s *loadinfo)
|
||||
{
|
||||
uintptr_t base = 0;
|
||||
|
||||
#ifdef HAVE_LIBC_ELF_PIN
|
||||
if (ioctl(loadinfo->filfd, XIPFSIOC_PIN, (unsigned long)&base) >= 0)
|
||||
{
|
||||
int ret = libelf_pinhold(loadinfo);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
berr("ERROR: Failed to hold the pinned file: %d\n", ret);
|
||||
ioctl(loadinfo->filfd, XIPFSIOC_UNPIN, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
loadinfo->xipbase = base;
|
||||
binfo("pinned xipbase %" PRIxPTR "\n", loadinfo->xipbase);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ioctl(loadinfo->filfd, FIOC_XIPBASE, (unsigned long)&base) >= 0)
|
||||
{
|
||||
loadinfo->xipbase = base;
|
||||
binfo("can use xipbase %" PRIxPTR "\n", loadinfo->xipbase);
|
||||
return OK;
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_LIBC_ELF_PIN
|
||||
/****************************************************************************
|
||||
* Name: libelf_pinrelease
|
||||
*
|
||||
* Description:
|
||||
* Give back an XIP pin and the file it was held through, so the
|
||||
* filesystem can reclaim the extent.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void libelf_pinrelease(FAR struct file **pinfile)
|
||||
{
|
||||
if (*pinfile != NULL)
|
||||
{
|
||||
file_ioctl(*pinfile, XIPFSIOC_UNPIN, 0);
|
||||
file_close(*pinfile);
|
||||
lib_free(*pinfile);
|
||||
*pinfile = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: libelf_load
|
||||
*
|
||||
|
|
@ -559,6 +671,7 @@ skipload:
|
|||
int libelf_load(FAR struct mod_loadinfo_s *loadinfo)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
binfo("loadinfo: %p\n", loadinfo);
|
||||
DEBUGASSERT(loadinfo && loadinfo->filfd >= 0);
|
||||
|
|
@ -576,11 +689,7 @@ int libelf_load(FAR struct mod_loadinfo_s *loadinfo)
|
|||
if (loadinfo->gotindex >= 0)
|
||||
{
|
||||
binfo("GOT section found! index %d\n", loadinfo->gotindex);
|
||||
if (ioctl(loadinfo->filfd, FIOC_XIPBASE,
|
||||
(unsigned long)&loadinfo->xipbase) >= 0)
|
||||
{
|
||||
binfo("can use xipbase %zu\n", loadinfo->xipbase);
|
||||
}
|
||||
libelf_xipacquire(loadinfo);
|
||||
}
|
||||
|
||||
/* Determine total size to allocate */
|
||||
|
|
@ -647,21 +756,96 @@ int libelf_load(FAR struct mod_loadinfo_s *loadinfo)
|
|||
}
|
||||
else if (loadinfo->ehdr.e_type == ET_DYN)
|
||||
{
|
||||
loadinfo->textalloc = (uintptr_t)lib_memalign(loadinfo->textalign,
|
||||
loadinfo->textsize +
|
||||
loadinfo->datasize +
|
||||
loadinfo->segpad);
|
||||
|
||||
if (!loadinfo->textalloc)
|
||||
if (loadinfo->fdpic)
|
||||
{
|
||||
berr("ERROR: Failed to allocate memory for the module\n");
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_buffers;
|
||||
}
|
||||
/* The two segments are placed independently, thus only the
|
||||
* writable segment is allocated, once per instance.
|
||||
*/
|
||||
|
||||
loadinfo->datastart = loadinfo->textalloc +
|
||||
loadinfo->textsize +
|
||||
loadinfo->segpad;
|
||||
if (loadinfo->xipbase != 0)
|
||||
{
|
||||
/* The text stays on the media. The media address is the base
|
||||
* of the file, thus add the file offset of the segment.
|
||||
*/
|
||||
|
||||
for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
|
||||
{
|
||||
FAR Elf_Phdr *phdr = &loadinfo->phdr[i];
|
||||
|
||||
if (phdr->p_type == PT_LOAD &&
|
||||
(phdr->p_flags & PF_X) != 0)
|
||||
{
|
||||
loadinfo->textalloc = loadinfo->xipbase +
|
||||
phdr->p_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (loadinfo->textsize > 0)
|
||||
{
|
||||
/* The filesystem cannot show its media, thus copy the text
|
||||
* to RAM. The instances no longer share it.
|
||||
*/
|
||||
|
||||
# if defined(CONFIG_ARCH_USE_TEXT_HEAP) && \
|
||||
defined(CONFIG_ARCH_USE_SEPARATED_SECTION)
|
||||
loadinfo->textalloc = (uintptr_t)
|
||||
up_textheap_memalign(".text",
|
||||
loadinfo->textalign,
|
||||
loadinfo->textsize);
|
||||
# elif defined(CONFIG_ARCH_USE_TEXT_HEAP)
|
||||
loadinfo->textalloc = (uintptr_t)
|
||||
up_textheap_memalign(loadinfo->textalign,
|
||||
loadinfo->textsize);
|
||||
# else
|
||||
loadinfo->textalloc = (uintptr_t)
|
||||
lib_memalign(loadinfo->textalign,
|
||||
loadinfo->textsize);
|
||||
# endif
|
||||
if (loadinfo->textalloc == 0)
|
||||
{
|
||||
berr("ERROR: Failed to allocate the module's text\n");
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_buffers;
|
||||
}
|
||||
}
|
||||
|
||||
if (loadinfo->datasize > 0)
|
||||
{
|
||||
loadinfo->datastart =
|
||||
(uintptr_t)lib_memalign(loadinfo->dataalign,
|
||||
loadinfo->datasize);
|
||||
if (!loadinfo->datastart)
|
||||
{
|
||||
berr("ERROR: Failed to allocate the module's data\n");
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_buffers;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Everything else keeps text and data adjacent: one allocation,
|
||||
* data behind text.
|
||||
*/
|
||||
|
||||
loadinfo->textalloc = (uintptr_t)
|
||||
lib_memalign(loadinfo->textalign,
|
||||
loadinfo->textsize +
|
||||
loadinfo->datasize +
|
||||
loadinfo->segpad);
|
||||
|
||||
if (!loadinfo->textalloc)
|
||||
{
|
||||
berr("ERROR: Failed to allocate memory for the module\n");
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_buffers;
|
||||
}
|
||||
|
||||
loadinfo->datastart = loadinfo->textalloc +
|
||||
loadinfo->textsize +
|
||||
loadinfo->segpad;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_LIBC_ELF_LOADTO_LMA */
|
||||
|
|
@ -732,11 +916,7 @@ int libelf_load_with_addrenv(FAR struct mod_loadinfo_s *loadinfo)
|
|||
if (loadinfo->gotindex >= 0)
|
||||
{
|
||||
binfo("GOT section found! index %d\n", loadinfo->gotindex);
|
||||
if (ioctl(loadinfo->filfd, FIOC_XIPBASE,
|
||||
(unsigned long)&loadinfo->xipbase) >= 0)
|
||||
{
|
||||
binfo("can use xipbase %zu\n", loadinfo->xipbase);
|
||||
}
|
||||
libelf_xipacquire(loadinfo);
|
||||
}
|
||||
|
||||
/* Determine total size to allocate */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <nuttx/debug.h>
|
||||
#include <nuttx/elf.h>
|
||||
|
||||
#include <nuttx/lib/elf.h>
|
||||
|
||||
|
|
@ -66,6 +67,23 @@ int libelf_loadhdrs(FAR struct mod_loadinfo_s *loadinfo)
|
|||
|
||||
/* Verify that there are sections */
|
||||
|
||||
/* The architecture knows how an FDPIC object announces itself. Ask it
|
||||
* once.
|
||||
*/
|
||||
|
||||
loadinfo->fdpic = ELF_IS_FDPIC(&loadinfo->ehdr);
|
||||
|
||||
/* A module is a shared object. An FDPIC object that is anything else
|
||||
* would be placed through the wrong path.
|
||||
*/
|
||||
|
||||
if (loadinfo->fdpic && loadinfo->ehdr.e_type != ET_DYN)
|
||||
{
|
||||
berr("ERROR: FDPIC object is not a shared object: e_type=%u\n",
|
||||
loadinfo->ehdr.e_type);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (loadinfo->ehdr.e_shnum < 1)
|
||||
{
|
||||
berr("ERROR: No sections(?)\n");
|
||||
|
|
|
|||
|
|
@ -59,6 +59,17 @@ int libelf_unload(FAR struct mod_loadinfo_s *loadinfo)
|
|||
|
||||
libelf_freebuffers(loadinfo);
|
||||
|
||||
#ifdef HAVE_LIBC_ELF_PIN
|
||||
/* Give the pin back if the loader took one, so the filesystem can
|
||||
* reclaim the extent.
|
||||
*/
|
||||
|
||||
if (loadinfo->pinfile != NULL)
|
||||
{
|
||||
libelf_pinrelease(&loadinfo->pinfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
if (loadinfo->addrenv != NULL)
|
||||
{
|
||||
|
|
@ -68,9 +79,35 @@ int libelf_unload(FAR struct mod_loadinfo_s *loadinfo)
|
|||
#endif
|
||||
/* Release memory holding the relocated ELF image */
|
||||
|
||||
/* ET_DYN has a single allocation so we only free textalloc */
|
||||
/* An FDPIC object placed its two segments separately. Free each one. If
|
||||
* the text stayed on the media, it was never allocated, thus leave it.
|
||||
*/
|
||||
|
||||
if (loadinfo->ehdr.e_type != ET_DYN)
|
||||
if (loadinfo->fdpic)
|
||||
{
|
||||
if (loadinfo->textalloc != 0 && loadinfo->xipbase == 0)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_USE_TEXT_HEAP
|
||||
up_textheap_free((FAR void *)loadinfo->textalloc);
|
||||
#else
|
||||
lib_free((FAR void *)loadinfo->textalloc);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (loadinfo->datastart != 0)
|
||||
{
|
||||
lib_free((FAR void *)loadinfo->datastart);
|
||||
loadinfo->datastart = 0;
|
||||
}
|
||||
|
||||
loadinfo->textalloc = 0;
|
||||
loadinfo->textsize = 0;
|
||||
loadinfo->datasize = 0;
|
||||
}
|
||||
|
||||
/* Any other ET_DYN has a single allocation so we only free textalloc */
|
||||
|
||||
else if (loadinfo->ehdr.e_type != ET_DYN)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_USE_SEPARATED_SECTION
|
||||
int i;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue