nuttx/binfmt/libelf/libelf_addrenv.c

294 lines
8.5 KiB
C
Raw Normal View History

/****************************************************************************
* binfmt/libelf/libelf_addrenv.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <sys/mman.h>
#include "libelf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ELF_TEXT_WRE (PROT_READ | PROT_WRITE | PROT_EXEC)
#define ELF_TEXT_WRD (PROT_READ | PROT_EXEC)
/****************************************************************************
* Private Constant Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: elf_addrenv_alloc
*
* Description:
* Allocate memory for the ELF image (textalloc and dataalloc). If
* CONFIG_ARCH_ADDRENV=n, textalloc will be allocated using kmm_zalloc()
* and dataalloc will be a offset from textalloc. If
* CONFIG_ARCH_ADDRENV=y, then textalloc and dataalloc will be allocated
* using up_addrenv_create(). In either case, there will be a unique
* instance of textalloc and dataalloc (and stack) for each instance of a
* process.
*
* Input Parameters:
* loadinfo - Load state information
* textsize - The size (in bytes) of the .text address environment needed
* for the ELF image (read/execute).
* datasize - The size (in bytes) of the .bss/.data address environment
* needed for the ELF image (read/write).
* heapsize - The initial size (in bytes) of the heap address environment
* needed by the task. This region may be read/write only.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
size_t datasize, size_t heapsize)
{
#ifdef CONFIG_ARCH_ADDRENV
FAR void *vtext;
FAR void *vdata;
int ret;
/* Create an address environment for the new ELF task */
ret = up_addrenv_create(textsize, datasize, heapsize, &loadinfo->addrenv);
if (ret < 0)
{
berr("ERROR: up_addrenv_create failed: %d\n", ret);
return ret;
}
/* Get the virtual address associated with the start of the address
* environment. This is the base address that we will need to use to
* access the ELF image (but only if the address environment has been
* selected.
*/
ret = up_addrenv_vtext(&loadinfo->addrenv, &vtext);
if (ret < 0)
{
berr("ERROR: up_addrenv_vtext failed: %d\n", ret);
return ret;
}
ret = up_addrenv_vdata(&loadinfo->addrenv, textsize, &vdata);
if (ret < 0)
{
berr("ERROR: up_addrenv_vdata failed: %d\n", ret);
return ret;
}
loadinfo->textalloc = (uintptr_t)vtext;
loadinfo->dataalloc = (uintptr_t)vdata;
return OK;
#else
/* Allocate memory to hold the ELF image */
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
loadinfo->textalloc = (uintptr_t)
up_textheap_memalign(loadinfo->textalign,
textsize);
#else
loadinfo->textalloc = (uintptr_t)kumm_memalign(loadinfo->textalign,
textsize);
#endif
if (!loadinfo->textalloc)
{
return -ENOMEM;
}
if (loadinfo->datasize > 0)
{
loadinfo->dataalloc = (uintptr_t)kumm_memalign(loadinfo->dataalign,
datasize);
if (!loadinfo->dataalloc)
{
return -ENOMEM;
}
}
return OK;
#endif
}
/****************************************************************************
* Name: elf_addrenv_select
*
* Description:
* Temporarily select the task's address environment.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo)
{
int ret;
/* Instantiate the new address environment */
ret = up_addrenv_select(&loadinfo->addrenv, &loadinfo->oldenv);
if (ret < 0)
{
berr("ERROR: up_addrenv_select failed: %d\n", ret);
return ret;
}
/* Allow write access to .text */
ret = up_addrenv_mprot(&loadinfo->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_WRE);
if (ret < 0)
{
berr("ERROR: up_addrenv_text_enable_write failed: %d\n", ret);
return ret;
}
return OK;
}
#endif
/****************************************************************************
* Name: elf_addrenv_restore
*
* Description:
* Restore the address environment before elf_addrenv_select() was called..
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo)
{
int ret;
/* Remove write access to .text */
ret = up_addrenv_mprot(&loadinfo->addrenv, loadinfo->textalloc,
loadinfo->textsize, ELF_TEXT_WRD);
if (ret < 0)
{
berr("ERROR: up_addrenv_text_disable_write failed: %d\n", ret);
return ret;
}
/* Restore the old address environment */
ret = up_addrenv_restore(&loadinfo->oldenv);
if (ret < 0)
{
berr("ERROR: up_addrenv_restore failed: %d\n", ret);
return ret;
}
return OK;
}
#endif
/****************************************************************************
* Name: elf_addrenv_free
*
* Description:
* Release the address environment previously created by
* elf_addrenv_alloc(). This function is called only under certain error
* conditions after the module has been loaded but not yet started.
* After the module has been started, the address environment will
* automatically be freed when the module exits.
*
* Input Parameters:
* loadinfo - Load state information
*
* Returned Value:
* None.
*
****************************************************************************/
void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo)
{
#ifdef CONFIG_ARCH_ADDRENV
int ret;
/* Free the address environment */
binfmt: elf_addrenv_free select addrenv before up_addrenv_destroy to avoid up_addrenv_destroy delete the current task page table this patch fix the below panic due to elf contain the unresolved symbol: qemu-system-arm -s -S -semihosting -M sabrelite -m 1024 -smp 4 -kernel nuttx -nographic -net nic -net user,hostfwd=tcp:127.0.0.1:10023-10.0.2.15:23,hostfwd=tcp:127.0.0.1:10021-10.0.2.15:21,hostfwd=tcp:127.0.0.1:15001-10.0.2.15:5001,hostfwd=tcp:127.0.0.1:15555-10.0.2.15:5555 ABDGHIJKNOPQ [ 0.470000] elf_relocate: Section 2 reloc 163: Failed to get value of symbol[1505]: -2 [ 0.530000] arm_dataabort: Data abort. PC: 108323de DFAR: 80202778 DFSR: 00000005 [ 0.530000] up_assert: Assertion failed at file:armv7-a/arm_dataabort.c line: 161 task: /system/bin/init [ 0.530000] arm_registerdump: R0: 10845820 R1: 80202778 R2: 00000001 R3: 80202778 [ 0.530000] arm_registerdump: R4: 80202624 R5: 80202634 R6: 80200330 FP: 80202628 [ 0.530000] arm_registerdump: R8: 802026b4 SB: 00000000 SL: 8000dbfe R11: 00000000 [ 0.530000] arm_registerdump: IP: 108453e0 SP: 108456b0 LR: 1082b091 PC: 108323de [ 0.530000] arm_registerdump: CPSR: a000007f [ 0.530000] arm_dump_stack: IRQ Stack: [ 0.530000] arm_dump_stack: sp: 10845510 [ 0.530000] arm_dump_stack: base: 108397c0 [ 0.530000] arm_dump_stack: size: 00000800 [ 0.530000] arm_dump_stack: ERROR: IRQ Stack pointer is not within the stack [ 0.530000] arm_stackdump: 10839f00: deadbeef 00adbeef 00000001 10844990 00000000 00000000 80300000 1082f2ef [ 0.530000] arm_stackdump: 10839f20: deadbeef 00000000 deadbeef 10844990 80200000 1082f2ff 1083d980 1082f311 [ 0.530000] arm_stackdump: 10839f40: 00000002 10814659 00000004 00000002 deadbeef 1081469b 00000001 00000000 [ 0.530000] arm_stackdump: 10839f60: 10845460 00000057 10844a90 00000002 deadbeef 10808d1b 10845460 00000057 [ 0.530000] arm_stackdump: 10839f80: 00dfbeef 00000057 00000000 00000002 deadbeef 10801d1f 10845460 00000057 [ 0.530000] arm_stackdump: 10839fa0: 00000000 10800fc5 deadbeef 10845460 00000057 00000057 deadbeef 108000a0 [ 0.530000] arm_dump_stack: User Stack: [ 0.530000] arm_dump_stack: sp: 108456b0 [ 0.530000] arm_dump_stack: base: 80202038 [ 0.530000] arm_dump_stack: size: 000007c8 [ 0.530000] arm_dump_stack: ERROR: User Stack pointer is not within the stack [ 0.530000] arm_dump_stack: Kernel Stack: [ 0.530000] arm_dump_stack: sp: 108456b0 [ 0.530000] arm_dump_stack: base: 10844c10 [ 0.530000] arm_dump_stack: size: 00000c00 [ 0.530000] arm_stackdump: 108456a0: 00000000 108453e0 108323de a000007f 80202778 10845820 00000000 10812aa9 [ 0.530000] arm_stackdump: 108456c0: 00000000 1083ff90 10845838 00000000 001f001e 10812b2f 10840008 1083ff90 [ 0.530000] arm_stackdump: 108456e0: 10845840 10812fab 10845840 1083ff90 005f0000 10844990 10845818 10845ff8 [ 0.530000] arm_stackdump: 10845700: 10845ff8 10845838 10845840 10812017 fffffffe 10845820 80202624 1082b091 [ 0.530000] arm_stackdump: 10845720: 00000000 00000000 80202778 10841d40 00000000 10845840 10845820 fffffffe [ 0.530000] arm_stackdump: 10845740: 00000000 1082998b 00000000 80200330 802026b4 80202778 10845788 0084578c [ 0.530000] arm_stackdump: 10845760: 10841d40 10844990 00000000 108306fb 00000000 80202634 802026b4 80202634 [ 0.530000] arm_stackdump: 10845780: 80202778 80202628 00000000 00000000 00000000 00000000 00000000 1083085f [ 0.530000] arm_stackdump: 108457a0: 80200330 00000000 00000000 00000000 80202634 80202624 80202778 80202628 [ 0.530000] arm_stackdump: 108457c0: 00000000 00000000 00000000 80202614 80202624 1080f26b 802026b4 80200330 [ 0.530000] arm_stackdump: 108457e0: 80202624 80202778 80202628 0000001f 00000000 80202634 802026b4 108012c3 [ 0.530000] arm_showtasks: PID PRI STACK USED FILLED COMMAND [ 0.530000] arm_showtasks: ---- ---- 2048 188 9.1% irq [ 0.530000] arm_dump_task: 0 0 2024 1240 61.2% Idle Task [ 0.530000] arm_dump_task: 1 224 1992 504 25.3% hpwork 0x1083e0f8 [ 0.530000] arm_dump_task: 2 100 1992 504 25.3% lpwork 0x1083e110 after apply this patch, nsh report error instead of crash: qemu-system-arm -s -S -semihosting -M sabrelite -m 1024 -smp 4 -kernel nuttx -nographic -net nic -net user,hostfwd=tcp:127.0.0.1:10023-10.0.2.15:23,hostfwd=tcp:127.0.0.1:10021-10.0.2.15:21,hostfwd=tcp:127.0.0.1:15001-10.0.2.15:5001,hostfwd=tcp:127.0.0.1:15555-10.0.2.15:5555 ABDGHIJKNOPQ [ 0.440000] elf_relocate: Section 2 reloc 163: Failed to get value of symbol[1505]: -2 telnetd [4:100] NuttShell (NSH) NuttX-11.0.0 nsh> nsh: telnetd: command not found Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2022-11-01 08:39:12 +01:00
elf_addrenv_select(loadinfo);
ret = up_addrenv_destroy(&loadinfo->addrenv);
binfmt: elf_addrenv_free select addrenv before up_addrenv_destroy to avoid up_addrenv_destroy delete the current task page table this patch fix the below panic due to elf contain the unresolved symbol: qemu-system-arm -s -S -semihosting -M sabrelite -m 1024 -smp 4 -kernel nuttx -nographic -net nic -net user,hostfwd=tcp:127.0.0.1:10023-10.0.2.15:23,hostfwd=tcp:127.0.0.1:10021-10.0.2.15:21,hostfwd=tcp:127.0.0.1:15001-10.0.2.15:5001,hostfwd=tcp:127.0.0.1:15555-10.0.2.15:5555 ABDGHIJKNOPQ [ 0.470000] elf_relocate: Section 2 reloc 163: Failed to get value of symbol[1505]: -2 [ 0.530000] arm_dataabort: Data abort. PC: 108323de DFAR: 80202778 DFSR: 00000005 [ 0.530000] up_assert: Assertion failed at file:armv7-a/arm_dataabort.c line: 161 task: /system/bin/init [ 0.530000] arm_registerdump: R0: 10845820 R1: 80202778 R2: 00000001 R3: 80202778 [ 0.530000] arm_registerdump: R4: 80202624 R5: 80202634 R6: 80200330 FP: 80202628 [ 0.530000] arm_registerdump: R8: 802026b4 SB: 00000000 SL: 8000dbfe R11: 00000000 [ 0.530000] arm_registerdump: IP: 108453e0 SP: 108456b0 LR: 1082b091 PC: 108323de [ 0.530000] arm_registerdump: CPSR: a000007f [ 0.530000] arm_dump_stack: IRQ Stack: [ 0.530000] arm_dump_stack: sp: 10845510 [ 0.530000] arm_dump_stack: base: 108397c0 [ 0.530000] arm_dump_stack: size: 00000800 [ 0.530000] arm_dump_stack: ERROR: IRQ Stack pointer is not within the stack [ 0.530000] arm_stackdump: 10839f00: deadbeef 00adbeef 00000001 10844990 00000000 00000000 80300000 1082f2ef [ 0.530000] arm_stackdump: 10839f20: deadbeef 00000000 deadbeef 10844990 80200000 1082f2ff 1083d980 1082f311 [ 0.530000] arm_stackdump: 10839f40: 00000002 10814659 00000004 00000002 deadbeef 1081469b 00000001 00000000 [ 0.530000] arm_stackdump: 10839f60: 10845460 00000057 10844a90 00000002 deadbeef 10808d1b 10845460 00000057 [ 0.530000] arm_stackdump: 10839f80: 00dfbeef 00000057 00000000 00000002 deadbeef 10801d1f 10845460 00000057 [ 0.530000] arm_stackdump: 10839fa0: 00000000 10800fc5 deadbeef 10845460 00000057 00000057 deadbeef 108000a0 [ 0.530000] arm_dump_stack: User Stack: [ 0.530000] arm_dump_stack: sp: 108456b0 [ 0.530000] arm_dump_stack: base: 80202038 [ 0.530000] arm_dump_stack: size: 000007c8 [ 0.530000] arm_dump_stack: ERROR: User Stack pointer is not within the stack [ 0.530000] arm_dump_stack: Kernel Stack: [ 0.530000] arm_dump_stack: sp: 108456b0 [ 0.530000] arm_dump_stack: base: 10844c10 [ 0.530000] arm_dump_stack: size: 00000c00 [ 0.530000] arm_stackdump: 108456a0: 00000000 108453e0 108323de a000007f 80202778 10845820 00000000 10812aa9 [ 0.530000] arm_stackdump: 108456c0: 00000000 1083ff90 10845838 00000000 001f001e 10812b2f 10840008 1083ff90 [ 0.530000] arm_stackdump: 108456e0: 10845840 10812fab 10845840 1083ff90 005f0000 10844990 10845818 10845ff8 [ 0.530000] arm_stackdump: 10845700: 10845ff8 10845838 10845840 10812017 fffffffe 10845820 80202624 1082b091 [ 0.530000] arm_stackdump: 10845720: 00000000 00000000 80202778 10841d40 00000000 10845840 10845820 fffffffe [ 0.530000] arm_stackdump: 10845740: 00000000 1082998b 00000000 80200330 802026b4 80202778 10845788 0084578c [ 0.530000] arm_stackdump: 10845760: 10841d40 10844990 00000000 108306fb 00000000 80202634 802026b4 80202634 [ 0.530000] arm_stackdump: 10845780: 80202778 80202628 00000000 00000000 00000000 00000000 00000000 1083085f [ 0.530000] arm_stackdump: 108457a0: 80200330 00000000 00000000 00000000 80202634 80202624 80202778 80202628 [ 0.530000] arm_stackdump: 108457c0: 00000000 00000000 00000000 80202614 80202624 1080f26b 802026b4 80200330 [ 0.530000] arm_stackdump: 108457e0: 80202624 80202778 80202628 0000001f 00000000 80202634 802026b4 108012c3 [ 0.530000] arm_showtasks: PID PRI STACK USED FILLED COMMAND [ 0.530000] arm_showtasks: ---- ---- 2048 188 9.1% irq [ 0.530000] arm_dump_task: 0 0 2024 1240 61.2% Idle Task [ 0.530000] arm_dump_task: 1 224 1992 504 25.3% hpwork 0x1083e0f8 [ 0.530000] arm_dump_task: 2 100 1992 504 25.3% lpwork 0x1083e110 after apply this patch, nsh report error instead of crash: qemu-system-arm -s -S -semihosting -M sabrelite -m 1024 -smp 4 -kernel nuttx -nographic -net nic -net user,hostfwd=tcp:127.0.0.1:10023-10.0.2.15:23,hostfwd=tcp:127.0.0.1:10021-10.0.2.15:21,hostfwd=tcp:127.0.0.1:15001-10.0.2.15:5001,hostfwd=tcp:127.0.0.1:15555-10.0.2.15:5555 ABDGHIJKNOPQ [ 0.440000] elf_relocate: Section 2 reloc 163: Failed to get value of symbol[1505]: -2 telnetd [4:100] NuttShell (NSH) NuttX-11.0.0 nsh> nsh: telnetd: command not found Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2022-11-01 08:39:12 +01:00
elf_addrenv_restore(loadinfo);
if (ret < 0)
{
berr("ERROR: up_addrenv_destroy failed: %d\n", ret);
}
#else
if (loadinfo->textalloc != 0)
{
#if defined(CONFIG_ARCH_USE_TEXT_HEAP)
up_textheap_free((FAR void *)loadinfo->textalloc);
#else
kumm_free((FAR void *)loadinfo->textalloc);
#endif
}
if (loadinfo->dataalloc != 0)
{
kumm_free((FAR void *)loadinfo->dataalloc);
}
#endif
/* Clear out all indications of the allocated address environment */
loadinfo->textalloc = 0;
loadinfo->dataalloc = 0;
loadinfo->textsize = 0;
loadinfo->datasize = 0;
}