From 731994d0383c636e43644c3dc91b91b15745b345 Mon Sep 17 00:00:00 2001 From: patacongo Date: Tue, 16 Jun 2009 22:08:59 +0000 Subject: Added NXFLAT a bit at a time git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1889 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/binfmt/Makefile | 85 +++++ nuttx/binfmt/libnxflat/Make.defs | 37 +++ nuttx/binfmt/libnxflat/libnxflat_load.c | 513 ++++++++++++++++++++++++++++++ nuttx/binfmt/libnxflat/libnxflat_stack.c | 224 +++++++++++++ nuttx/binfmt/libnxflat/libnxflat_verify.c | 116 +++++++ 5 files changed, 975 insertions(+) create mode 100644 nuttx/binfmt/Makefile create mode 100644 nuttx/binfmt/libnxflat/Make.defs create mode 100644 nuttx/binfmt/libnxflat/libnxflat_load.c create mode 100644 nuttx/binfmt/libnxflat/libnxflat_stack.c create mode 100644 nuttx/binfmt/libnxflat/libnxflat_verify.c (limited to 'nuttx/binfmt') diff --git a/nuttx/binfmt/Makefile b/nuttx/binfmt/Makefile new file mode 100644 index 000000000..0e3d9720c --- /dev/null +++ b/nuttx/binfmt/Makefile @@ -0,0 +1,85 @@ +############################################################################ +# nxflat/Makefile +# +# Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +include libnxflat/Make.defs + +SUBDIRS = libnxflat + +ASRCS = $(LIBNXFLAT_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(LIBNXFLAT_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libbinfmt$(LIBEXT) + +VPATH = libnxflat + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + +.depend: Makefile $(SRCS) + @$(MKDEP) --dep-path . --dep-path libnxflat \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + @rm -f $(BIN) *~ .*.swp + $(call CLEAN) + @( for dir in $(SUBDIRS); do \ + rm -f $${dir}/*~ $${dir}/.*.swp; \ + done ; ) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/binfmt/libnxflat/Make.defs b/nuttx/binfmt/libnxflat/Make.defs new file mode 100644 index 000000000..96cff471d --- /dev/null +++ b/nuttx/binfmt/libnxflat/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# nxflat/lib/Make.defs +# +# Copyright (C) 2009 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +LIBNXFLAT_ASRCS = +LIBNXFLAT_CSRCS = libnxflat_load.c libnxflat_stack.c libnxflat_verify.c diff --git a/nuttx/binfmt/libnxflat/libnxflat_load.c b/nuttx/binfmt/libnxflat/libnxflat_load.c new file mode 100644 index 000000000..d456ae3a1 --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_load.c @@ -0,0 +1,513 @@ +/**************************************************************************** + * libnxflat/lib/libnxflat_load.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#define V_MAP (load_info->vtbl->map) +#define V_UNMAP (load_info->vtbl->unmap) +#define V_ALLOC (load_info->vtbl->alloc) +#define V_FREE (load_info->vtbl->free) +#define V_OPEN (load_info->vtbl->open) +#define V_READ (load_info->vtbl->read) +#define V_CLOSE (load_info->vtbl->close) + +#define NXFLAT_HDR_SIZE sizeof(struct nxflat_hdr_s) + +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +#ifdef CONFIG_NXFLAT_DEBUG +static const char text_segment[] = "TEXT"; +static const char data_segment[] = "DATA"; +static const char bss_segment[] = "BSS"; +static const char unknown[] = "UNKNOWN"; + +static const char *segment[] = +{ + text_segment, + data_segment, + bss_segment, + unknown +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_swap32 + ****************************************************************************/ + +#ifdef __BIG_ENDIAN +static inline uint32 nxflat_swap32(uint32 little) +{ + uint32 big = + ((little >> 24) & 0xff) | + (((little >> 16) & 0xff) << 8) | + (((little >> 8) & 0xff) << 16) | + ((little & 0xff) << 24); + return big; +} +#endif + +/**************************************************************************** + * Name: nxflat_reloc + ****************************************************************************/ + +static void nxflat_reloc(struct nxflat_loadinfo_s *load_info, uint32 rl) +{ + union + { + uint32 l; + struct nxflat_reloc_s s; + } reloc; + uint32 *ptr; + uint32 datastart; + + /* Force the long value into a union so that we can strip off some + * bit-encoded values. + */ + + reloc.l = rl; + + /* We only support relocations in the data sections. + * Verify that the the relocation address lies in the data + * section of the file image. + */ + + if (reloc.s.r_offset > load_info->data_size) + { + dbg("ERROR: Relocation at 0x%08x invalid -- " + "does not lie in the data segment, size=0x%08x\n", + reloc.s.r_offset, load_info->data_size); + dbg(" Relocation not performed!\n"); + } + else if ((reloc.s.r_offset & 0x00000003) != 0) + { + dbg("ERROR: Relocation at 0x%08x invalid -- " + "Improperly aligned\n", + reloc.s.r_offset); + } + else + { + /* Get a reference to the "real" start of data. It is + * offset slightly from the beginning of the allocated + * DSpace to hold information needed by ld.so at run time. + */ + + datastart = load_info->dspace + NXFLAT_DATA_OFFSET; + + /* Get a pointer to the value that needs relocation in + * DSpace. + */ + + ptr = (uint32*)(datastart + reloc.s.r_offset); + + vdbg("Relocation of variable at DATASEG+0x%08x " + "(address 0x%p, currently 0x%08x) into segment %s\n", + reloc.s.r_offset, ptr, *ptr, segment[reloc.s.r_type]); + + switch (reloc.s.r_type) + { + /* TEXT is located at an offset of NXFLAT_HDR_SIZE from + * the allocated/mapped ISpace region. + */ + + case NXFLAT_RELOC_TYPE_TEXT: + *ptr += load_info->ispace + NXFLAT_HDR_SIZE; + break; + + /* DATA and BSS are always contiguous regions. DATA + * begins at an offset of NXFLAT_DATA_OFFSET from + * the beginning of the allocated data segment. + * BSS is positioned after DATA, unrelocated references + * to BSS include the data offset. + * + * In other contexts, is it necessary to add the data_size + * to get the BSS offset like: + * + * *ptr += datastart + load_info->data_size; + */ + + case NXFLAT_RELOC_TYPE_DATA: + case NXFLAT_RELOC_TYPE_BSS: + *ptr += datastart; + break; + + /* This case happens normally if the symbol is a weak + * undefined symbol. We permit these. + */ + + case NXFLAT_RELOC_TYPE_NONE: + dbg("NULL relocation!\n"); + break; + + default: + dbg("ERROR: Unknown relocation type=%d\n", reloc.s.r_type); + break; + } + + vdbg("Relocation became 0x%08x\n", *ptr); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_init + ****************************************************************************/ + +int nxflat_init(bin_handle_t bin_handle, file_handle_t file_handle, + const struct nxflat_hdr_s *header, const struct nxflat_vtbl_s *vtbl, + struct nxflat_loadinfo_s *load_info) +{ + uint32 datastart; + uint32 dataend; + uint32 bssstart; + uint32 bssend; + + vdbg("bin_handle=0x%p header=0x%p load_info=0x%p\n", + bin_handle, header, load_info); + + /* Clear the load info structure */ + + memset(load_info, 0, sizeof(struct nxflat_loadinfo_s)); + + /* Verify the xFLT header */ + + if (nxflat_verifyheader(header) != 0) + { + /* This is not an error because we will be called + * to attempt loading EVERY binary. Returning -ENOEXEC + * simply informs the system that the file is not + * an xFLT file. Besides, if there is something worth + * complaining about, nnxflat_verifyheader() has already + * done so. + */ + + dbg("Bad xFLT header\n"); + return -ENOEXEC; + } + + /* Save all of the input values in the load_info structure */ + + load_info->bin_handle = bin_handle; + load_info->file_handle = file_handle; + load_info->header = header; + load_info->vtbl = vtbl; + + /* And extract some additional information from the xflat + * header. Note that the information in the xflat header is in + * network order. + */ + + datastart = ntohl(header->h_datastart); + dataend = ntohl(header->h_dataend); + bssstart = dataend; + bssend = ntohl(header->h_bssend); + + /* And put this information into the load_info structure as well. + * + * Note that: + * + * ispace_size = the address range from 0 up to datastart. + * data_size = the address range from datastart up to dataend + * bss_size = the address range from dataend up to bssend. + */ + + load_info->entry_offset = ntohl(header->h_entry); + load_info->ispace_size = datastart; + + load_info->data_size = dataend - datastart; + load_info->bss_size = bssend - dataend; + load_info->stack_size = ntohl(header->h_stacksize); + + /* This is the initial dspace size. We'll recaculate this later + * after the memory has been allocated. So that the caller can feel + * free to modify dspace_size values from now until then. + */ + + load_info->dspace_size = /* Total DSpace Size is: */ + (NXFLAT_DATA_OFFSET + /* Memory set aside for ldso */ + bssend - datastart + /* Data and bss segment sizes */ + load_info->stack_size); /* (Current) stack size */ + + /* Get the offset to the start of the relocations (we'll relocate + * this later). + */ + + load_info->reloc_start = ntohl(header->h_relocstart); + load_info->reloc_count = ntohl(header->h_reloccount); + + return 0; +} + +/**************************************************************************** + * Name: nxflat_uninit + ****************************************************************************/ + +int nxflat_uninit(struct nxflat_loadinfo_s *load_info) +{ + if (load_info->file_handle) + { + V_CLOSE(load_info->file_handle); + } + return 0; +} + +/**************************************************************************** + * Name: nxflat_load + ****************************************************************************/ + +int nxflat_load(struct nxflat_loadinfo_s *load_info) +{ + uint32 dspace_read_size; + uint32 data_offset; + uint32 *reloc_tab; + uint32 result; + int i; + + /* Calculate the extra space we need to map in. This region + * will be the BSS segment and the stack. It will also be used + * temporarily to hold relocation information. So the size of this + * region will either be the size of the BSS section and the + * stack OR, it the size of the relocation entries, whichever + * is larger + */ + + { + uint32 extra_alloc; + uint32 reloc_size; + + /* This is the amount of memory that we have to have to hold + * the relocations. + */ + + reloc_size = load_info->reloc_count * sizeof(uint32); + + /* In the file, the relocations should lie at the same offset + * as BSS. The additional amount that we allocate have to + * be either (1) the BSS size + the stack size, or (2) the + * size of the relocation records, whicher is larger. + */ + + extra_alloc = MAX(load_info->bss_size + load_info->stack_size, + reloc_size); + + /* Use this addtional amount to adjust the total size of the + * dspace region. */ + + load_info->dspace_size = + NXFLAT_DATA_OFFSET + /* Memory used by ldso */ + load_info->data_size + /* Initialized data */ + extra_alloc; /* bss+stack/relocs */ + + /* The number of bytes of data that we have to read from the + * file is the data size plus the size of the relocation table. + */ + + dspace_read_size = load_info->data_size + reloc_size; + } + + /* We'll need this a few times as well. */ + + data_offset = load_info->ispace_size; + + /* We will make two mmap calls create an address space for + * the executable. We will attempt to map the file to get + * the ISpace address space and to allocate RAM to get the + * DSpace address space. If the system does not support + * file mapping, the V_MAP() implementation should do the + * right thing. + */ + + /* The following call will give as a pointer to the mapped + * file ISpace. This may be in ROM, RAM, Flash, ... + * We don't really care where the memory resides as long + * as it is fully initialized and ready to execute. + * However, the memory should be share-able between processes; + * otherwise, we don't really have shared libraries. + */ + + load_info->ispace = (uint32)V_MAP(load_info->file_handle, + load_info->ispace_size); + + if (load_info->ispace >= (uint32) -4096) + { + dbg("Failed to map xFLT ISpace, error=%d\n", -load_info->ispace); + return load_info->ispace; + } + + vdbg("Mapped ISpace (%d bytes) at 0x%08x\n", + load_info->ispace_size, load_info->ispace); + + /* The following call will give a pointer to the allocated + * but uninitialized ISpace memory. + */ + + load_info->dspace = (uint32)V_ALLOC(load_info->dspace_size); + + if (load_info->dspace >= (uint32) -4096) + { + dbg("Failed to allocate DSpace, error=%d\n", + -load_info->ispace); + (void)nxflat_unload(load_info); + return load_info->ispace; + } + + vdbg("Allocated DSpace (%d bytes) at 0x%08x\n", + load_info->dspace_size, load_info->dspace); + + /* Now, read the data into allocated DSpace at an offset into + * the allocated DSpace memory. This offset provides a small + * amount of BSS for use by the loader. + */ + + result = V_READ(load_info->bin_handle, + load_info->file_handle, + (char*)(load_info->dspace + NXFLAT_DATA_OFFSET), + dspace_read_size, + data_offset); + + if (result >= (uint32) -4096) + { + dbg("Unable to read DSpace, errno %d\n", -result); + (void)nxflat_unload(load_info); + return result; + } + + /* Save information about the allocation. */ + + load_info->alloc_start = load_info->dspace; + load_info->alloc_size = load_info->dspace_size; + + vdbg("TEXT=0x%x Entry point offset=0x%08x, datastart is 0x%08x\n", + load_info->ispace, load_info->entry_offset, data_offset); + + /* Resolve the address of the relocation table. In the file, the + * relocations should lie at the same offset as BSS. The current + * value of reloc_start is the offset from the beginning of the file. + * The following adjustment will convert it to an address in DSpace. + */ + + reloc_tab = (uint32*) + (load_info->reloc_start /* File offset to reloc records */ + + load_info->dspace /* + Allocated DSpace memory */ + + NXFLAT_DATA_OFFSET /* + Offset for ldso usage */ + - load_info->ispace_size); /* - File offset to DSpace */ + + vdbg("Relocation table at 0x%p, reloc_count=%d\n", + reloc_tab, load_info->reloc_count); + + /* Now run through the relocation entries. */ + + for (i=0; i < load_info->reloc_count; i++) + { +#ifdef __BIG_ENDIAN + nxflat_reloc(load_info, nxflat_swap32(reloc_tab[i])); +#else + nxflat_reloc(load_info, reloc_tab[i]); +#endif + } + + /* Zero the BSS, BRK and stack areas, trashing the relocations + * that lived in the corresponding space in the file. */ + + memset((void*)(load_info->dspace + NXFLAT_DATA_OFFSET + load_info->data_size), + 0, + (load_info->dspace_size - NXFLAT_DATA_OFFSET - + load_info->data_size)); + + return 0; +} + +/**************************************************************************** + * Name: nxflat_unload + * + * Description: + * This function unloads the object from memory. This essentially + * undoes the actions of nxflat_load. + * + ****************************************************************************/ + +int nxflat_unload(struct nxflat_loadinfo_s *load_info) +{ + /* Reset the contents of the info structure. */ + + /* Nothing is allocated */ + + load_info->alloc_start = 0; + load_info->alloc_size = 0; + + /* Release the memory segments */ + + if (load_info->ispace) + { + V_UNMAP((void*)load_info->ispace, load_info->ispace_size); + load_info->ispace = 0; + } + + if (load_info->dspace) + { + V_FREE((void*)load_info->dspace, load_info->dspace_size); + load_info->dspace = 0; + } + + return 0; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_stack.c b/nuttx/binfmt/libnxflat/libnxflat_stack.c new file mode 100644 index 000000000..082a2e05e --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_stack.c @@ -0,0 +1,224 @@ +/**************************************************************************** + * libnxflat/lib/nxflat_stack.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_adjuststacksize + ****************************************************************************/ + +void nxflat_adjuststacksize(struct nxflat_loadinfo_s *load_info, + int argc, int envc, int system_usage) +{ + uint32 total_usage = system_usage; + + /* For argc, we will store the array (argc elements), the argc + * value itself, plus a null pointer. + */ + + total_usage += (argc + 2) * sizeof(uint32); + + /* For envc, we will store the array (envc elements) plus a null + * pointer. + */ + + total_usage += (envc + 1) * sizeof(uint32); + + /* And we will store six additional words described the memory + * layout. + */ + + total_usage += 6 * sizeof(uint32); + + /* Add this to the previously determined stack size */ + + load_info->stack_size += total_usage; +} + +/**************************************************************************** + * Name: nxflat_initstack + * + * Description: + * When we enter the NXFLAT_ loader, it will expect to see a stack frame + * like the following. NOTE: This logic assumes a push down stack + * (i.e., we decrement the stack pointer to go from the "BOTTOM" to + * the "TOP"). + * + * + * TOP->argc Argument count (integer) + * argv[0...(argc-1)] Program arguments (pointers) + * NULL Marks end of arguments + * env[0...N] Environment variables (pointers) + * NULL Marks end of environment variables + * loader ispace Address of loader ISpace (NXFLAT_ header) + * loader dspace Address of loader DSpace + * loader dspace size Size of the allocated loader DSpace + * program ispace Address of program ISpace (NXFLAT_ header) + * program dspace Address of program DSpace + * BOTTOM->program dspace size Size of the allocated program DSpace + * + ****************************************************************************/ + +uint32 nxflat_initstack(struct nxflat_loadinfo_s *prog_load_info, + struct nxflat_loadinfo_s *lib_load_info, + int argc, int envc, char *p) +{ + uint32 *argv; + uint32 *envp; + uint32 *sp; + char dummy; + + /* p points to the beginning of the array of arguments; + * sp points to the "bottom" of a push down stack. + */ + + sp = (uint32*)((-(uint32)sizeof(char*))&(uint32) p); + + /* Place program information on the stack */ + + if (prog_load_info) + { + *sp-- = (uint32)prog_load_info->dspace_size; + *sp-- = (uint32)prog_load_info->dspace; + *sp-- = (uint32)prog_load_info->ispace; + } + else + { + dbg("No program load info provided\n"); + return -EINVAL; + } + + /* Place loader information on the stack */ + + if (lib_load_info) + { + *sp-- = (uint32)lib_load_info->dspace_size; + *sp-- = (uint32)lib_load_info->dspace; + *sp-- = (uint32)lib_load_info->ispace; + } + else + { + *sp-- = (uint32)0; + *sp-- = (uint32)0; + *sp-- = (uint32)0; + } + + /* Allocate space on the stack for the envp array contents + * (including space for a null terminator). + */ + + sp -= envc+1; + envp = sp; + + /* Allocate space on the stack for the argv array contents + * (including space for a null terminator). + */ + + sp -= argc+1; + argv = sp; + + /* Put argc on the stack. sp now points to the "top" of the + * stack as it will be received by the new task. + */ + + *sp-- = (uint32)argc; + + /* Copy argv pointers into the stack frame (terminated with + * a null pointer). + */ + + prog_load_info->arg_start = (uint32)p; + while (argc-->0) + { + /* Put the address of the beginning of the string */ + + *argv++ = (uint32)p; + + /* Search for the end of the string */ + + do + { + dummy = *p++; + } + while (dummy); + } + *argv = (uint32)NULL,argv; + + /* Copy envp pointers into the stack frame (terminated with + * a null pointer). + */ + + prog_load_info->env_start = (uint32)p; + while (envc-->0) + { + /* Put the address of the beginning of the string */ + + *envp++ = (uint32)p; + + /* Search for the end of the string */ + + do + { + dummy = *p++; + } + while (dummy); + } + *envp = (uint32)NULL; + + prog_load_info->env_end = (uint32)p; + + return (uint32)sp; +} + diff --git a/nuttx/binfmt/libnxflat/libnxflat_verify.c b/nuttx/binfmt/libnxflat/libnxflat_verify.c new file mode 100644 index 000000000..b31994b8b --- /dev/null +++ b/nuttx/binfmt/libnxflat/libnxflat_verify.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * nxflat/lib/nxflat_stack.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define V_MAP (load_info->vtbl->map) +#define V_UNMAP (load_info->vtbl->unmap) +#define V_ALLOC (load_info->vtbl->alloc) +#define V_FREE (load_info->vtbl->free) +#define V_OPEN (load_info->vtbl->open) +#define V_READ (load_info->vtbl->read) +#define V_CLOSE (load_info->vtbl->close) + +#define XFLT_HDR_SIZE sizeof(struct nxflat_hdr_s) + +#ifndef MAX +# define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxflat_verifyheader + ****************************************************************************/ + +int nxflat_verifyheader(const struct nxflat_hdr_s *header) +{ + uint16 revision; + + if (!header) + { + dbg("NULL NXFLAT header!"); + return -ENOEXEC; + } + + /* Check the FLT header -- magic number and revision. + * + * If the the magic number does not match. Just return + * silently. This is not our binary. + */ + + if (strncmp(header->h_magic, "NXFLAT", 4) != 0) + { + dbg("Unrecognized magic=\"%c%c%c%c\"", + header->h_magic[0], header->h_magic[1], + header->h_magic[2], header->h_magic[3]); + return -ENOEXEC; + } + + /* Complain a little more if the version does not match. */ + + revision = ntohs(header->h_rev); + if (revision != NXFLAT_VERSION_CURRENT) + { + dbg("Unsupported NXFLAT version=%d\n", revision); + return -ENOEXEC; + } + return 0; +} + -- cgit v1.2.3