summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c97613f)
raw | patch | inline | side by side (parent: c97613f)
author | unknown <a0216664@.dhcp.itg.ti.com> | |
Fri, 1 Oct 2010 12:18:01 +0000 (08:18 -0400) | ||
committer | unknown <a0216664@.dhcp.itg.ti.com> | |
Fri, 1 Oct 2010 12:18:01 +0000 (08:18 -0400) |
15 files changed:
src/interp/elf/ArrayList.c | [new file with mode: 0644] | patch | blob |
src/interp/elf/ArrayList.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/dload.c | [new file with mode: 0644] | patch | blob |
src/interp/elf/dload.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/dload_api.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/dload_endian.c | [new file with mode: 0644] | patch | blob |
src/interp/elf/dload_endian.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/dlw_client.c | [new file with mode: 0644] | patch | blob |
src/interp/elf/elf32.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/elfwrap.c | [new file with mode: 0644] | patch | blob |
src/interp/elf/ewrap.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/file_ovr.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/ibl_elf.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/util.h | [new file with mode: 0644] | patch | blob |
src/interp/elf/version.h | [new file with mode: 0644] | patch | blob |
diff --git a/src/interp/elf/ArrayList.c b/src/interp/elf/ArrayList.c
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+* ArrayList.c
+*
+* Array_List is a C implementation of a C++ vector class.
+*
+* This class emulates a resizable array along the lines of a C++
+* vector or Java ArrayList class in C, and uses the convention
+* of passing a pointer to the current "object" as the first
+* argument.
+*
+* Usage is defined as follows:
+*
+* Array_List obj;
+* AL_initialize(&obj, sizeof(type_name));
+*
+* ...
+*
+* type_name *ptr = (type_name*)(obj.buf);
+* for(i = 0; i < AL_size(&obj); i++)
+* do_something_to(ptr[i]);
+* type_name to_append = ...;
+* AL_append(&obj, &to_append);
+*
+* ...
+*
+* AL_destroy(&obj);
+*
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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 <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ArrayList.h"
+#include "ewrap.h"
+#include "dload_api.h"
+
+/*****************************************************************************/
+/* AL_INITIALIZE() - Initialize a newly created Array_List object. */
+/*****************************************************************************/
+void AL_initialize(Array_List* obj, int32_t type_size, int32_t num_elem)
+{
+ if (num_elem == 0) num_elem = 1;
+ obj->buf = DLIF_malloc(type_size * num_elem);
+ obj->type_size = type_size;
+ obj->size = 0;
+ obj->buffer_size = num_elem;
+}
+
+/*****************************************************************************/
+/* AL_APPEND() - Append an element to the end of an Array_List. */
+/*****************************************************************************/
+void AL_append(Array_List* obj, void* to_append)
+{
+ /*------------------------------------------------------------------------*/
+ /* If there is already space in the specified buffer for the new data, */
+ /* just append it to the end of the data that is already in the buffer. */
+ /*------------------------------------------------------------------------*/
+ if (obj->size < obj->buffer_size)
+ memcpy(((uint8_t*)obj->buf) + obj->type_size * ((obj->size)++), to_append,
+ obj->type_size);
+
+ /*------------------------------------------------------------------------*/
+ /* Grow the buffer if we need more space to add the new data to it. */
+ /*------------------------------------------------------------------------*/
+ else
+ {
+ void* old_buffer = obj->buf;
+ obj->buffer_size *= 2;
+ obj->buf = DLIF_malloc(obj->buffer_size*obj->type_size);
+ memcpy(obj->buf,old_buffer,obj->size*obj->type_size);
+ DLIF_free(old_buffer);
+ memcpy(((uint8_t*)obj->buf) + obj->type_size *((obj->size)++), to_append,
+ obj->type_size);
+ }
+}
+
+/*****************************************************************************/
+/* AL_SIZE() - Get the number of elements in an Array_List. */
+/*****************************************************************************/
+int32_t AL_size(Array_List* obj)
+{
+ return obj->size;
+}
+
+/*****************************************************************************/
+/* AL_DESTROY() - Free up memory associated with an Array_List that is no */
+/* longer in use. */
+/*****************************************************************************/
+void AL_destroy(Array_List* obj)
+{
+ free(obj->buf);
+}
diff --git a/src/interp/elf/ArrayList.h b/src/interp/elf/ArrayList.h
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+* ArrayList.h
+*
+* This implementation of ArrayList is a replacement for the C++
+* vector class in C.
+*
+* This class emulates a resizable array along the lines of a C++
+* vector or Java ArrayList class in C, and uses the convention
+* of passing a pointer to the current "object" as the first
+* argument.
+*
+* Usage is defined as follows:
+*
+* Array_List obj;
+* AL_initialize(&obj, sizeof(type_name));
+*
+* ...
+*
+* type_name *ptr = (type_name*)(obj.buf);
+* for(i = 0; i < AL_size(&obj); i++)
+* do_something_to(ptr[i]);
+* type_name to_append = ...;
+* AL_append(&obj, &to_append);
+*
+* ...
+*
+* AL_destroy(&obj);
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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.
+*
+*/
+
+#ifndef ARRAYLIST_H
+#define ARRAYLIST_H
+
+#include <inttypes.h>
+
+/**********************************************************************/
+/* Array_List - structure type specification. */
+/**********************************************************************/
+typedef struct
+{
+ void *buf;
+ int32_t type_size;
+ int32_t size;
+ int32_t buffer_size;
+} Array_List;
+
+/*--------------------------------------------------------------------*/
+/* Array_List Member Functions: */
+/* */
+/* AL_initialize() - Initialize a newly created Array_List object. */
+/* AL_append() - Append an element to the end of an Array_List. */
+/* AL_size() - Get number of elements in an Array_List. */
+/* AL_destroy() - Free memory associated with an Array_List that is */
+/* no longer in use. */
+/*--------------------------------------------------------------------*/
+void AL_initialize(Array_List* obj, int32_t type_size, int32_t num_elem);
+void AL_append(Array_List* obj, void* to_append);
+int32_t AL_size(Array_List* obj);
+void AL_destroy(Array_List* obj);
+
+#endif
diff --git a/src/interp/elf/dload.c b/src/interp/elf/dload.c
--- /dev/null
+++ b/src/interp/elf/dload.c
@@ -0,0 +1,2992 @@
+/*
+* dload.c
+*
+* Core Dynamic Loader Reference Implementation
+*
+* This implementation of the core dynamic loader is platform independent,
+* but it is object file format dependent. In particular, this
+* implementation supports ELF object file format.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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 <limits.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "ewrap.h"
+#include "elf32.h"
+#include "dload.h"
+#include "dload_api.h"
+
+#if 0
+
+#include "ArrayList.h"
+#include "Queue.h"
+
+#include "symtab.h"
+#include "dload_endian.h"
+#include "elf32.h"
+#include "dload.h"
+#include "relocate.h"
+#include "dload_api.h"
+
+#ifdef ARM_TARGET
+#include "arm_dynamic.h"
+#endif
+
+#ifdef C60_TARGET
+#include "c60_dynamic.h"
+#endif
+
+#endif
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Identify target supported by this implementation of the core loader. */
+/*---------------------------------------------------------------------------*/
+int DLOAD_TARGET_MACHINE = DLOAD_DEFAULT_TARGET_MACHINE;
+
+#if 0
+/*---------------------------------------------------------------------------*/
+/* Contains filenames (type const char*) the system is in the process of */
+/* loading. Used to detect cycles in incorrectly compiled ELF binaries. */
+/*---------------------------------------------------------------------------*/
+Array_List DLIMP_module_dependency_list;
+
+/*---------------------------------------------------------------------------*/
+/* Contains objects (type DLIMP_Loaded_Module) that the system has loaded into */
+/* target memory. */
+/*---------------------------------------------------------------------------*/
+TYPE_QUEUE_IMPLEMENTATION(DLIMP_Loaded_Module*, loaded_module_ptr)
+loaded_module_ptr_Queue DLIMP_loaded_objects;
+
+/*---------------------------------------------------------------------------*/
+/* Dependency Graph Queue - FIFO queue of dynamic modules that are loaded */
+/* when client asks to load a dynamic executable or library. Note that */
+/* dependents that have already been loaded with another module will not */
+/* appear on this queue. */
+/*---------------------------------------------------------------------------*/
+TYPE_STACK_IMPLEMENTATION(DLIMP_Dynamic_Module*, dynamic_module_ptr)
+dynamic_module_ptr_Stack DLIMP_dependency_stack;
+
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Counter for generating unique IDs for file handles. */
+/* NOTE: File handle is assigned sequencially but is never reclaimed */
+/* when the modules are unloaded. It is conceivable that a loader */
+/* running for a long time and loading and unloading modules could */
+/* wrap-around. The loader generates error in this case. */
+/*---------------------------------------------------------------------------*/
+static int32_t file_handle = 1;
+
+/*---------------------------------------------------------------------------*/
+/* Support for profiling performance of dynamic loader core. */
+/*---------------------------------------------------------------------------*/
+#if LOADER_DEBUG
+static clock_t cycle0 = 0;
+static clock_t cycle_end = 0;
+#define profile_start_clock() (cycle0 = clock())
+#define profile_stop_clock() (cycle_end = clock())
+#define profile_cycle_count() (cycle_end - cycle0)
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* DLIMP_get_first_dyntag() */
+/* */
+/* Return value for first tag entry in the given dynamic table whose */
+/* tag type matches the given key. */
+/* */
+/*****************************************************************************/
+uint32_t DLIMP_get_first_dyntag(int tag, struct Elf32_Dyn* dyn_table)
+{
+ /*------------------------------------------------------------------------*/
+ /* Spin through dynamic segment looking for a specific dynamic tag. */
+ /* Return the value associated with the tag, if the tag is found. */
+ /*------------------------------------------------------------------------*/
+ struct Elf32_Dyn *dtp = dyn_table;
+ while (dtp->d_tag != DT_NULL)
+ {
+ if (dtp->d_tag == tag) return dtp->d_un.d_val;
+ else dtp++;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Tag wasn't found, return a known bogus value for the tag. */
+ /*------------------------------------------------------------------------*/
+ return INT_MAX;
+}
+
+#endif
+
+#if 0
+/*****************************************************************************/
+/* dload_and_allocate_dependencies() */
+/* */
+/* If not already loaded, load each dependent file identified in the */
+/* dynamic segment with a DT_NEEDED tag. Dependent files are listed in */
+/* order and should be loaded in the same order that they appear in the */
+/* dynamic segment. */
+/* */
+/*****************************************************************************/
+static BOOL dload_and_allocate_dependencies(DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* Spin through each dynamic tag entry in the dynamic segment. */
+ /*------------------------------------------------------------------------*/
+ struct Elf32_Dyn* dyn_nugget = dyn_module->dyntab;
+
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Starting dload_and_allocate_dependencies() for %s ...\n",
+ dyn_module->name);
+#endif
+
+ while(dyn_nugget->d_tag != DT_NULL)
+ {
+ /*---------------------------------------------------------------------*/
+ /* For each DT_NEEDED dynamic tag that we find in the dynamic segment, */
+ /* load the dependent file identified by the so_name value attached */
+ /* to the DT_NEEDED dynamic tag. */
+ /*---------------------------------------------------------------------*/
+ if (dyn_nugget->d_tag == DT_NEEDED)
+ {
+ loaded_module_ptr_Queue_Node* ptr;
+
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Found DT_NEEDED: %s\n",
+ dyn_module->strtab+dyn_nugget->d_un.d_val);
+#endif
+
+ /*------------------------------------------------------------------*/
+ /* Find out if the file named by the DT_NEEDED tag has already */
+ /* been loaded. If it has, then we only have to bump the use count */
+ /* of the named dependent file. */
+ /*------------------------------------------------------------------*/
+ for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL;
+ ptr = ptr->next_ptr)
+ {
+ if (!strcmp(ptr->value->name,
+ dyn_module->strtab + dyn_nugget->d_un.d_val))
+ {
+ ptr->value->use_count++;
+ AL_append(&(dyn_module->loaded_module->dependencies),
+ &(ptr->value->file_handle));
+ break;
+ }
+ }
+
+ /*------------------------------------------------------------------*/
+ /* If the named dependent file has not been loaded, then we ask the */
+ /* client to invoke a load of the dependent file on our behalf. */
+ /*------------------------------------------------------------------*/
+ if (ptr == NULL)
+ {
+ int32_t dependent_handle = DLIF_load_dependent(dyn_module->strtab +
+ dyn_nugget->d_un.d_val);
+ AL_append(&(dyn_module->loaded_module->dependencies),
+ &dependent_handle);
+ if (dependent_handle == 0) return FALSE;
+ }
+ }
+
+ dyn_nugget++;
+ }
+
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Finished dload_and_allocate_dependencies() for %s\n",
+ dyn_module->name);
+#endif
+
+ return TRUE;
+}
+
+#endif
+
+/*****************************************************************************/
+/* load_object() */
+/* */
+/* Finish the process of loading an object file. */
+/* */
+/*****************************************************************************/
+static int load_object(LOADER_FILE_DESC *fd, DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* With the dynamic loader already running on the target, we are able to */
+ /* relocate directly into target memory, so there is nothing more to be */
+ /* done (at least in the bare-metal dynamic linking ABI model). */
+ /*------------------------------------------------------------------------*/
+ return 1;
+}
+
+#if 1
+/*****************************************************************************/
+/* initialize_loaded_module() */
+/* */
+/* Initialize DLIMP_Loaded_Module internal data object associated with a */
+/* dynamic module. This function will also set up a queue of */
+/* DLIMP_Loaded_Segment(s) associated with the loaded module. */
+/* This function is called as we are getting ready to actually load the */
+/* object file contents into target memory. Each segment will get a */
+/* target memory request that it can use to ask the client for target */
+/* memory space. This function will also assign a file handle to the */
+/* loaded module. */
+/* */
+/*---------------------------------------------------------------------------*/
+/* */
+/* In applications that use the DSBT model, this function will also need to */
+/* negotiate the module's DSBT index with the client. */
+/* */
+/*****************************************************************************/
+static void initialize_loaded_module(DLIMP_Dynamic_Module *dyn_module)
+{
+ int i;
+
+ /*------------------------------------------------------------------------*/
+ /* Allocate a DLIMP_Loaded_Module data structure for the specified ELF */
+ /* file and assign a file handle for it (bumping the file handle counter */
+ /* as we go). */
+ /*------------------------------------------------------------------------*/
+ DLIMP_Loaded_Module *loaded_module =
+ dyn_module->loaded_module = DLIF_malloc(sizeof(DLIMP_Loaded_Module));
+
+#if LOADER_DEBUG || LOADER_PROFILE
+ /*------------------------------------------------------------------------*/
+ /* Start clock on initialization of loaded module object. */
+ /*------------------------------------------------------------------------*/
+ if (debugging_on || profiling_on)
+ {
+ printf("Starting initialize_loaded_module() ...\n");
+ if (profiling_on) profile_start_clock();
+ }
+#endif
+
+ loaded_module->name = DLIF_malloc(strlen(dyn_module->name) + 1);
+ strcpy(loaded_module->name, dyn_module->name);
+
+ loaded_module->file_handle = file_handle++;
+ loaded_module->direct_dependent_only = dyn_module->direct_dependent_only;
+ loaded_module->use_count = 1;
+
+ /*------------------------------------------------------------------------*/
+ /* In case we wrapped around the file handle, return error. */
+ /*------------------------------------------------------------------------*/
+ if (file_handle == 0)
+ DLIF_error(DLET_MISC, "DLOAD File handle overflowed.\n");
+
+ /*------------------------------------------------------------------------*/
+ /* Initially the loaded module does not have access to its global */
+ /* symbols. These need to be copied from the dynamic module (see call */
+ /* to DLSYM_copy_globals() below). */
+ /* */
+ /* THESE INITIALIZATIONS SHOULD BE MOVED TO AN INIT ROUTINE FOR THE */
+ /* LOADED MODULE */
+ /*------------------------------------------------------------------------*/
+ loaded_module->gsymtab = NULL;
+ loaded_module->gstrtab = NULL;
+ loaded_module->gsymnum = loaded_module->gstrsz = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Initialize the Array_List of dependencies. */
+ /*------------------------------------------------------------------------*/
+ AL_initialize(&(loaded_module->dependencies), sizeof(int), 1);
+
+ if (dyn_module->symtab)
+ DLSYM_copy_globals(dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Initialize the module loaded segments Array_List. */
+ /*------------------------------------------------------------------------*/
+ AL_initialize(&(loaded_module->loaded_segments),
+ sizeof(DLIMP_Loaded_Segment), dyn_module->phnum);
+
+ /*------------------------------------------------------------------------*/
+ /* Spin thru segment headers and process each load segment encountered. */
+ /*------------------------------------------------------------------------*/
+ for (i = 0; i < dyn_module->phnum; i++)
+ if (dyn_module->phdr[i].p_type == PT_LOAD)
+ {
+ /*------------------------------------------------------------------*/
+ /* Note that this is parallel to and does not supplant the ELF */
+ /* phdr tables. */
+ /*------------------------------------------------------------------*/
+ DLIMP_Loaded_Segment seg;
+ seg.obj_desc = DLIF_malloc(sizeof(struct DLOAD_MEMORY_SEGMENT));
+ seg.phdr.p_vaddr = dyn_module->phdr[i].p_vaddr;
+ seg.phdr.p_offset = dyn_module->phdr[i].p_offset;
+ seg.obj_desc->target_page = 0; /*not used*/
+ seg.modified = 0;
+ seg.phdr.p_filesz = seg.obj_desc->objsz_in_bytes
+ = dyn_module->phdr[i].p_filesz;
+ seg.phdr.p_memsz = seg.obj_desc->memsz_in_bytes
+ = dyn_module->phdr[i].p_memsz;
+ seg.phdr.p_align = dyn_module->phdr[i].p_align;
+ seg.phdr.p_flags = dyn_module->phdr[i].p_flags;
+ seg.reloc_offset = 0;
+ AL_append(&(loaded_module->loaded_segments), &seg);
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Initialize the DSO termination information for this module. */
+ /* It will be copied over from the enclosing dyn_module object when */
+ /* placement is completed and dyn_module's local copy of the dynamic */
+ /* table is updated. */
+ /*------------------------------------------------------------------------*/
+ loaded_module->fini_array = NULL;
+ loaded_module->fini_arraysz = 0;
+ loaded_module->fini = NULL;
+
+#if LOADER_DEBUG || LOADER_PROFILE
+ if (debugging_on || profiling_on)
+ {
+ printf("Finished initialize_loaded_module()\n");
+ if (profiling_on)
+ {
+ profile_stop_clock();
+ printf("Took %d cycles.\n", profile_cycle_count());
+ }
+ }
+#endif
+
+}
+#endif
+
+/*****************************************************************************/
+/* load_static_segment() */
+/* */
+/* The core dynamic loader requires that a statically linked executable */
+/* be placed in target memory at the location that was determined during */
+/* the static link that created the executable. Failure to get the */
+/* required target memory where the static executable is to be loaded */
+/* will cause the dynamic loader to emit an error and abort the load. */
+/* */
+/*****************************************************************************/
+static BOOL load_static_segment(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ int i;
+ DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
+ (dyn_module->loaded_module->loaded_segments.buf);
+
+ /*------------------------------------------------------------------------*/
+ /* For each segment in the loaded module, build up a target memory */
+ /* request for the segment, get rights to target memory where we want */
+ /* to load the segment from the client, then get the client to write the */
+ /* segment contents out to target memory to the appropriate address. */
+ /*------------------------------------------------------------------------*/
+ for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
+ {
+ struct DLOAD_MEMORY_REQUEST targ_req;
+ seg[i].obj_desc->target_page = 0;
+ targ_req.flags = 0;
+
+ /*---------------------------------------------------------------------*/
+ /* This is a static executable. DLIF_allocate should give us the */
+ /* address we ask for or fail. */
+ /*---------------------------------------------------------------------*/
+ if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
+
+ targ_req.align = seg[i].phdr.p_align;
+ seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
+ targ_req.flags &= ~DLOAD_SF_relocatable;
+ targ_req.fp = fd;
+ targ_req.segment = seg[i].obj_desc;
+ targ_req.offset = seg[i].phdr.p_offset;
+ targ_req.flip_endian = dyn_module->wrong_endian;
+
+ /*---------------------------------------------------------------------*/
+ /* Ask the client side of the dynamic loader to allocate target memory */
+ /* for this segment to be loaded into. */
+ /*---------------------------------------------------------------------*/
+ if (!DLIF_allocate(&targ_req)) return FALSE;
+
+ /*---------------------------------------------------------------------*/
+ /* If there is any initialized data in the segment, we'll first write */
+ /* it into a host writable buffer (DLIF_copy()) and then flush it to */
+ /* target memory. */
+ /*---------------------------------------------------------------------*/
+ if (seg[i].phdr.p_filesz)
+ {
+ DLIF_copy(&targ_req);
+ DLIF_write(&targ_req);
+ }
+ }
+
+ return TRUE;
+}
+
+#if 0
+/*****************************************************************************/
+/* relocate_target_dynamic_tag_info() */
+/* */
+/* Update a target specific dynamic tag value that happens to be a */
+/* virtual address of a section. Returns TRUE if the tag was updated or */
+/* is not a virtual address and FALSE if it was not successfully updated */
+/* or was not recognized. */
+/*****************************************************************************/
+static BOOL relocate_target_dynamic_tag_info(DLIMP_Dynamic_Module *dyn_module,
+ int i)
+{
+#ifdef ARM_TARGET
+ if (is_arm_module(&dyn_module->fhdr))
+ return DLDYN_arm_relocate_dynamic_tag_info(dyn_module, i);
+#endif
+
+#ifdef C60_TARGET
+ if (is_c60_module(&dyn_module->fhdr))
+ return DLDYN_c60_relocate_dynamic_tag_info(dyn_module, i);
+#endif
+
+ return FALSE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* DLIMP_update_dyntag_section_address() */
+/* */
+/* Given the index of a dynamic tag which we happen to know points to a */
+/* section address, find the program header table entry associated with */
+/* the specified address and update the tag value with the real address */
+/* of the section. */
+/* */
+/*****************************************************************************/
+BOOL DLIMP_update_dyntag_section_address(DLIMP_Dynamic_Module *dyn_module,
+ int32_t i)
+{
+ int j;
+ DLIMP_Loaded_Segment *seg = (DLIMP_Loaded_Segment *)
+ (dyn_module->loaded_module->loaded_segments.buf);
+ for (j = 0; j < dyn_module->loaded_module->loaded_segments.size; j++)
+ {
+ if ((dyn_module->dyntab[i].d_un.d_ptr >= seg[j].input_vaddr) &&
+ (dyn_module->dyntab[i].d_un.d_ptr <
+ (seg[j].input_vaddr + seg[j].phdr.p_memsz)))
+ {
+ dyn_module->dyntab[i].d_un.d_ptr +=
+ (seg[j].phdr.p_vaddr - seg[j].input_vaddr);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* relocate_dynamic_tag_info() */
+/* */
+/* Once segment allocation has been completed, we'll need to go through */
+/* the dynamic table and update any tag values that happen to be virtual */
+/* addresses of segments (DT_C6000_DSBT_BASE, for example). */
+/* */
+/*****************************************************************************/
+static BOOL relocate_dynamic_tag_info(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* Spin through dynamic table loking for tags that have a value which is */
+ /* the virtual address of a section. After the sections are allocated, */
+ /* we'll need to update these values with the new address of the section. */
+ /*------------------------------------------------------------------------*/
+ int i;
+ for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
+ {
+ switch (dyn_module->dyntab[i].d_tag)
+ {
+ /*------------------------------------------------------------------*/
+ /* Only tag values that are virtual addresses will be affected. */
+ /*------------------------------------------------------------------*/
+ case DT_NEEDED:
+ case DT_PLTRELSZ:
+ case DT_HASH:
+ case DT_STRTAB:
+ case DT_SYMTAB:
+ case DT_RELA:
+ case DT_RELASZ:
+ case DT_RELAENT:
+ case DT_STRSZ:
+ case DT_SYMENT:
+ case DT_SONAME:
+ case DT_RPATH:
+ case DT_SYMBOLIC:
+ case DT_REL:
+ case DT_RELSZ:
+ case DT_RELENT:
+ case DT_PLTREL:
+ case DT_DEBUG:
+ case DT_TEXTREL:
+ case DT_BIND_NOW:
+ case DT_INIT_ARRAYSZ:
+ case DT_RUNPATH:
+ case DT_FLAGS:
+ case DT_PREINIT_ARRAYSZ:
+ continue;
+
+ /*------------------------------------------------------------------*/
+ /* NOTE!!! */
+ /* case DT_ENCODING: -- tag type has same "id" as DT_PREINIT_ARRAY */
+ /*------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------*/
+ /* This is a generic dynamic tag whose value is a virtual address */
+ /* of a section. It needs to be relocated to the section's actual */
+ /* address in target memory. */
+ /*------------------------------------------------------------------*/
+ case DT_PREINIT_ARRAY:
+ case DT_INIT:
+ case DT_INIT_ARRAY:
+ if (!DLIMP_update_dyntag_section_address(dyn_module, i))
+ return FALSE;
+
+ continue;
+
+ /*------------------------------------------------------------------*/
+ /* Once we have resolved the actual address of termination function */
+ /* sections, we need to copy their addresses over to the loaded */
+ /* module object (dyn_module will be deleted before we get to */
+ /* unloading the module). */
+ /*------------------------------------------------------------------*/
+ case DT_FINI_ARRAY:
+ case DT_FINI:
+ if (!DLIMP_update_dyntag_section_address(dyn_module, i))
+ return FALSE;
+
+ if (dyn_module->dyntab[i].d_tag == DT_FINI)
+ dyn_module->loaded_module->fini =
+ dyn_module->dyntab[i].d_un.d_ptr;
+ else
+ dyn_module->loaded_module->fini_array =
+ dyn_module->dyntab[i].d_un.d_ptr;
+
+ continue;
+
+ case DT_FINI_ARRAYSZ:
+ dyn_module->loaded_module->fini_arraysz =
+ dyn_module->dyntab[i].d_un.d_val;
+ continue;
+
+ /*------------------------------------------------------------------*/
+ /* Is this a virtual address??? */
+ /*------------------------------------------------------------------*/
+ case DT_JMPREL: /* is this a virtual address??? */
+ continue;
+
+ /*------------------------------------------------------------------*/
+ /* The remaining dynamic tag types should be target specific. If */
+ /* something generic slips through to here, then the handler for */
+ /* relocating target specific dynamic tags should fail. */
+ /*------------------------------------------------------------------*/
+ default:
+ if (!relocate_target_dynamic_tag_info(dyn_module, i))
+ return FALSE;
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* We've gotten through all of the dynamic table without incident. */
+ /* All dynamic tag values that were virtual section addresses should have */
+ /* been updated with the final address of the section that they point to. */
+ /*------------------------------------------------------------------------*/
+ return TRUE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* allocate_dynamic_segments_and relocate_symbols() */
+/* */
+/* Allocate target memory for each segment in this module, getting a */
+/* host-accessible space to copy the content of each segment into. Then */
+/* update the symbol table and program header table to reflect the new */
+/* target address for each segment. Processing of the dynamic relocation */
+/* entries will wait until all dependent files have been loaded and */
+/* allocated into target memory. */
+/* */
+/*---------------------------------------------------------------------------*/
+/* */
+/* The relocation entries in the ELF file do not handle the necessary */
+/* adjustments to the memory addresses in the program header or symbol */
+/* tables. These must be done manually. */
+/* */
+/* This is harder for us than for most dynamic loaders, because we have to */
+/* work in environments without virtual memory and thus where the offsets */
+/* between segments in memory may be different than they were in the file. */
+/* So, even though a dynamic loader usually only has to adjust all the */
+/* segments by a single fixed offset, we need to offset the symbols and */
+/* program header addresses segment by segment. This job is done by the */
+/* function below. */
+/* */
+/*****************************************************************************/
+static BOOL allocate_dynamic_segments_and_relocate_symbols
+ (LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ int i,j;
+ DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
+ (dyn_module->loaded_module->loaded_segments.buf);
+ struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
+
+#if LOADER_DEBUG || LOADER_PROFILE
+ if (debugging_on || profiling_on)
+ {
+ printf("Dynamic executable found.\n"
+ "Starting allocate_dynamic_segments_and_relocate_symbols() ...\n");
+ if (profiling_on) profile_start_clock();
+ }
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Spin through the list of loaded segments from the current module. */
+ /*------------------------------------------------------------------------*/
+ for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
+ {
+ /*--------------------------------------------------------------------*/
+ /* Allocate target memory for segment via client-provided target */
+ /* memory API. */
+ /*--------------------------------------------------------------------*/
+ int32_t addr_offset;
+ struct DLOAD_MEMORY_REQUEST targ_req;
+ seg[i].obj_desc->target_page = 0;
+ targ_req.flags = 0;
+ if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
+ targ_req.align = 0x20;
+ seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
+ targ_req.flags |= DLOAD_SF_relocatable;
+ targ_req.fp = fd;
+ targ_req.segment = seg[i].obj_desc;
+ targ_req.offset = seg[i].phdr.p_offset;
+ targ_req.flip_endian = dyn_module->wrong_endian;
+
+ if (!DLIF_allocate(&targ_req))
+ {
+ DLIF_error(DLET_MEMORY, "DLIF allocation failure.\n");
+ return FALSE;
+ }
+
+ /*--------------------------------------------------------------------*/
+ /* Calculate the offset we need to adjust segment header and symbol */
+ /* table addresses. */
+ /*--------------------------------------------------------------------*/
+ addr_offset = (int32_t)(seg[i].obj_desc->target_address) -
+ (int32_t)(seg[i].phdr.p_vaddr);
+
+#if LOADER_DEBUG
+ if (debugging_on)
+ {
+ printf("Segment %d (at 0x%x, 0x%x bytes) relocated to 0x%x\n", i,
+ (int32_t)(seg[i].phdr.p_vaddr),
+ (int32_t)(seg[i].phdr.p_memsz),
+ (int32_t)(seg[i].obj_desc->target_address));
+ printf( "Addr Offset is 0x%x\n", addr_offset);
+ }
+#endif
+
+ /*--------------------------------------------------------------------*/
+ /* Update program entry point if needed. Need to replace to deal */
+ /* with full ELF initialization routine. */
+ /*--------------------------------------------------------------------*/
+ if (dyn_module->relocate_entry_point &&
+ fhdr->e_entry >= (Elf32_Addr)(seg[i].phdr.p_vaddr) &&
+ fhdr->e_entry <
+ (Elf32_Addr)((uint8_t*)(seg[i].phdr.p_vaddr) +
+ (uint32_t)(seg[i].phdr.p_memsz)))
+ {
+#if LOADER_DEBUG
+ if (debugging_on)
+ {
+ printf("Entry point 0x%x relocated to 0x%x\n",
+ fhdr->e_entry, fhdr->e_entry + addr_offset);
+ }
+#endif
+ fhdr->e_entry += addr_offset;
+
+ /*------------------------------------------------------------------*/
+ /* Mark the entry point as being relocated so we will not do it */
+ /* again. */
+ /*------------------------------------------------------------------*/
+ dyn_module->relocate_entry_point = FALSE;
+ }
+
+ /*---------------------------------------------------------------------*/
+ /* Fix program header entries in segment and Elf32_Phdr structs. */
+ /*---------------------------------------------------------------------*/
+ for (j = 0; j < fhdr->e_phnum; j++)
+ if (dyn_module->phdr[j].p_vaddr == (Elf32_Addr)seg[i].phdr.p_vaddr)
+ {
+ dyn_module->phdr[j].p_vaddr += addr_offset;
+ dyn_module->phdr[i].p_paddr += addr_offset;
+ break;
+ }
+
+ seg[i].input_vaddr = (Elf32_Addr)(seg[i].phdr.p_vaddr);
+ seg[i].phdr.p_vaddr += addr_offset;
+
+ /*---------------------------------------------------------------------*/
+ /* Great, now the hard part: fix offsets in symbols. It would be nice */
+ /* if there were an easier way to deal with this. */
+ /*---------------------------------------------------------------------*/
+ {
+ struct Elf32_Sym *gsymtab =
+ ((struct Elf32_Sym*)(dyn_module->loaded_module->gsymtab));
+ Elf32_Addr segment_start = (Elf32_Addr)seg[i].phdr.p_vaddr;
+ Elf32_Addr segment_end = (Elf32_Addr)seg[i].phdr.p_vaddr +
+ seg[i].phdr.p_memsz;
+ Elf32_Word global_index = dyn_module->symnum -
+ dyn_module->loaded_module->gsymnum;
+
+ for (j = 0; j < dyn_module->symnum; j++)
+ {
+ /*---------------------------------------------------------------*/
+ /* Get the relocated symbol value. */
+ /*---------------------------------------------------------------*/
+ Elf32_Addr symval_adj = dyn_module->symtab[j].st_value + addr_offset;
+
+ /*---------------------------------------------------------------*/
+ /* If the symbol is defined in this segment, update the symbol */
+ /* value and mark the symbol so that we don't relocate it again. */
+ /*---------------------------------------------------------------*/
+ if (symval_adj >= segment_start && symval_adj < segment_end &&
+ dyn_module->symtab[j].st_shndx != INT16_MAX)
+ {
+ dyn_module->symtab[j].st_value = symval_adj;
+
+ /*------------------------------------------------------------*/
+ /* The module symbol table only has the global symbols. */
+ /*------------------------------------------------------------*/
+ if (j >= global_index)
+ gsymtab[j-global_index].st_value = symval_adj;
+
+ /*------------------------------------------------------------*/
+ /* Mark the symbol as relocated. */
+ /*------------------------------------------------------------*/
+ dyn_module->symtab[j].st_shndx = INT16_MAX;
+ }
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Update dynamic tag information. Some dynamic tags have values which */
+ /* are virtual addresses of sections. These values need to be updated */
+ /* once segment allocation is completed and the new segment addresses are */
+ /* known. */
+ /*------------------------------------------------------------------------*/
+ /* We should only traverse through the dynamic table once because we want */
+ /* to avoid the possibility of updating the same tag multiple times (an */
+ /* error, if it happens). */
+ /*------------------------------------------------------------------------*/
+ if (!relocate_dynamic_tag_info(fd, dyn_module))
+ {
+ DLIF_error(DLET_MISC, "Failed dynamic table update.\n");
+ return FALSE;
+ }
+
+#if LOADER_DEBUG || LOADER_PROFILE
+ if (debugging_on || profiling_on)
+ {
+ printf("Finished allocate_dynamic_segments_and_relocate_symbols()\n");
+ if (profiling_on)
+ {
+ profile_stop_clock();
+ printf("Took %d cycles.\n", profile_cycle_count());
+ }
+ }
+#endif
+
+ return TRUE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* delete_DLIMP_Loaded_Module() */
+/* */
+/* Free host memory associated with a DLIMP_Loaded_Module data structure */
+/* and all of the DLIMP_Loaded_Segment objects that are associated with */
+/* it. */
+/* */
+/*****************************************************************************/
+static void delete_DLIMP_Loaded_Module(DLIMP_Loaded_Module **pplm)
+{
+ DLIMP_Loaded_Module *loaded_module = *pplm;
+ DLIMP_Loaded_Segment *segments = (DLIMP_Loaded_Segment*)
+ (loaded_module->loaded_segments.buf);
+
+ /*-----------------------------------------------------------------------*/
+ /* Spin through the segments attached to this loaded module, freeing up */
+ /* any target memory that was allocated by the client for the segment. */
+ /*-----------------------------------------------------------------------*/
+ int i;
+ for (i = 0; i < loaded_module->loaded_segments.size; i++)
+ {
+ if (!DLIF_release(segments[i].obj_desc))
+ DLIF_error(DLET_MISC, "Failed call to DLIF_release!\n");;
+ DLIF_free(segments[i].obj_desc);
+ }
+
+ /*----------------------------------------------------------------------*/
+ /* Hacky way of indicating that the base image is no longer available. */
+ /* WHHHHAAAAAAATTT!?!?!?!?!?! */
+ /*----------------------------------------------------------------------*/
+ if (loaded_module->file_handle == DLIMP_application_handle)
+ DLIMP_application_handle = 0;
+
+ /*-----------------------------------------------------------------------*/
+ /* Free host heap memory that was allocated for the internal loaded */
+ /* module data structure members. */
+ /*-----------------------------------------------------------------------*/
+ if (loaded_module->name) DLIF_free(loaded_module->name);
+ if (loaded_module->gsymtab) DLIF_free(loaded_module->gsymtab);
+ loaded_module->gsymnum = 0;
+ if (loaded_module->gstrtab) DLIF_free(loaded_module->gstrtab);
+ loaded_module->gstrsz = 0;
+ AL_destroy(&(loaded_module->loaded_segments));
+ AL_destroy(&(loaded_module->dependencies));
+
+ /*-----------------------------------------------------------------------*/
+ /* Finally, free the host memory for the loaded module object, then NULL */
+ /* the pointer that was passed in. */
+ /*-----------------------------------------------------------------------*/
+ DLIF_free(loaded_module);
+ *pplm = NULL;
+}
+
+#endif
+
+/*****************************************************************************/
+/* new_DLIMP_Dynamic_Module() */
+/* */
+/* Allocate a dynamic module data structure from host memory and */
+/* initialize its members to their default values. */
+/* */
+/*****************************************************************************/
+static DLIMP_Dynamic_Module *new_DLIMP_Dynamic_Module(LOADER_FILE_DESC *fd)
+{
+ /*-----------------------------------------------------------------------*/
+ /* Allocate space for dynamic module data structure from host memory. */
+ /*-----------------------------------------------------------------------*/
+ DLIMP_Dynamic_Module *dyn_module =
+ (DLIMP_Dynamic_Module *)DLIF_malloc(sizeof(DLIMP_Dynamic_Module));
+
+ if (!dyn_module)
+ return NULL;
+
+ /*-----------------------------------------------------------------------*/
+ /* Initialize data members of the new dynamic module data structure. */
+ /*-----------------------------------------------------------------------*/
+ dyn_module->name = NULL;
+ dyn_module->fd = fd;
+ dyn_module->phdr = NULL;
+ dyn_module->phnum = 0;
+ dyn_module->strtab = NULL;
+ dyn_module->strsz = 0;
+ dyn_module->dyntab = NULL;
+ dyn_module->symtab = NULL;
+ dyn_module->symnum = 0;
+ dyn_module->gsymtab_offset = 0;
+ dyn_module->gstrtab_offset = 0;
+ dyn_module->c_args = NULL;
+ dyn_module->argc = 0;
+ dyn_module->argv = NULL;
+ dyn_module->loaded_module = NULL;
+ dyn_module->wrong_endian = 0;
+ dyn_module->direct_dependent_only = TRUE;
+ dyn_module->relocatable = FALSE;
+ dyn_module->relocate_entry_point = TRUE;
+
+ dyn_module->dsbt_size = 0;
+ dyn_module->dsbt_index = DSBT_INDEX_INVALID;
+ dyn_module->dsbt_base_tagidx = -1;
+
+ dyn_module->preinit_array_idx = -1;
+ dyn_module->preinit_arraysz = 0;
+ dyn_module->init_idx = -1;
+ dyn_module->init_array_idx = -1;
+ dyn_module->init_arraysz = 0;
+
+ return dyn_module;
+}
+
+/*****************************************************************************/
+/* detach_loaded_module() */
+/* */
+/* Detach loaded module data structure from given dynamic module. When */
+/* an object file has been successfully loaded, the loader core will */
+/* detach the loaded module data structure from the dynamic module data */
+/* structure because the loaded module must continue to persist until is */
+/* is actually unloaded from target memory. If there is a problem with */
+/* the load, then the host memory associated with the loaded module will */
+/* be released as part of the destruction of the dynamic module. */
+/* */
+/*****************************************************************************/
+static DLIMP_Loaded_Module *detach_loaded_module(DLIMP_Dynamic_Module *dyn_module)
+{
+ if (dyn_module && dyn_module->loaded_module)
+ {
+ DLIMP_Loaded_Module *loaded_module = dyn_module->loaded_module;
+ dyn_module->loaded_module = NULL;
+ return loaded_module;
+ }
+
+ return NULL;
+}
+
+
+#if 0
+/*****************************************************************************/
+/* delete_DLIMP_Dynamic_Module() */
+/* */
+/* Remove local copies of the string table, symbol table, program header */
+/* table, and dynamic table. */
+/* */
+/*****************************************************************************/
+static void delete_DLIMP_Dynamic_Module(DLIMP_Dynamic_Module **ppdm)
+{
+ DLIMP_Dynamic_Module *dyn_module = NULL;
+
+ if (!ppdm || (*ppdm == NULL))
+ {
+ DLIF_error(DLET_MISC,
+ "Internal Error: invalid argument to dynamic module "
+ "destructor function; aborting loader\n");
+ exit(1);
+ }
+
+ dyn_module = *ppdm;
+ if (dyn_module->name) DLIF_free(dyn_module->name);
+ if (dyn_module->strtab) DLIF_free(dyn_module->strtab);
+ if (dyn_module->symtab) DLIF_free(dyn_module->symtab);
+ if (dyn_module->phdr) DLIF_free(dyn_module->phdr);
+ if (dyn_module->dyntab) DLIF_free(dyn_module->dyntab);
+
+ /*------------------------------------------------------------------------*/
+ /* If we left the loaded module attached to the dynamic module, then */
+ /* something must have gone wrong with the load. Remove the loaded */
+ /* module from the queue of loaded modules, if it is there. Then free */
+ /* the host memory allocated to the loaded module and its segments. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->loaded_module != NULL)
+ delete_DLIMP_Loaded_Module(&(dyn_module->loaded_module));
+
+ /*------------------------------------------------------------------------*/
+ /* Finally, free the host memory for this dynamic module object and NULL */
+ /* the pointer to the object. */
+ /*------------------------------------------------------------------------*/
+ DLIF_free(dyn_module);
+ *ppdm = NULL;
+}
+
+#endif
+
+/*****************************************************************************/
+/* file_header_magic_number_is_valid() */
+/* */
+/* Given an object file header, check the magic number to ensure that it */
+/* is an object file format that we recognize. This implementation of */
+/* the dynamic loader core will handle ELF object file format. */
+/* */
+/*****************************************************************************/
+static BOOL file_header_magic_number_is_valid(struct Elf32_Ehdr* header)
+{
+ /*------------------------------------------------------------------------*/
+ /* Check for correct ELF magic numbers in file header. */
+ /*------------------------------------------------------------------------*/
+ if (!header->e_ident[EI_MAG0] == ELFMAG0 ||
+ !header->e_ident[EI_MAG1] == ELFMAG1 ||
+ !header->e_ident[EI_MAG2] == ELFMAG2 ||
+ !header->e_ident[EI_MAG3] == ELFMAG3)
+ {
+ DLIF_error(DLET_FILE, "Invalid ELF magic number.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+/* file_header_machine_is_valid() */
+/* */
+/* Check if the machine specified in the file header is supported by the */
+/* loader. If the loader was compiled with support for all targets, */
+/* the machine will be initially set to EM_NONE. Once a module has been */
+/* loaded, all remaining modules must have the same machine value. */
+/*****************************************************************************/
+static BOOL file_header_machine_is_valid(Elf32_Half e_machine)
+{
+ if (DLOAD_TARGET_MACHINE == EM_NONE)
+ DLOAD_TARGET_MACHINE = e_machine;
+
+ if (e_machine != DLOAD_TARGET_MACHINE)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+/* is_valid_elf_object_file() */
+/* */
+/* Check file size against anticipated end location of string table, */
+/* symbol table, program header tables, etc. If we anything untoward, */
+/* then we declare that the ELF file is corrupt and the load is aborted. */
+/* */
+/*****************************************************************************/
+static BOOL is_valid_elf_object_file(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ uint32_t fsz;
+ int i;
+
+ /*------------------------------------------------------------------------*/
+ /* Get file size. */
+ /*------------------------------------------------------------------------*/
+ DLIF_fseek(fd, 0, LOADER_SEEK_END);
+ fsz = DLIF_ftell(fd);
+
+ /*------------------------------------------------------------------------*/
+ /* Check for invalid table sizes (string table, symbol table, and */
+ /* program header tables). */
+ /*------------------------------------------------------------------------*/
+ if (!((dyn_module->strsz < fsz) &&
+ (dyn_module->symnum < fsz) &&
+ (dyn_module->phnum * sizeof(struct Elf32_Phdr)) < fsz))
+ {
+ DLIF_error(DLET_FILE, "Invalid ELF table bounds.\n");
+ return FALSE;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Check for null so_name string in file with dynamic information. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->dyntab && !strcmp(dyn_module->name, ""))
+ {
+ DLIF_error(DLET_MISC, "Dynamic file lacks SO_NAME identifier.\n");
+ return FALSE;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Check for invalid program header information. */
+ /*------------------------------------------------------------------------*/
+ for (i = 0; i < dyn_module->phnum; i++)
+ {
+ struct Elf32_Phdr* phdr = dyn_module->phdr + i;
+
+ /*---------------------------------------------------------------------*/
+ /* Sanity check for relative sizes of filesz and memsz. */
+ /*---------------------------------------------------------------------*/
+ if (!(phdr->p_type != PT_LOAD || phdr->p_filesz <= phdr->p_memsz))
+ {
+ DLIF_error(DLET_MISC,
+ "Invalid file or memory size for segment %d.\n", i);
+ return FALSE;
+ }
+
+ /*---------------------------------------------------------------------*/
+ /* Check that segment file offset doesn't go off the end of the file. */
+ /*---------------------------------------------------------------------*/
+ if (!(phdr->p_offset + phdr->p_filesz < fsz))
+ {
+ DLIF_error(DLET_FILE,
+ "File location of segment %d is past the end of file.\n", i);
+ return FALSE;
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Check that a ET_DYN-type file is relocatable. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->fhdr.e_type == ET_DYN && !dyn_module->symtab) return FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* All checks passed. */
+ /*------------------------------------------------------------------------*/
+ return TRUE;
+}
+
+/*****************************************************************************/
+/* process_eiosabi() */
+/* */
+/* Check the EI_OSABI field to validate it and set any parameters based on */
+/* it. */
+/*****************************************************************************/
+static BOOL process_eiosabi(DLIMP_Dynamic_Module* dyn_module)
+{
+#if ARM_TARGET
+ if (is_arm_module(&dyn_module->fhdr))
+ return DLDYN_arm_process_eiosabi(dyn_module);
+#endif
+
+#if C60_TARGET
+ if (is_c60_module(&dyn_module->fhdr))
+ return DLDYN_c60_process_eiosabi(dyn_module);
+#endif
+
+ return FALSE;
+}
+/*****************************************************************************/
+/* dload_file_header() */
+/* */
+/* Read ELF file header. Store critical information in the provided */
+/* DLIMP_Dynamic_Module record. Check file header for validity. */
+/* */
+/*****************************************************************************/
+static BOOL dload_file_header(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* Read ELF file header from given input file. */
+ /*------------------------------------------------------------------------*/
+ DLIF_fread(&(dyn_module->fhdr), sizeof(struct Elf32_Ehdr), 1, fd);
+
+ /*------------------------------------------------------------------------*/
+ /* Determine target vs. host endian-ness. Does header data need to be */
+ /* byte swapped? */
+ /*------------------------------------------------------------------------*/
+ dyn_module->wrong_endian =
+ (dyn_module->fhdr.e_ident[EI_DATA] != DLIMP_get_endian());
+
+ /*------------------------------------------------------------------------*/
+ /* Swap file header structures, if needed. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->wrong_endian)
+ DLIMP_change_ehdr_endian(&(dyn_module->fhdr));
+
+ /*------------------------------------------------------------------------*/
+ /* Write out magic ELF information for debug purposes. */
+ /*------------------------------------------------------------------------*/
+ printf("ELF: %c%c%c\n", dyn_module->fhdr.e_ident[1],
+ dyn_module->fhdr.e_ident[2],
+ dyn_module->fhdr.e_ident[3]);
+ printf("ELF file header entry point: %x\n", dyn_module->fhdr.e_entry);
+
+ /*------------------------------------------------------------------------*/
+ /* Verify magic numbers in ELF file header. */
+ /*------------------------------------------------------------------------*/
+ if (!file_header_magic_number_is_valid(&(dyn_module->fhdr)))
+ {
+ DLIF_error(DLET_FILE, "Invalid ELF file header magic number.\n");
+ return 0;
+ }
+
+ if (!file_header_machine_is_valid(dyn_module->fhdr.e_machine))
+ {
+ DLIF_error(DLET_FILE, "Invalid ELF file target machine.\n");
+ return 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Verify file is an executable or dynamic shared object or library. */
+ /*------------------------------------------------------------------------*/
+ if ((dyn_module->fhdr.e_type != ET_EXEC) &&
+ (dyn_module->fhdr.e_type != ET_DYN))
+ {
+ DLIF_error(DLET_FILE, "Invalid ELF file type.\n");
+ return FALSE;
+ }
+
+#if LOADER_DEBUG || LOADER_PROFILE
+ /*------------------------------------------------------------------------*/
+ /* Stop profiling clock when file header information has finished */
+ /* loading. Re-start clock on initialization of symbol table, and */
+ /* dynamic table pointers. */
+ /*------------------------------------------------------------------------*/
+ if (debugging_on || profiling_on)
+ {
+ printf("done.\n");
+ if (profiling_on)
+ {
+ profile_stop_clock();
+ printf("Took %d cycles.\n", profile_cycle_count());
+ profile_start_clock();
+ }
+ }
+#endif
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+/* dload_program_header_table() */
+/* */
+/* Make a local copy of the ELF object file's program header table in the */
+/* dynamic module data structure. */
+/* */
+/*****************************************************************************/
+static void dload_program_header_table(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* Read the program header tables from the object file. */
+ /*------------------------------------------------------------------------*/
+ struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
+ dyn_module->phdr = (struct Elf32_Phdr*)
+ (DLIF_malloc(fhdr->e_phnum * fhdr->e_phentsize));
+ DLIF_fseek(fd, fhdr->e_phoff, LOADER_SEEK_SET);
+ DLIF_fread(dyn_module->phdr, fhdr->e_phentsize, fhdr->e_phnum,fd);
+ dyn_module->phnum = fhdr->e_phnum;
+
+ /*------------------------------------------------------------------------*/
+ /* Byte swap the program header tables if the target endian-ness is not */
+ /* the same as the host endian-ness. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->wrong_endian)
+ {
+ int i;
+ for (i = 0; i < dyn_module->phnum; i++)
+ DLIMP_change_phdr_endian(dyn_module->phdr + i);
+ }
+}
+
+/*****************************************************************************/
+/* dload_headers() */
+/* */
+/* Read ELF object file header and program header table information into */
+/* the given dynamic module data structure. If the object file contains */
+/* dynamic information, read in the dynamic tags, dynamic symbol table, */
+/* and global string table. Check to make sure that we are not already */
+/* in the process of loading the module (circular dependencies), then */
+/* perform some level of sanity checking on the content of the file to */
+/* provide some assurance that the file is not corrupted. */
+/* */
+/*****************************************************************************/
+static BOOL dload_headers(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+#if LOADER_DEBUG || LOADER_PROFILE
+ /*------------------------------------------------------------------------*/
+ /* More progress information. Start timing if profiling is enabled. */
+ /*------------------------------------------------------------------------*/
+ if (debugging_on || profiling_on)
+ {
+ printf("\nReading file headers ...\n");
+ if (profiling_on) profile_start_clock();
+ }
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Read file header information and check vs. expected ELF object file */
+ /* header content. */
+ /*------------------------------------------------------------------------*/
+ if (!dload_file_header(fd, dyn_module))
+ return FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* Read program header table information into the dynamic module object. */
+ /*------------------------------------------------------------------------*/
+ dload_program_header_table(fd, dyn_module);
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+/* find_dynamic_segment() */
+/* */
+/* Find the dynamic segment in the given ELF object file, if there is */
+/* one. If the segment is found, then the segment ID output parameter */
+/* is set to the index of the dynamic segment in the program header */
+/* table. If the dynamic segment is not found, the dynamic module's */
+/* relocatable flag is set to FALSE, and return FALSE. */
+/* */
+/*****************************************************************************/
+static BOOL find_dynamic_segment(DLIMP_Dynamic_Module *dyn_module,
+ Elf32_Word *dyn_seg_idx)
+{
+ int i;
+
+ /*------------------------------------------------------------------------*/
+ /* We should have a valid dynamic module pointer and somewhere to put the */
+ /* dynamic segment id, if we find one. If either of these are missing, */
+ /* we should get an internal error and abort the loader. */
+ /*------------------------------------------------------------------------*/
+ if ((dyn_module == NULL) || (dyn_seg_idx == NULL))
+ {
+ DLIF_error(DLET_MISC, "Internal error: find_dynamic_segment() needs "
+ "non-NULL arguments.\n");
+ exit(1);
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Spin through segment program headers to find the dynamic segment. */
+ /*------------------------------------------------------------------------*/
+ dyn_module->relocatable = TRUE;
+ for (i = 0; i < dyn_module->phnum; i++)
+ if (dyn_module->phdr[i].p_type == PT_DYNAMIC)
+ { *dyn_seg_idx = i; return TRUE; }
+
+ /*------------------------------------------------------------------------*/
+ /* No dynamic segment found, mark the object module as not relocatable */
+ /* and warn the user. */
+ /*------------------------------------------------------------------------*/
+ dyn_module->relocatable = FALSE;
+ DLIF_warning(DLWT_MISC, "'%s' does not have a dynamic segment; assuming "
+ "that it is a static executable and it cannot "
+ "be relocated.\n", dyn_module->name);
+ return FALSE;
+}
+
+
+#if 0
+/*****************************************************************************/
+/* copy_dynamic_table() */
+/* */
+/* Make a local copy of the dynamic table read from the dynamic segment */
+/* in the ELF object file. */
+/* */
+/*****************************************************************************/
+static void copy_dynamic_table(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module,
+ Elf32_Word dyn_seg_idx)
+{
+
+ /*------------------------------------------------------------------------*/
+ /* Allocate space for the dynamic table from host memory and read its */
+ /* content from the ELF object file. */
+ /*------------------------------------------------------------------------*/
+ Elf32_Word num_elem;
+ dyn_module->dyntab = DLIF_malloc(dyn_module->phdr[dyn_seg_idx].p_filesz);
+ num_elem = dyn_module->phdr[dyn_seg_idx].p_filesz / sizeof(struct Elf32_Dyn);
+ DLIF_fseek(fd, dyn_module->phdr[dyn_seg_idx].p_offset, LOADER_SEEK_SET);
+ DLIF_fread(dyn_module->dyntab, sizeof(struct Elf32_Dyn), num_elem, fd);
+
+ /*------------------------------------------------------------------------*/
+ /* If necessary, byte swap each entry in the dynamic table. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->wrong_endian)
+ {
+ int i;
+ for (i = 0; i < num_elem; i++)
+ DLIMP_change_dynent_endian(&dyn_module->dyntab[i]);
+ }
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* process_target_dynamic_tag() */
+/* */
+/* Process a target specific dynamic tag entry. Returns TRUE if the tag */
+/* was handled and FALSE if it was not recognized. */
+/*****************************************************************************/
+static BOOL process_target_dynamic_tag(DLIMP_Dynamic_Module* dyn_module, int i)
+{
+#ifdef ARM_TARGET
+ if (is_arm_module(&dyn_module->fhdr))
+ return DLDYN_arm_process_dynamic_tag(dyn_module, i);
+#endif
+
+#ifdef C60_TARGET
+ if (is_c60_module(&dyn_module->fhdr))
+ return DLDYN_c60_process_dynamic_tag(dyn_module, i);
+#endif
+
+ return FALSE;
+}
+#endif
+
+#if 0
+/*****************************************************************************/
+/* process_dynamic_table() */
+/* */
+/* Process dynamic tag entries from the dynamic table. At the conclusion */
+/* of this function, we should have made a copy of the global symbols */
+/* and the global symbol names. */
+/* */
+/*****************************************************************************/
+static BOOL process_dynamic_table(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ int i;
+ BOOL soname_found = FALSE;
+ Elf32_Addr soname_offset = 0;
+ Elf32_Addr strtab_offset = 0;
+ Elf32_Addr hash_offset = 0;
+ Elf32_Addr symtab_offset = 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Iterate over the dynamic table in order to process dynamic tags. */
+ /* See ELF TIS Specification for details on the meaning of each dynamic */
+ /* tag. The C6000 ELF ABI Specification provides more details about the */
+ /* TI specific C6000 ELF ABI tags. */
+ /*------------------------------------------------------------------------*/
+ for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
+ {
+ switch(dyn_module->dyntab[i].d_tag)
+ {
+ /*------------------------------------------------------------------*/
+ /* DT_SONAME: Contains name of dynamic object, used for dependency */
+ /* comparisons. Its value is an offset from the start */
+ /* of the string table. We need to copy the string at */
+ /* this offset into dmodule->name. */
+ /*------------------------------------------------------------------*/
+ case DT_SONAME:
+#if LOADER_DEBUG
+ if (debugging_on) printf("Found SO_NAME.\n");
+#endif
+ /*---------------------------------------------------------------*/
+ /* We store the offset of the so_name in the dynamic string */
+ /* table so that it doesn't matter which dynamic tag we see */
+ /* first (DT_SONAME actually is generated before DT_STRTAB). */
+ /*---------------------------------------------------------------*/
+ soname_found = TRUE;
+ soname_offset = dyn_module->dyntab[i].d_un.d_ptr;
+ break;
+
+ /*------------------------------------------------------------------*/
+ /* DT_STRSZ: Contains the size of the string table. */
+ /*------------------------------------------------------------------*/
+ case DT_STRSZ:
+ dyn_module->strsz = dyn_module->dyntab[i].d_un.d_val;
+
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Found string table Size: 0x%x\n", dyn_module->strsz);
+#endif
+ break;
+
+ /*------------------------------------------------------------------*/
+ /* DT_STRTAB: Contains the file offset of the string table. The */
+ /* tag directly after this is guaranteed to be DT_STRSZ, */
+ /* containing the string table size. We need to */
+ /* allocate memory for the string table and copy it from */
+ /* the file. */
+ /*------------------------------------------------------------------*/
+ case DT_STRTAB:
+ strtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Found string table: 0x%x\n", strtab_offset);
+#endif
+ break;
+
+ /*------------------------------------------------------------------*/
+ /* DT_HASH: Contains the file offset of the symbol hash table. */
+ /*------------------------------------------------------------------*/
+ case DT_HASH:
+ hash_offset = dyn_module->dyntab[i].d_un.d_ptr;
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Found symbol hash table: 0x%x\n", hash_offset);
+#endif
+ break;
+
+ /*------------------------------------------------------------------*/
+ /* DT_SYMTAB: Contains the file offset of the symbol table. */
+ /*------------------------------------------------------------------*/
+ case DT_SYMTAB:
+ symtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Found symbol table: 0x%x\n", symtab_offset);
+#endif
+ break;
+
+ /*------------------------------------------------------------------*/
+ /* DSO Initialization / Termination Model Dynamic Tags */
+ /*------------------------------------------------------------------*/
+ /* For initialization tags, we store indices and array sizes in */
+ /* the dyn_module. Termination works a little different, the */
+ /* indices into the local copy of the dynamic table are stored in */
+ /* dyn_module, but the DT_FINI_ARRAYSZ value is recorded with the */
+ /* loaded module. */
+ /*------------------------------------------------------------------*/
+ /* After placement is done, the DT_FINI and DT_FINI_ARRAY values */
+ /* need to be copied from the local dynamic table into the loaded */
+ /* module object. */
+ /*------------------------------------------------------------------*/
+ case DT_PREINIT_ARRAY:
+ dyn_module->preinit_array_idx = i;
+ break;
+
+ case DT_PREINIT_ARRAYSZ:
+ dyn_module->preinit_arraysz = dyn_module->dyntab[i].d_un.d_val;
+ break;
+
+ case DT_INIT:
+ dyn_module->init_idx = i;
+ break;
+
+ case DT_INIT_ARRAY:
+ dyn_module->init_array_idx = i;
+ break;
+
+ case DT_INIT_ARRAYSZ:
+ dyn_module->init_arraysz = dyn_module->dyntab[i].d_un.d_val;
+ break;
+
+ /*------------------------------------------------------------------*/
+ /* This information will be copied over to the loaded module */
+ /* object after placement has been completed and the information */
+ /* in the dynamic table has been relocated. */
+ /*------------------------------------------------------------------*/
+ case DT_FINI_ARRAY:
+ case DT_FINI_ARRAYSZ:
+ case DT_FINI:
+ break;
+
+ /*------------------------------------------------------------------*/
+ /* Unrecognized tag, may not be illegal, but is not explicitly */
+ /* handled by this function. Should it be? */
+ /*------------------------------------------------------------------*/
+ default:
+ {
+ if (!process_target_dynamic_tag(dyn_module, i))
+ {
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Unrecognized dynamic tag: 0x%X\n",
+ dyn_module->dyntab[i].d_tag);
+#endif
+ }
+
+ break;
+ }
+
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* If string table offset and size were found, read string table in from */
+ /* the ELF object file. */
+ /*------------------------------------------------------------------------*/
+ if (strtab_offset && dyn_module->strsz)
+ {
+ DLIF_fseek(fd, strtab_offset, LOADER_SEEK_SET);
+ dyn_module->strtab = DLIF_malloc(dyn_module->strsz);
+ DLIF_fread(dyn_module->strtab, sizeof(uint8_t), dyn_module->strsz, fd);
+ }
+ else
+ {
+ DLIF_warning(DLWT_MISC, "Mandatory dynamic tag DT_STRTAB/DT_STRSZ not found!\n");
+ return FALSE;
+ }
+
+
+ /*------------------------------------------------------------------------*/
+ /* If symbol hash table is found read-in the hash table. */
+ /*------------------------------------------------------------------------*/
+ if (hash_offset)
+ {
+ /*---------------------------------------------------------------------*/
+ /* Hash table has the following format. nchain equals the number of */
+ /* entries in the symbol table (symnum) */
+ /* */
+ /* +----------------------------+ */
+ /* | nbucket | */
+ /* +----------------------------+ */
+ /* | nchain | */
+ /* +----------------------------+ */
+ /* | bucket[0] | */
+ /* | ... | */
+ /* | bucket[nbucket-1] | */
+ /* +----------------------------+ */
+ /* | chain[0] | */
+ /* | ... | */
+ /* | chain[nchain-1] | */
+ /* +----------------------------+ */
+ /*---------------------------------------------------------------------*/
+ Elf32_Word hash_nbucket;
+ Elf32_Word hash_nchain;
+
+ /*---------------------------------------------------------------------*/
+ /* Seek to the hash offset and read first two words into nbucket and */
+ /* symnum. */
+ /*---------------------------------------------------------------------*/
+ DLIF_fseek(fd, hash_offset, LOADER_SEEK_SET);
+ DLIF_fread(&(hash_nbucket), sizeof(Elf32_Word), 1, fd);
+ DLIF_fread(&(hash_nchain), sizeof(Elf32_Word), 1, fd);
+ if (dyn_module->wrong_endian)
+ {
+ DLIMP_change_endian32((int32_t*)(&(hash_nbucket)));
+ DLIMP_change_endian32((int32_t*)(&(hash_nchain)));
+ }
+
+ /*---------------------------------------------------------------------*/
+ /* The number of entires in the dynamic symbol table is not encoded */
+ /* anywhere in the elf file. However, the nchain is guaranteed to be */
+ /* the same as the number of symbols. Use nchain to set the symnum. */
+ /*---------------------------------------------------------------------*/
+ dyn_module->symnum = hash_nchain;
+#if LOADER_DEBUG
+ if (debugging_on) printf("symnum=%d\n", hash_nchain);
+#endif
+ }
+ else
+ {
+ DLIF_warning(DLWT_MISC, "Mandatory dynamic tag DT_HASH is not found!\n");
+ return FALSE;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Read dynamic symbol table. */
+ /*------------------------------------------------------------------------*/
+ if (symtab_offset)
+ {
+ int j = 0;
+ DLIF_fseek(fd, symtab_offset, LOADER_SEEK_SET);
+ dyn_module->symtab =
+ DLIF_malloc(dyn_module->symnum * sizeof(struct Elf32_Sym));
+ DLIF_fread(dyn_module->symtab, sizeof(struct Elf32_Sym),
+ dyn_module->symnum, fd);
+ if (dyn_module->wrong_endian)
+ {
+ for (j = 0; j < dyn_module->symnum; j++)
+ DLIMP_change_sym_endian(dyn_module->symtab + j);
+ }
+
+ /*---------------------------------------------------------------------*/
+ /* The st_name field of an Elf32_Sym entity is an offset into the */
+ /* string table. Convert it into a pointer to the string. */
+ /*---------------------------------------------------------------------*/
+ if (strtab_offset)
+ for (j = 0; j < dyn_module->symnum; j++)
+ dyn_module->symtab[j].st_name += (Elf32_Word) dyn_module->strtab;
+ }
+ else
+ {
+ DLIF_warning(DLWT_MISC, "Mandatory dynamic tag DT_SYMTAB is not found!\n");
+ return FALSE;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Read the SONAME. */
+ /*------------------------------------------------------------------------*/
+ if (!soname_found)
+ {
+ DLIF_warning(DLWT_MISC, "Dynamic tag DT_SONAME is not found!\n");
+ dyn_module->name = DLIF_malloc(sizeof(char));
+ *dyn_module->name = '\0';
+ }
+ else
+ {
+ dyn_module->name =
+ DLIF_malloc(strlen(dyn_module->strtab + soname_offset) + 1);
+ strcpy(dyn_module->name, dyn_module->strtab + soname_offset);
+
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("Name of dynamic object: %s\n", dyn_module->name);
+#endif
+ }
+
+ return TRUE;
+}
+
+#endif
+
+
+#if 0
+
+/*****************************************************************************/
+/* dload_dynamic_information() */
+/* */
+/* Given a dynamic module with a dynamic segment which is located via */
+/* given dynamic segment index, make a local copy of the dynamic table */
+/* in the dynamic module object, then process the dynamic tag entries in */
+/* the table. */
+/* */
+/*****************************************************************************/
+static BOOL dload_dynamic_information(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module,
+ Elf32_Word dyn_seg_idx)
+{
+ /*------------------------------------------------------------------------*/
+ /* Read a copy of the dynamic table into the dynamic module object. */
+ /*------------------------------------------------------------------------*/
+ copy_dynamic_table(fd, dyn_module, dyn_seg_idx);
+
+ /*------------------------------------------------------------------------*/
+ /* Process dynamic entries in the dynamic table. If any problems are */
+ /* encountered, the loader should emit an error or warning and return */
+ /* FALSE here. */
+ /*------------------------------------------------------------------------*/
+ return process_dynamic_table(fd, dyn_module);
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* check_circular_dependency() */
+/* */
+/* Determine whether a dynamic module is already in the process of being */
+/* loaded before we try to start loading it again. If it is already */
+/* being loaded, then the dynamic loader has detected a circular */
+/* dependency. An error will be emitted and the load will be aborted. */
+/* */
+/*****************************************************************************/
+static BOOL check_circular_dependency(const char *dyn_mod_name)
+{
+ /*------------------------------------------------------------------------*/
+ /* Check the name of the given dependency module to be loaded against the */
+ /* list of modules that are currently in the process of being loaded. */
+ /* Report an error if any circular dependencies are detected. */
+ /*------------------------------------------------------------------------*/
+ int i;
+ for (i = 0; i < DLIMP_module_dependency_list.size; i++)
+ if (!strcmp(dyn_mod_name, ((char**)(DLIMP_module_dependency_list.buf))[i]))
+ {
+ DLIF_error(DLET_MISC,
+ "Circular dependency detected, '%s' is already in the "
+ "process of loading.\n", dyn_mod_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* dload_dynamic_segment() */
+/* */
+/* Find the dynamic segment in the given ELF module, if there is one. */
+/* If there is a dynamic segment, then make a local copy of the dynamic */
+/* table in the dynamic module object provided, then process the dynamic */
+/* tag entries in the table. */
+/* */
+/* If there is no dynamic segment, then we return success from this */
+/* function, marking the dynamic module as "not relocatable". */
+/* */
+/*****************************************************************************/
+static BOOL dload_dynamic_segment(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* If we don't find dynamic segment, the relocatable flag will have been */
+ /* set to false to indicate that the module is a static executable. We */
+ /* still return TRUE from this function so that we can proceed with */
+ /* static loading. */
+ /*------------------------------------------------------------------------*/
+ Elf32_Word dyn_seg_idx = 0;
+ if (!find_dynamic_segment(dyn_module, &dyn_seg_idx))
+ return TRUE;
+
+ /*------------------------------------------------------------------------*/
+ /* Process the OSABI now, after we know if the module is relocatable. */
+ /*------------------------------------------------------------------------*/
+ if (!process_eiosabi(dyn_module))
+ {
+ DLIF_error(DLET_FILE, "Unsupported EI_OSABI value.\n");
+ return FALSE;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Read the dynamic table from the ELF file, then process the dynamic */
+ /* tags in the table. */
+ /*------------------------------------------------------------------------*/
+ if (!dload_dynamic_information(fd, dyn_module, dyn_seg_idx))
+ return FALSE;
+
+ /*------------------------------------------------------------------------*/
+ /* Check to make sure that this module is not already being loaded. If */
+ /* is, then it will cause a circular dependency to be introduced. */
+ /* Loader should detect circular dependencies and emit an error. */
+ /*------------------------------------------------------------------------*/
+ if (!check_circular_dependency(dyn_module->name))
+ return FALSE;
+
+ return TRUE;
+}
+
+#endif
+
+#if 0
+/*****************************************************************************/
+/* COPY_SEGMENTS() - */
+/* */
+/* Copy all segments into host memory. */
+/*****************************************************************************/
+static void copy_segments(LOADER_FILE_DESC* fp,
+ DLIMP_Dynamic_Module* dyn_module)
+{
+ DLIMP_Loaded_Segment* seg =
+ (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
+ int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
+
+ for (s=0; s<seg_size; s++)
+ {
+ struct DLOAD_MEMORY_REQUEST targ_req;
+ targ_req.fp = fp;
+ targ_req.segment = seg[s].obj_desc;
+ targ_req.offset = seg[s].phdr.p_offset;
+ targ_req.flags = DLOAD_SF_relocatable;
+ if (seg[s].phdr.p_flags & PF_X)
+ seg[s].phdr.p_flags |= DLOAD_SF_executable;
+ targ_req.align = seg[s].phdr.p_align;
+
+ /*---------------------------------------------------------------------*/
+ /* Copy segment data from the file into host buffer where it can */
+ /* be relocated. */
+ /*---------------------------------------------------------------------*/
+ DLIF_copy(&targ_req);
+
+ /*---------------------------------------------------------------------*/
+ /* Calculate offset for relocations. */
+ /*---------------------------------------------------------------------*/
+ seg[s].reloc_offset = (int32_t)(targ_req.host_address) -
+ (int32_t)(seg[s].obj_desc->target_address);
+ }
+}
+
+#endif
+
+#if 0
+/*****************************************************************************/
+/* WRITE_SEGMENTS() - */
+/* */
+/* Write all segments to target memory. */
+/*****************************************************************************/
+static void write_segments(LOADER_FILE_DESC* fp,
+ DLIMP_Dynamic_Module* dyn_module)
+{
+ DLIMP_Loaded_Segment* seg =
+ (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
+ int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
+
+ for (s=0; s<seg_size; s++)
+ {
+ struct DLOAD_MEMORY_REQUEST targ_req;
+ targ_req.fp = fp;
+ targ_req.segment = seg[s].obj_desc;
+ targ_req.offset = seg[s].phdr.p_offset;
+ targ_req.flags = DLOAD_SF_relocatable;
+ if (seg[s].phdr.p_flags & PF_X)
+ seg[s].phdr.p_flags |= DLOAD_SF_executable;
+ targ_req.align = seg[s].phdr.p_align;
+
+ /*---------------------------------------------------------------------*/
+ /* Copy segment data from the file into host buffer where it can */
+ /* be relocated. */
+ /*---------------------------------------------------------------------*/
+ DLIF_write(&targ_req);
+ }
+}
+
+#endif
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_initialize() */
+/* */
+/* Construct and initialize data structures internal to the dynamic */
+/* loader core. */
+/* */
+/*---------------------------------------------------------------------------*/
+/* */
+/* This implementation of DLOAD_initialize() will set up the list of */
+/* dependency modules maintained by the loader core. This list contains */
+/* the names of the files that the loader is in the process of loading. */
+/* The list is used to keep track of what objects are waiting on their */
+/* dependents to be loaded so thath circular dependencies can be detected */
+/* and reported by the core loader. */
+/* */
+/*****************************************************************************/
+void DLOAD_initialize()
+{
+ /*------------------------------------------------------------------------*/
+ /* Set up initial objects_loading queue. */
+ /*------------------------------------------------------------------------*/
+ AL_initialize(&DLIMP_module_dependency_list, sizeof (const char*), 1);
+}
+
+#endif
+
+/*****************************************************************************/
+/* dload_static_executable() */
+/* */
+/* Account for target memory allocated to static executable and wrap up */
+/* loading. No relocation is necessary. */
+/* */
+/*****************************************************************************/
+static int32_t dload_static_executable(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ int32_t local_file_handle = 0;
+
+#if LOADER_DEBUG
+ if (debugging_on) printf("Starting dload_static_executable() ...\n");
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Set entry point for static executable and attempt to allocate target */
+ /* memory for the static executable. */
+ /*------------------------------------------------------------------------*/
+ dyn_module->loaded_module->entry_point = dyn_module->fhdr.e_entry;
+ if (load_static_segment(fd, dyn_module) && load_object(fd, dyn_module))
+ {
+ /*---------------------------------------------------------------------*/
+ /* If successful, we'll want to detach the loaded module object from */
+ /* the dynamic module object that created it. Take note of the file */
+ /* handle. */
+ /*---------------------------------------------------------------------*/
+ DLIMP_Loaded_Module *loaded_module = detach_loaded_module(dyn_module);
+ local_file_handle = loaded_module->file_handle;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Static load failed. Flag an error. */
+ /*------------------------------------------------------------------------*/
+ else
+ DLIF_error(DLET_MEMORY,
+ "Failed to allocate target memory for static executable.\n");
+
+ /*------------------------------------------------------------------------*/
+ /* Destruct dynamic module object. */
+ /*------------------------------------------------------------------------*/
+#if 0
+ delete_DLIMP_Dynamic_Module(&dyn_module);
+#endif
+
+#if LOADER_DEBUG
+ if (debugging_on) printf("Finished dload_static_executable()\n");
+#endif
+
+ return local_file_handle;
+}
+
+#if 0
+/*****************************************************************************/
+/* process_dynamic_module_relocations() */
+/* */
+/* Make a host-accessible copy of all of the segments, process all */
+/* relocation entries associated with the given module within that */
+/* space, then write the updated segment buffers back out to target */
+/* memory. */
+/* */
+/*****************************************************************************/
+static void process_dynamic_module_relocations(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+#if LOADER_DEBUG || LOADER_PROFILE
+ if(debugging_on || profiling_on)
+ {
+ printf("Running relocate()...\n");
+ if (profiling_on) profile_start_clock();
+ }
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Copy segments from file to host memory */
+ /*------------------------------------------------------------------------*/
+ copy_segments(fd, dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Process dynamic relocations. */
+ /*------------------------------------------------------------------------*/
+ DLREL_relocate(fd, dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Write segments from host memory to target memory */
+ /*------------------------------------------------------------------------*/
+ write_segments(fd, dyn_module);
+
+#if LOADER_DEBUG || LOADER_PROFILE
+ /*------------------------------------------------------------------------*/
+ /* Report timing and progress information for relocation step. */
+ /*------------------------------------------------------------------------*/
+ if (debugging_on || profiling_on)
+ {
+ if (profiling_on)
+ {
+ profile_stop_clock();
+ printf("Took %d cycles.\n", profile_cycle_count());
+ printf("Total reloc time: %d\n", DLREL_total_reloc_time);
+ printf("Time per relocation: %d\n",
+ DLREL_relocations ? DLREL_total_reloc_time / DLREL_relocations : 0);
+ }
+
+ printf("Number of relocations: %d\n", DLREL_relocations);
+ printf("\nAbout to run load_object()...");
+ DLREL_total_reloc_time = DLREL_relocations = 0;
+ if (profiling_on) profile_start_clock();
+ }
+#endif
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* execute_module_pre_initialization() */
+/* */
+/* Given a dynamic module object, execute any pre-initialization */
+/* functions for the specified dynamic executable module. Such functions */
+/* must be provided by the user and their addresses written to the */
+/* .preinit_array section. These functions should be executed in the */
+/* order that they are specified in the array before the initialization */
+/* process for this dynamic executable module begins. */
+/* */
+/*---------------------------------------------------------------------------*/
+/* */
+/* Note that dynamic shared objects (libraries) should not have a */
+/* .preinit_array (should be caught during static link-time if the user */
+/* attempts to link a .preinit_array section into a shared object. */
+/* */
+/*****************************************************************************/
+static void execute_module_pre_initialization(DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* Check for presence of DT_PREINIT_ARRAY and DT_PREINIT_ARRAYSZ */
+ /* dynamic tags associated with this module. The dyn_module object will */
+ /* hold the relevant indices into the local copy of the dynamic table. */
+ /* The value of the DT_INIT_ARRAY tag will have been updated after */
+ /* placement of the module was completed. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->preinit_arraysz != 0)
+ {
+ /*---------------------------------------------------------------------*/
+ /* Retrieve the address of the .preinit_array section from the value */
+ /* of the DT_PREINIT_ARRAY tag. */
+ /*---------------------------------------------------------------------*/
+ TARGET_ADDRESS preinit_array_loc = (TARGET_ADDRESS)
+ (dyn_module->dyntab[dyn_module->preinit_array_idx].d_un.d_ptr);
+
+ /*---------------------------------------------------------------------*/
+ /* Now make a loader-accessible copy of the .preinit_array section. */
+ /*---------------------------------------------------------------------*/
+ int32_t i;
+ int32_t num_preinit_fcns = dyn_module->preinit_arraysz/sizeof(TARGET_ADDRESS);
+ TARGET_ADDRESS *preinit_array_buf = (TARGET_ADDRESS *)
+ DLIF_malloc(dyn_module->preinit_arraysz);
+
+ DLIF_read(preinit_array_buf, 1, dyn_module->preinit_arraysz,
+ (TARGET_ADDRESS)preinit_array_loc);
+
+ /*---------------------------------------------------------------------*/
+ /* Call each function whose address occupies an entry in the array in */
+ /* the order that it appears in the array. The sizeof the array is */
+ /* provided by the preinit_arraysz field in the dynamic module (copied */
+ /* earlier when the dynamic table was read in). We need to divide the */
+ /* sizeof value down to get the number of actual entries in the array. */
+ /*---------------------------------------------------------------------*/
+ for (i = 0; i < num_preinit_fcns; i++)
+ DLIF_execute((TARGET_ADDRESS)(preinit_array_buf[i]));
+
+ DLIF_free(preinit_array_buf);
+ }
+}
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* execute_module_initialization() */
+/* */
+/* Given a dynamic module object, execute initialization function(s) for */
+/* all global and static data objects that are defined in the module */
+/* which require construction. The user may also provide a custom */
+/* iniitialization function that needs to be executed before the compiler */
+/* generated static initialization functions are executed. */
+/* */
+/*****************************************************************************/
+static void execute_module_initialization(DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* Check for presence of a DT_INIT dynamic tag associated with this */
+ /* module. The dynamic module will hold the index into the local copy of */
+ /* the dynamic table. This entry in the dynamic table will have been */
+ /* updated after placement of the module is completed. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->init_idx != -1)
+ {
+ /*---------------------------------------------------------------------*/
+ /* Retrieve the address of the initialization function from the value */
+ /* of the DT_INIT tag, and get the client to execute the function. */
+ /*---------------------------------------------------------------------*/
+ TARGET_ADDRESS init_fcn = (TARGET_ADDRESS)
+ (dyn_module->dyntab[dyn_module->init_idx].d_un.d_ptr);
+ DLIF_execute(init_fcn);
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Check for presence of a DT_INIT_ARRAY and DT_INIT_ARRAYSZ dynamic tags */
+ /* associated with this module. The dyn_module object will hold the */
+ /* relevant indices into the local copy of the dynamic table. The value */
+ /* of the DT_INIT_ARRAY tag will have been updated after placement of the */
+ /* module was completed. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->init_arraysz != 0)
+ {
+ /*---------------------------------------------------------------------*/
+ /* Retrieve the address of the .init_array section from the value of */
+ /* DT_INIT_ARRAY tag. */
+ /*---------------------------------------------------------------------*/
+ TARGET_ADDRESS init_array_loc = (TARGET_ADDRESS)
+ (dyn_module->dyntab[dyn_module->init_array_idx].d_un.d_ptr);
+
+ /*---------------------------------------------------------------------*/
+ /* Now make a loader-accessible copy of the .init_array section. */
+ /*---------------------------------------------------------------------*/
+ int32_t i;
+ int32_t num_init_fcns = dyn_module->init_arraysz/sizeof(TARGET_ADDRESS);
+ TARGET_ADDRESS *init_array_buf = (TARGET_ADDRESS *)
+ DLIF_malloc(dyn_module->init_arraysz);
+
+ DLIF_read(init_array_buf, 1, dyn_module->init_arraysz,
+ (TARGET_ADDRESS)init_array_loc);
+
+ /*---------------------------------------------------------------------*/
+ /* Call each function whose address occupies an entry in the array in */
+ /* the order that they appear in the array. The size of the array is */
+ /* provided by the init_arraysz field in the dynamic module (copied */
+ /* earlier when the dynamic table was read in). */
+ /*---------------------------------------------------------------------*/
+ for (i = 0; i < num_init_fcns; i++)
+ DLIF_execute((TARGET_ADDRESS)(init_array_buf[i]));
+
+ DLIF_free(init_array_buf);
+ }
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* relocate_dependency_graph_modules() */
+/* */
+/* For each dynamic module on the dependency stack, process dynamic */
+/* relocation entries then perform initialization for all global and */
+/* static objects that are defined in tha given module. The stack is */
+/* emptied from the top (LIFO). Each dynamic module object is popped */
+/* off the top of the stack, the module gets relocated, its global and */
+/* static objects that need to be constructed will be constructed, and */
+/* then, after detaching the loaded module object from its dynamic */
+/* module, the dynamic module object is destructed. */
+/* */
+/*****************************************************************************/
+static int32_t relocate_dependency_graph_modules(LOADER_FILE_DESC *fd,
+ DLIMP_Dynamic_Module *dyn_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* Processing of relocations will only be triggered when this function */
+ /* is called from the top-level object module (at the bottom of the */
+ /* dependency graph stack). */
+ /*------------------------------------------------------------------------*/
+ int32_t local_file_handle = dyn_module->loaded_module->file_handle;
+ dynamic_module_ptr_Stack_Node *ptr = DLIMP_dependency_stack.bottom_ptr;
+ if (ptr && (ptr->value != dyn_module)) return local_file_handle;
+
+ /*------------------------------------------------------------------------*/
+ /* Assign DSBT indices. */
+ /*------------------------------------------------------------------------*/
+ DLIF_assign_dsbt_indices();
+
+ /*------------------------------------------------------------------------*/
+ /* Update the content of all DSBTs for any module that uses the DSBT */
+ /* model. */
+ /*------------------------------------------------------------------------*/
+ DLIF_update_all_dsbts();
+
+ /*------------------------------------------------------------------------*/
+ /* Ok, we are ready to process relocations. The relocation tables */
+ /* associated with dependent files will be processed first. Consume */
+ /* dynamic module objects from the dependency graph stack from dependents */
+ /* to the root of the dependency graph. */
+ /*------------------------------------------------------------------------*/
+ while (DLIMP_dependency_stack.size > 0)
+ {
+ DLIMP_Dynamic_Module *dyn_mod_ptr =
+ dynamic_module_ptr_pop(&DLIMP_dependency_stack);
+
+ /*---------------------------------------------------------------------*/
+ /* Process dynamic relocations associated with this module. */
+ /*---------------------------------------------------------------------*/
+ process_dynamic_module_relocations(dyn_mod_ptr->fd, dyn_mod_ptr);
+
+ /*---------------------------------------------------------------------*/
+ /* __c_args__ points to the beginning of the .args section, if there */
+ /* is one. Record this pointer in the ELF file internal data object. */
+ /*---------------------------------------------------------------------*/
+ DLSYM_lookup_local_symtab("__c_args__", dyn_mod_ptr->symtab,
+ dyn_mod_ptr->symnum,
+ (Elf32_Addr *)&dyn_mod_ptr->c_args);
+
+ /*---------------------------------------------------------------------*/
+ /* Pick up entry point address from ELF file header. */
+ /* We currently only support a single entry point into the ELF file. */
+ /* To support Braveheart notion of nodes, with multiple entry points,*/
+ /* we'll need to get the list of entry points associated with a node,*/
+ /* then add capability to the "execute" command to select the entry */
+ /* point that we want to start executing from. */
+ /*---------------------------------------------------------------------*/
+ dyn_mod_ptr->loaded_module->entry_point = dyn_mod_ptr->fhdr.e_entry;
+
+ /*---------------------------------------------------------------------*/
+ /* Copy command-line arguments into args section and deal with DSBT */
+ /* issues (copy DSBT to its run location). */
+ /*---------------------------------------------------------------------*/
+ load_object(dyn_mod_ptr->fd, dyn_mod_ptr);
+
+ /*---------------------------------------------------------------------*/
+ /* Perform initialization, if needed, for this module. */
+ /*---------------------------------------------------------------------*/
+ execute_module_initialization(dyn_mod_ptr);
+
+ /*---------------------------------------------------------------------*/
+ /* Free all dependent file pointers. */
+ /*---------------------------------------------------------------------*/
+ if (dyn_mod_ptr->fd != fd)
+ {
+ DLIF_fclose(dyn_mod_ptr->fd);
+ dyn_mod_ptr->fd = NULL;
+ }
+
+ /*---------------------------------------------------------------------*/
+ /* Detach loaded module object from the dynamic module object that */
+ /* created it, then throw away the dynamic module object. */
+ /*---------------------------------------------------------------------*/
+ detach_loaded_module(dyn_mod_ptr);
+ delete_DLIMP_Dynamic_Module(&dyn_mod_ptr);
+ }
+
+ return local_file_handle;
+}
+
+#endif
+
+/*****************************************************************************/
+/* DLOAD_load() */
+/* */
+/* Dynamically load the specified file and return a file handle for the */
+/* loaded file. If the load fails, this function will return a value of */
+/* zero (0) for the file handle. */
+/* */
+/* The core loader must have read access to the file pointed to by fd. */
+/* */
+/*****************************************************************************/
+int32_t DLOAD_load(LOADER_FILE_DESC *fd, int argc, char** argv, uint32_t *entry)
+{
+ DLIMP_Dynamic_Module *dyn_module = new_DLIMP_Dynamic_Module(fd);
+
+ if (!dyn_module)
+ return 0;
+
+#if LOADER_DEBUG
+ /*------------------------------------------------------------------------*/
+ /* Spit out some loader progress information when we begin loading an */
+ /* object. */
+ /*------------------------------------------------------------------------*/
+ if (debugging_on) printf("Loading file...\n");
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* If no access to a program was provided, there is nothing to do. */
+ /*------------------------------------------------------------------------*/
+ if (!fd)
+ {
+ DLIF_error(DLET_FILE, "Missing file specification.\n");
+ return 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Read file headers and dynamic information into dynamic module. */
+ /*------------------------------------------------------------------------*/
+ if (!dload_headers(fd, dyn_module))
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Find the dynamic segment, if there is one, and read dynamic */
+ /* information from the ELF object file into the dynamic module data */
+ /* structure associated with this file. */
+ /*------------------------------------------------------------------------*/
+ if (!dload_dynamic_segment(fd, dyn_module))
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* ??? We currently don't have a way of finding the .args section. So */
+ /* we are hard-wiring the address of the .args section. The proposed */
+ /* solution for this problem is to invent a special segment type or */
+ /* dynamic tag(s) that identify the location and size of the .args */
+ /* section for the dynamic loader. */
+ /*------------------------------------------------------------------------*/
+ /*HACK ---> */dyn_module->c_args = (uint8_t*)(0x02204000); /* <--- HACK*/
+
+ /*------------------------------------------------------------------------*/
+ /* Record argc and argv pointers with the dynamic module record. */
+ /*------------------------------------------------------------------------*/
+ dyn_module->argc = argc;
+ dyn_module->argv = argv;
+
+ /*------------------------------------------------------------------------*/
+ /* Perform sanity checking on the read-in ELF file. */
+ /*------------------------------------------------------------------------*/
+ if (!is_valid_elf_object_file(fd, dyn_module))
+ {
+ DLIF_error(DLET_FILE, "Attempt to load invalid ELF file, '%s'.\n",
+ dyn_module->name);
+ return 0;
+ }
+
+#if LOADER_DEBUG || LOADER_PROFILE
+ /*------------------------------------------------------------------------*/
+ /* Stop clock on initialization of ELF file information. Start clock on */
+ /* initialization of ELF module. */
+ /*------------------------------------------------------------------------*/
+ if (debugging_on || profiling_on)
+ {
+ printf("Finished dload_dynamic_segment.\n");
+ if (profiling_on)
+ {
+ profile_stop_clock();
+ printf("Took %d cycles.\n", profile_cycle_count());
+ }
+ }
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Initialize internal ELF module and segment structures. Sets */
+ /* loaded_module in *dyn_module. This also deals with assigning a file */
+ /* handle and bumping file handle counter. */
+ /*------------------------------------------------------------------------*/
+ initialize_loaded_module(dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Append Module structure to loaded object list. */
+ /*------------------------------------------------------------------------*/
+#if 0
+ loaded_module_ptr_enqueue(&DLIMP_loaded_objects, dyn_module->loaded_module);
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Support static loading as special case. */
+ /*------------------------------------------------------------------------*/
+ if (!dyn_module->relocatable) {
+ dload_static_executable(fd, dyn_module);
+ *entry = dyn_module->fhdr.e_entry;
+ return (0);
+ }
+
+#if 0
+
+ /*------------------------------------------------------------------------*/
+ /* Get space & address for segments, and offset symbols and program */
+ /* header table to reflect the relocated address. Also offset the */
+ /* addresses in the internal Segment structures used by the Module */
+ /* structure. Note that this step needs to be performed prior and in */
+ /* addition to the relocation entry processing. */
+ /*------------------------------------------------------------------------*/
+ if (!allocate_dynamic_segments_and_relocate_symbols(fd, dyn_module))
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Execute any user defined pre-initialization functions that may be */
+ /* associated with a dynamic executable module. */
+ /*------------------------------------------------------------------------*/
+ if (dyn_module->fhdr.e_type == ET_EXEC)
+ execute_module_pre_initialization(dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Append current ELF file to list of objects currently loading. */
+ /* This is used to detect circular dependencies while we are processing */
+ /* the dependents of this file. */
+ /*------------------------------------------------------------------------*/
+ AL_append(&DLIMP_module_dependency_list, &dyn_module->name);
+
+ /*------------------------------------------------------------------------*/
+ /* Push this dynamic module object onto the dependency stack. */
+ /* All of the modules on the stack will get relocated after all of the */
+ /* dependent files have been loaded and allocated. */
+ /*------------------------------------------------------------------------*/
+ dynamic_module_ptr_push(&DLIMP_dependency_stack, dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* If this object file uses the DSBT model, then register a DSBT index */
+ /* request with the client's DSBT support management. */
+ /*------------------------------------------------------------------------*/
+ if (is_dsbt_module(dyn_module) &&
+ !DLIF_register_dsbt_index_request(dyn_module->name,
+ dyn_module->loaded_module->file_handle,
+ dyn_module->dsbt_index))
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Load this ELF file's dependents (all files on its DT_NEEDED list). */
+ /* Do not process relocation entries for anyone in the dependency graph */
+ /* until all modules in the graph are loaded and allocated. */
+ /*------------------------------------------------------------------------*/
+ if (!dload_and_allocate_dependencies(dyn_module))
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Remove the current ELF file from the list of files that are in the */
+ /* process of loading. */
+ /*------------------------------------------------------------------------*/
+ DLIMP_module_dependency_list.size--;
+
+ /*------------------------------------------------------------------------*/
+ /* __c_args__ points to the beginning of the .args section, if there is */
+ /* one. Record this pointer in the ELF file internal data object. */
+ /*------------------------------------------------------------------------*/
+ DLSYM_lookup_local_symtab("__c_args__", dyn_module->symtab,
+ dyn_module->symnum,
+ (Elf32_Addr *)&dyn_module->c_args);
+
+
+ return relocate_dependency_graph_modules(fd, dyn_module);
+
+#endif
+}
+
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_get_entry_names() */
+/* */
+/* Build a list of entry point names for a loaded object. Currently, */
+/* any global symbol in the module is considered a valid entry point */
+/* regardless of whether it is defined in code or associated with a */
+/* data object. We would need to process the content of the symbol */
+/* table entry or its debug information to determine whether it is a */
+/* valid entry point or not. */
+/* */
+/*****************************************************************************/
+BOOL DLOAD_get_entry_names(uint32_t file_handle,
+ int32_t *entry_pt_cnt,
+ char ***entry_pt_names)
+{
+ /*------------------------------------------------------------------------*/
+ /* Spin through list of loaded files until we find the file handle we */
+ /* are looking for. Then build a list of entry points from that file's */
+ /* symbol table. */
+ /*------------------------------------------------------------------------*/
+ loaded_module_ptr_Queue_Node* ptr;
+ for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL; ptr = ptr->next_ptr)
+ {
+ if (ptr->value->file_handle == file_handle)
+ {
+ DLIMP_Loaded_Module *module = ptr->value;
+ struct Elf32_Sym *symtab;
+ int i;
+
+ /*------------------------------------------------------------------*/
+ /* Any symbol in our file's symbol table is considered a valid */
+ /* entry point. */
+ /*------------------------------------------------------------------*/
+ symtab = (struct Elf32_Sym*)module->gsymtab;
+ *entry_pt_cnt = module->gsymnum;
+ *entry_pt_names = DLIF_malloc(*entry_pt_cnt * sizeof(char*));
+ for (i = 0; i < module->gsymnum; i++)
+ {
+ const char *sym_name = (const char *)symtab[i].st_name;
+ **entry_pt_names = DLIF_malloc(strlen(sym_name) + 1);
+ strcpy(**entry_pt_names,sym_name);
+ }
+
+ return TRUE;
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* We didn't find the file we were looking for, return false. */
+ /*------------------------------------------------------------------------*/
+ return FALSE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_get_entry_point() */
+/* */
+/* Given a file handle, return the entry point associated with that */
+/* module in the *sym_val output parameter. */
+/* */
+/*****************************************************************************/
+BOOL DLOAD_get_entry_point(uint32_t file_handle, TARGET_ADDRESS *sym_val)
+{
+ /*------------------------------------------------------------------------*/
+ /* Spin through list of loaded files until we find the file handle we */
+ /* are looking for. Then return the entry point address associated with */
+ /* that module. */
+ /*------------------------------------------------------------------------*/
+ loaded_module_ptr_Queue_Node* ptr;
+ for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL; ptr = ptr->next_ptr)
+ if (ptr->value->file_handle == file_handle)
+ {
+ *sym_val = (TARGET_ADDRESS)(ptr->value->entry_point);
+ return TRUE;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* We didn't find the file we were looking for, return false. */
+ /*------------------------------------------------------------------------*/
+ return FALSE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_query_symbol() */
+/* */
+/* Query the value of a global symbol from a specific file. The value */
+/* result will be written to *sym_val. The function returns TRUE if the */
+/* symbol was found, and FALSE if it wasn't. */
+/* */
+/*****************************************************************************/
+BOOL DLOAD_query_symbol(uint32_t file_handle,
+ const char *sym_name,
+ TARGET_ADDRESS *sym_val)
+{
+ /*------------------------------------------------------------------------*/
+ /* Spin through list of loaded files until we find the file handle we */
+ /* are looking for. Then return the value (target address) associated */
+ /* with the symbol we are looking for in that file. */
+ /*------------------------------------------------------------------------*/
+ loaded_module_ptr_Queue_Node* ptr;
+ for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL; ptr = ptr->next_ptr)
+ {
+ if (ptr->value->file_handle == file_handle)
+ {
+ DLIMP_Loaded_Module *module = ptr->value;
+ struct Elf32_Sym *symtab;
+ int i;
+
+ /*------------------------------------------------------------------*/
+ /* Search through the symbol table by name. */
+ /*------------------------------------------------------------------*/
+ symtab = (struct Elf32_Sym*)module->gsymtab;
+ for(i=0; i < module->gsymnum; i++)
+ {
+ if (!strcmp(sym_name, (const char *)symtab[i].st_name))
+ {
+ *sym_val = (TARGET_ADDRESS) symtab[i].st_value;
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* We didn't find the file we were looking for, return false. */
+ /*------------------------------------------------------------------------*/
+ return FALSE;
+}
+
+#endif
+
+
+
+#if 0
+/*****************************************************************************/
+/* unlink_loaded_module() */
+/* */
+/* Unlink a loaded module data object from the list of loaded objects, */
+/* returning a pointer to the object so that it can be deconstructed. */
+/* */
+/*****************************************************************************/
+static DLIMP_Loaded_Module *unlink_loaded_module(loaded_module_ptr_Queue_Node *back_ptr,
+ loaded_module_ptr_Queue_Node *lm_node)
+{
+ DLIMP_Loaded_Module *loaded_module = lm_node->value;
+ loaded_module_ptr_remove(&DLIMP_loaded_objects, lm_node->value);
+ DLIF_free(lm_node);
+ return loaded_module;
+}
+
+#endif
+
+#if 0
+
+/*****************************************************************************/
+/* execute_module_termination() */
+/* */
+/* Execute termination functions associated with this loaded module. */
+/* Termination functions are called in the reverse order as their */
+/* corresponding initialization functions. */
+/* */
+/*****************************************************************************/
+static void execute_module_termination(DLIMP_Loaded_Module *loaded_module)
+{
+ /*------------------------------------------------------------------------*/
+ /* If a DT_FINI_ARRAY dynamic tag was encountered for this module, spin */
+ /* through the array in reverse order, calling each function address */
+ /* stored in the array. */
+ /*------------------------------------------------------------------------*/
+ if (loaded_module->fini_arraysz != 0)
+ {
+ /*---------------------------------------------------------------------*/
+ /* Now make a loader-accessible copy of the .fini_array section. */
+ /*---------------------------------------------------------------------*/
+ int32_t i;
+ int32_t num_fini_fcns = loaded_module->fini_arraysz/sizeof(TARGET_ADDRESS);
+ TARGET_ADDRESS *fini_array_buf = (TARGET_ADDRESS *)
+ DLIF_malloc(loaded_module->fini_arraysz);
+
+ DLIF_read(fini_array_buf, 1, loaded_module->fini_arraysz,
+ (TARGET_ADDRESS)loaded_module->fini_array);
+
+ /*---------------------------------------------------------------------*/
+ /* Now spin through the array in reverse order, executing each */
+ /* termination function whose address occupies an entry in the array. */
+ /*---------------------------------------------------------------------*/
+ for (i = num_fini_fcns - 1; i >= 0; i--)
+ DLIF_execute((TARGET_ADDRESS)(fini_array_buf[i]));
+
+ DLIF_free(fini_array_buf);
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* If a DT_FINI dynamic tag was encountered for this module, call the */
+ /* function indicated by the tag's value to complete the termination */
+ /* process for this module. */
+ /*------------------------------------------------------------------------*/
+ if (loaded_module->fini != NULL)
+ DLIF_execute((TARGET_ADDRESS)loaded_module->fini);
+}
+
+#endif
+
+#if 0
+/*****************************************************************************/
+/* remove_loaded_module() */
+/* */
+/* Find and unlink a loaded module data object from the list of loaded */
+/* objects, then call its destructor to free the host memory associated */
+/* with the loaded module and all of its loaded segments. */
+/* */
+/*****************************************************************************/
+static void remove_loaded_module(loaded_module_ptr_Queue_Node *lm_node)
+{
+ DLIMP_Loaded_Module *lm_object = NULL;
+ loaded_module_ptr_Queue_Node *back_ptr = NULL;
+
+ if (lm_node != DLIMP_loaded_objects.front_ptr)
+ for (back_ptr = DLIMP_loaded_objects.front_ptr;
+ back_ptr->next_ptr != lm_node;
+ back_ptr = back_ptr->next_ptr);
+
+ lm_object = unlink_loaded_module(back_ptr, lm_node);
+
+ delete_DLIMP_Loaded_Module(&lm_object);
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_unload() */
+/* */
+/* Unload specified module (identified by its file handle) from target */
+/* memory. Free up any target memory that was allocated for the module's */
+/* segments and also any host heap memory that was allocated for the */
+/* internal module and segment data structures. */
+/* */
+/* Return TRUE if program entry is actually destroyed. This is a way of */
+/* communicating to the client when it needs to actually remove debug */
+/* information associated with this module (so that client does not have */
+/* to maintain a use count that mirrors the program entry). */
+/* */
+/*****************************************************************************/
+BOOL DLOAD_unload(uint32_t handle)
+{
+ loaded_module_ptr_Queue_Node* lm_node;
+
+ for (lm_node = DLIMP_loaded_objects.front_ptr; lm_node != NULL;
+ lm_node = lm_node->next_ptr)
+ {
+ if (lm_node->value->file_handle == handle)
+ {
+ --lm_node->value->use_count;
+ if (lm_node->value->use_count == 0)
+ {
+ DLIMP_Loaded_Module *loaded_module =
+ (DLIMP_Loaded_Module *)lm_node->value;
+ int j;
+ int *dep_file_handles;
+
+ /*---------------------------------------------------------------*/
+ /* Termination functions need to be executed in the reverse */
+ /* order as the corresponding initialization functions, so */
+ /* before we go unload this module's dependents, we need to */
+ /* perform the user/global/static termination functions */
+ /* associated with this module. */
+ /*---------------------------------------------------------------*/
+ execute_module_termination(loaded_module);
+
+ /*---------------------------------------------------------------*/
+ /* Unload dependent modules via the client. Client needs to know */
+ /* when a dependent gets unloaded so that it can update debug */
+ /* information. */
+ /*---------------------------------------------------------------*/
+ dep_file_handles = (int*)(loaded_module->dependencies.buf);
+ for (j = 0; j < loaded_module->dependencies.size; j++)
+ DLIF_unload_dependent(dep_file_handles[j]);
+
+ /*---------------------------------------------------------------*/
+ /* Find the predecessor node of the value we're deleting, */
+ /* because its next_ptr will need to be updated. */
+ /* */
+ /* We can't keep a back pointer around because */
+ /* DLIF_unload_dependent() might free that node, making our */
+ /* pointer invalid. Turn the Queue template into a doubly */
+ /* linked list if this overhead becomes a problem. */
+ /*---------------------------------------------------------------*/
+ remove_loaded_module(lm_node);
+
+ /*---------------------------------------------------------------*/
+ /* If all loaded objects have been unloaded (including the */
+ /* base image), then reset the machine to the default target */
+ /* machine. This only has an effect when multiple targets are */
+ /* supported, in which case the machine is set to EM_NONE. */
+ /*---------------------------------------------------------------*/
+ if (DLIMP_loaded_objects.front_ptr == NULL)
+ {
+ DLOAD_TARGET_MACHINE = DLOAD_DEFAULT_TARGET_MACHINE;
+ }
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_load_symbols() */
+/* */
+/* Load the symbols from the given file and make symbols available for */
+/* global symbol linkage. */
+/* */
+/*****************************************************************************/
+int32_t DLOAD_load_symbols(LOADER_FILE_DESC *fd)
+{
+ DLIMP_Dynamic_Module *dyn_module = new_DLIMP_Dynamic_Module(fd);
+ DLIMP_Loaded_Module *loaded_module = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Ensure we have a valid dynamic module object from the constructor. */
+ /*------------------------------------------------------------------------*/
+ if (!dyn_module)
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* If no access to a program was provided, there is nothing to do. */
+ /*------------------------------------------------------------------------*/
+ if (!fd)
+ {
+ DLIF_error(DLET_FILE, "Missing file specification.\n");
+ return 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Record argc and argv pointers with the dynamic module record. */
+ /*------------------------------------------------------------------------*/
+ dyn_module->argc = 0;
+ dyn_module->argv = NULL;
+
+ /*------------------------------------------------------------------------*/
+ /* Read file headers and dynamic information into dynamic module. */
+ /*------------------------------------------------------------------------*/
+ if (!dload_headers(fd, dyn_module))
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Find the dynamic segment, if there is one, and read dynamic */
+ /* information from the ELF object file into the dynamic module data */
+ /* structure associated with this file. */
+ /*------------------------------------------------------------------------*/
+ if (!dload_dynamic_segment(fd, dyn_module))
+ return 0;
+
+ /*------------------------------------------------------------------------*/
+ /* Perform sanity checking on the read-in ELF file. */
+ /*------------------------------------------------------------------------*/
+ if (!is_valid_elf_object_file(fd, dyn_module))
+ {
+ DLIF_error(DLET_FILE, "Attempt to load invalid ELF file, '%s'.\n",
+ dyn_module->name);
+ return 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Initialize internal ELF module and segment structures. Sets */
+ /* loaded_module in *dyn_module. This also deals with assigning a file */
+ /* handle and bumping file handle counter. */
+ /*------------------------------------------------------------------------*/
+ initialize_loaded_module(dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Add this module to the loaded module queue. */
+ /* Detach the loaded module object from the dynamic module thath created */
+ /* it. Ownership of the host memory allocated for the loaded module */
+ /* object now belongs to the DLIMP_loaded_objects list. */
+ /*------------------------------------------------------------------------*/
+ loaded_module_ptr_enqueue(&DLIMP_loaded_objects, dyn_module->loaded_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Register a DSBT index request for this module and update its own copy */
+ /* of the DSBT with the contents of the client's master DSBT. */
+ /*------------------------------------------------------------------------*/
+ if (is_dsbt_module(dyn_module))
+ {
+ dynamic_module_ptr_push(&DLIMP_dependency_stack, dyn_module);
+ DLIF_register_dsbt_index_request(dyn_module->name,
+ dyn_module->loaded_module->file_handle,
+ dyn_module->dsbt_index);
+ DLIF_assign_dsbt_indices();
+ DLIF_update_all_dsbts();
+ dynamic_module_ptr_pop(&DLIMP_dependency_stack);
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Ownership of the host memory allocated for the loaded module object is */
+ /* transferred to the DLIMP_loaded_objects list. Free up the host memory */
+ /* for the dynamic module that created the loaded module object. Just */
+ /* call the destructor function for DLIMP_Dynamic_Module. */
+ /*------------------------------------------------------------------------*/
+ loaded_module = detach_loaded_module(dyn_module);
+ delete_DLIMP_Dynamic_Module(&dyn_module);
+
+ /*------------------------------------------------------------------------*/
+ /* Return a file handle so that the client can match this file to an ID. */
+ /*------------------------------------------------------------------------*/
+ return loaded_module->file_handle;
+}
+
+#endif
+
+/*****************************************************************************/
+/* DSBT Support Functions */
+/*****************************************************************************/
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_get_dsbt_size() */
+/* */
+/* Find the amount of space allocated for the specified module's DSBT. */
+/* It must be big enough to hold a copy of the master DSBT or the client */
+/* will flag an error. Those modules whose DSBT size is zero are assumed */
+/* to not be using the DSBT model. */
+/* */
+/*****************************************************************************/
+uint32_t DLOAD_get_dsbt_size(int32_t file_handle)
+{
+ dynamic_module_ptr_Stack_Node *ptr;
+ for (ptr = DLIMP_dependency_stack.top_ptr; ptr != NULL; ptr = ptr->next_ptr)
+ {
+ DLIMP_Dynamic_Module *dmp = ptr->value;
+ if (dmp->loaded_module->file_handle == file_handle)
+ return dmp->dsbt_size;
+ }
+
+ return 0;
+}
+
+#endif
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_get_static_base() */
+/* */
+/* Look up static base symbol associated with the specified module. */
+/* */
+/*****************************************************************************/
+BOOL DLOAD_get_static_base(int32_t file_handle, TARGET_ADDRESS *static_base)
+{
+ dynamic_module_ptr_Stack_Node *ptr;
+ for (ptr = DLIMP_dependency_stack.top_ptr; ptr != NULL; ptr = ptr->next_ptr)
+ {
+ DLIMP_Dynamic_Module *dmp = ptr->value;
+ if (dmp->loaded_module->file_handle == file_handle)
+ {
+ BOOL stat = DLSYM_lookup_local_symtab("__TI_STATIC_BASE",
+ dmp->symtab, dmp->symnum,
+ (Elf32_Addr *)static_base);
+ return stat;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif
+
+
+#if 0
+/*****************************************************************************/
+/* DLOAD_get_dsbt_base() */
+/* */
+/* Look up address of DSBT for the specified module. */
+/* */
+/*****************************************************************************/
+BOOL DLOAD_get_dsbt_base(int32_t file_handle, TARGET_ADDRESS *dsbt_base)
+{
+ dynamic_module_ptr_Stack_Node *ptr;
+ for (ptr = DLIMP_dependency_stack.top_ptr; ptr != NULL; ptr = ptr->next_ptr)
+ {
+ DLIMP_Dynamic_Module *dmp = ptr->value;
+ if (dmp->loaded_module->file_handle == file_handle)
+ {
+ *dsbt_base = (TARGET_ADDRESS)dmp->dyntab[dmp->dsbt_base_tagidx].d_un.d_ptr;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif
diff --git a/src/interp/elf/dload.h b/src/interp/elf/dload.h
--- /dev/null
+++ b/src/interp/elf/dload.h
@@ -0,0 +1,295 @@
+/*
+* dload.h
+*
+* Define internal data structures used by core dynamic loader.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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.
+*
+*/
+
+#ifndef DLOAD_H
+#define DLOAD_H
+
+#include "ewrap.h"
+
+#include "ArrayList.h"
+/* #include "Queue.h" */
+/* #include "Stack.h" */
+#include "types.h"
+#include "elf32.h"
+#include "dload_api.h"
+#include "util.h"
+
+/*---------------------------------------------------------------------------*/
+/* Contains strings with names of files the loader is in process of loading. */
+/* This list is used to keep track of what objects are in the process of */
+/* loading while their dependents are being loaded so that we can detect */
+/* circular dependencies. */
+/*---------------------------------------------------------------------------*/
+#if 0
+extern Array_List DLIMP_module_dependency_list;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* DLIMP_Loaded_Segment */
+/* */
+/* This structure represents a segment loaded on memory. */
+/* */
+/* This data structure should be created using host memory when a module */
+/* is being loaded into target memory. The data structure should persist */
+/* as long as the module stays resident in target memory. It should be */
+/* removed when the last use of the module is unloaded from the target. */
+/*---------------------------------------------------------------------------*/
+typedef struct
+{
+ struct Elf32_Phdr phdr;
+ Elf32_Addr input_vaddr; /* original segment load addr */
+ BOOL modified;
+ int32_t reloc_offset; /* used by load_program */
+ struct DLOAD_MEMORY_SEGMENT *obj_desc;
+} DLIMP_Loaded_Segment;
+
+/*---------------------------------------------------------------------------*/
+/* DLIMP_Loaded_Module */
+/* */
+/* This structure contains all the information the dynamic loader needs */
+/* to retain after loading an object file's segments into target memory. */
+/* The data structure is created while the object file is being loaded, */
+/* and should persist until the last use of the module is unloaded from */
+/* target memory. */
+/* */
+/* The information contained here is used by the dynamic loader to */
+/* perform dynamic symbol resolution, to track the use count, and to */
+/* finally deallocate the module's segments when the module is unloaded. */
+/*---------------------------------------------------------------------------*/
+typedef struct
+{
+ char *name; /* Local copy of so_name */
+ int32_t file_handle;
+ int32_t use_count;
+ Elf32_Addr entry_point; /* Entry point address into module */
+ struct Elf32_Sym *gsymtab; /* Module's global symbol table */
+ Elf32_Word gsymnum; /* # global symbols */
+ char *gstrtab; /* Module's global symbol names */
+ Elf32_Word gstrsz; /* Size of global string table */
+ Array_List loaded_segments; /* List of DLIMP_Loaded_Segment(s) */
+ Array_List dependencies; /* List of dependent file handles */
+ BOOL direct_dependent_only;
+
+ Elf32_Addr fini; /* .fini function/section address */
+ Elf32_Addr fini_array; /* .fini_array term fcn ary addr */
+ int32_t fini_arraysz; /* sizeof .fini_array */
+
+} DLIMP_Loaded_Module;
+
+/*---------------------------------------------------------------------------*/
+/* DLIMP_loaded_objects */
+/* */
+/* A list of loaded module objects (DLIMP_Loaded_Module *) that the */
+/* loader has placed into target memory. */
+/*---------------------------------------------------------------------------*/
+#if 0
+TYPE_QUEUE_DEFINITION(DLIMP_Loaded_Module*, loaded_module_ptr)
+extern loaded_module_ptr_Queue DLIMP_loaded_objects;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* DLIMP_Dynamic_Module */
+/* */
+/* This structure represents a dynamic module to be loaded by the dynamic */
+/* loader. It contains all the information necessary to load and relocate */
+/* the module. It actually contains most of the headers, dynamic info, */
+/* dynamic symbol table, string table etc. */
+/* */
+/* This structure is allocated in host memory while an ELF object file is */
+/* being loaded and will be destructed after the file has been */
+/* successfully loaded. To simplify loading and relocation of the object */
+/* file's segments, this data structure maintains a link to the loaded */
+/* module. This link is severed when the load is successfully completed. */
+/* The loaded module data structure will persist until the module is */
+/* actually unloaded from target memory, but this data structure will be */
+/* freed. */
+/* */
+/* If the load of the object file is not successful for any reason, then */
+/* the loaded module will not be detached from the dynamic module. In */
+/* such case, the destructor for the dynamic module will assume */
+/* responsibility for freeing any host memory associated with the loaded */
+/* module and its segments. */
+/*---------------------------------------------------------------------------*/
+typedef struct
+{
+ char *name; /* Local copy of so_name */
+ LOADER_FILE_DESC *fd; /* Access to ELF object file */
+ struct Elf32_Ehdr fhdr; /* ELF Object File Header */
+ struct Elf32_Phdr *phdr; /* ELF Program Header Table */
+ Elf32_Word phnum; /* # entries in program header table */
+ char* strtab; /* String Table */
+ Elf32_Word strsz; /* String Table size in bytes */
+ struct Elf32_Dyn *dyntab; /* Elf Dynamic Table (.dynamic scn) */
+ /* This contains a list of dynamic */
+ /* tags which is terminated by a NULL */
+ /* record. */
+ struct Elf32_Sym *symtab; /* Elf Dynamic Symbol Table */
+ Elf32_Word symnum; /* # symbols in dynamic symbol table */
+ Elf32_Word gsymtab_offset;/* Offset into symbol table where */
+ /* global symbols start. */
+ Elf32_Word gstrtab_offset;/* Offset into string table where */
+ /* global symbol names start. */
+
+ uint8_t *c_args;
+ int32_t argc;
+ char **argv;
+ DLIMP_Loaded_Module *loaded_module;
+ int32_t wrong_endian;
+ BOOL direct_dependent_only;
+ BOOL relocatable; /* TRUE if module can be relocated */
+ /* at load-time. FALSE if module is */
+ /* a static executable. */
+ BOOL relocate_entry_point; /* TRUE if the entry point has */
+ /* not been relocated */
+
+ int32_t dsbt_index; /* DSBT index requested/assigned */
+ uint32_t dsbt_size; /* DSBT size for this module */
+ int32_t dsbt_base_tagidx;/* Location of DSBT base dyn tag */
+
+ int32_t preinit_array_idx; /* DT_PREINIT_ARRAY dyn tag loc */
+ int32_t preinit_arraysz; /* sizeof pre-init array */
+ int32_t init_idx; /* DT_INIT dynamic tag location */
+ int32_t init_array_idx; /* DT_INIT_ARRAY dyn tag location */
+ int32_t init_arraysz; /* sizeof init array */
+
+} DLIMP_Dynamic_Module;
+
+/*---------------------------------------------------------------------------*/
+/* DLIMP_dependency_stack */
+/* */
+/* A LIFO stack of dynamic module objects (DLIMP_Dynamic_Module *) that */
+/* is retained while dependent files are being loaded and allocated. It */
+/* is used to guide which dynamic modules need to be relocated after all */
+/* items in the dependency graph have been allocated. The stack is only */
+/* used when the client asks the core loader to load a dynamic executable */
+/* or library. When relocation is completed, this stack should be empty. */
+/*---------------------------------------------------------------------------*/
+TYPE_STACK_DEFINITION(DLIMP_Dynamic_Module*, dynamic_module_ptr)
+#if 0
+extern dynamic_module_ptr_Stack DLIMP_dependency_stack;
+#endif
+
+/*****************************************************************************/
+/* is_DSBT_module() */
+/* */
+/* return true if the module uses DSBT model */
+/*****************************************************************************/
+static inline BOOL is_dsbt_module(DLIMP_Dynamic_Module *dyn_module)
+{
+ return (dyn_module->dsbt_size != 0);
+}
+
+/*****************************************************************************/
+/* is_arm_module() */
+/* */
+/* return true if the module being processed is for ARM */
+/*****************************************************************************/
+static inline BOOL is_arm_module(struct Elf32_Ehdr* fhdr)
+{
+ return fhdr->e_machine == EM_ARM;
+}
+
+/*****************************************************************************/
+/* is_c60_module() */
+/* */
+/* return true if the module being processed is for C60 */
+/*****************************************************************************/
+static inline BOOL is_c60_module(struct Elf32_Ehdr* fhdr)
+{
+ return fhdr->e_machine == EM_TI_C6000;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Identifies the current supported target. This is reset by the default */
+/* value when all loaded objects have been unloaded. */
+/*---------------------------------------------------------------------------*/
+extern int DLOAD_TARGET_MACHINE;
+
+/*---------------------------------------------------------------------------*/
+/* Identify target which is supported by the core loader. If set to EM_NONE */
+/* the target will be determined by the first loaded module. */
+/*---------------------------------------------------------------------------*/
+#if defined(ARM_TARGET) && defined(C60_TARGET)
+#define DLOAD_DEFAULT_TARGET_MACHINE (EM_NONE)
+#elif defined(ARM_TARGET)
+#define DLOAD_DEFAULT_TARGET_MACHINE (EM_ARM)
+#elif defined(C60_TARGET)
+#define DLOAD_DEFAULT_TARGET_MACHINE (EM_TI_C6000)
+#else
+#error "ARM_TARGET and/or C60_TARGET must be defined"
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* DLIMP_update_dyntag_section_address() */
+/* */
+/* Given the index of a dynamic tag which we happen to know points to a */
+/* section address, find the program header table entry associated with */
+/* the specified address and update the tag value with the real address */
+/* of the section. */
+/* */
+/*---------------------------------------------------------------------------*/
+extern BOOL DLIMP_update_dyntag_section_address(DLIMP_Dynamic_Module *dyn_module,
+ int32_t i);
+
+/*---------------------------------------------------------------------------*/
+/* Global flags to help manage internal debug and profiling efforts. */
+/*---------------------------------------------------------------------------*/
+#if 0
+#ifndef __TI_COMPILER_VERSION__
+#define LOADER_DEBUG 1
+#else
+#define LOADER_DEBUG 0
+#endif
+
+#undef LOADER_DEBUG
+#define LOADER_DEBUG 1
+#define LOADER_PROFILE 1
+#endif
+
+#define LOADER_DEBUG 0
+#define LOADER_PROFILE 0
+
+#if LOADER_DEBUG
+extern BOOL debugging_on;
+#endif
+
+#if LOADER_DEBUG || LOADER_PROFILE
+extern BOOL profiling_on;
+#endif
+
+#endif
diff --git a/src/interp/elf/dload_api.h b/src/interp/elf/dload_api.h
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+* dload_api.h
+*
+* Dynamic Loader API Specification
+* --------------------------------
+*
+* Client-side of API is assumed to be platform dependent, but object file
+* format independent.
+*
+* Core Loader side of API is assumed to be platform independent, but
+* object file format dependent and target dependent.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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.
+*
+*/
+
+#ifndef DLOAD_API_H
+#define DLOAD_API_H
+
+#include <inttypes.h>
+#include <stdio.h>
+#include "util.h"
+
+/*****************************************************************************/
+/* Specification of Loader File Descriptor. If client side of the loader */
+/* supports virtual memory, this may need to be updated to facilitate the */
+/* use of mmap(). */
+/*****************************************************************************/
+/* typedef FILE LOADER_FILE_DESC; - Moved to ewrap.h for ibl */
+
+static const int LOADER_SEEK_SET = SEEK_SET;
+static const int LOADER_SEEK_CUR = SEEK_CUR;
+static const int LOADER_SEEK_END = SEEK_END;
+
+/*****************************************************************************/
+/* TARGET_ADDRESS - type suitable for storing target memory address values. */
+/*****************************************************************************/
+typedef void* TARGET_ADDRESS;
+
+/*****************************************************************************/
+/* Core Loader Provided API Functions (Core Loader Entry Points) */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_version() */
+/* */
+/* Return a string constant representation for the version ID of the */
+/* dynamic loader's core loader source code. */
+/* */
+/*---------------------------------------------------------------------------*/
+#include "version.h"
+#define DLOAD_version() VERSION
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_initialize() */
+/* */
+/* Construct and initialize data structures internal to the dynamic */
+/* loader core. */
+/* */
+/*---------------------------------------------------------------------------*/
+void DLOAD_initialize(void);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_load_symbols() */
+/* */
+/* Load externally visible symbols from the specified file so that they */
+/* can be linked against when another object file is subsequntly loaded. */
+/* External symbols will be made available for global symbol linkage. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLOAD_load_symbols(LOADER_FILE_DESC* fp);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_load() */
+/* */
+/* Dynamically load the specified file and return a file handle for the */
+/* loaded file. If the load fails, this function will return a value */
+/* zero (0). */
+/* */
+/* The core loader must have read access to the file pointed by fp. */
+/* */
+/*---------------------------------------------------------------------------*/
+int DLOAD_load(LOADER_FILE_DESC* fp, int argc, char** argv, uint32_t *entry);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_unload() */
+/* */
+/* Given a file handle ID, unload all object segments associated with */
+/* the identified file and any of its dependents that are not still in */
+/* use. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLOAD_unload(uint32_t pseudopid);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_get_entry_names() */
+/* */
+/* Given a file handle, build a list of entry point names that are */
+/* available in the specified file. This can be used when querying */
+/* the list of global functions available in a shared library. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLOAD_get_entry_names(uint32_t file_handle, int32_t* entry_pt_cnt,
+ char*** entry_pt_names);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_query_symbol() */
+/* */
+/* Query the value of a symbol that is defined by an object file that */
+/* has previously been loaded. Boolean return value will be false if */
+/* the symbol is not found. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLOAD_query_symbol(uint32_t file_handle, const char *sym_name,
+ TARGET_ADDRESS *sym_val);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_get_entry_point() */
+/* */
+/* Given a file handle, return the entry point target address associated */
+/* with that object file. The entry point address value is written to */
+/* *sym_val. The return value of the function indicates whether the */
+/* file with the specified handle was found or not. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLOAD_get_entry_point(uint32_t file_handle, TARGET_ADDRESS *sym_val);
+
+/*****************************************************************************/
+/* Client Provided API Functions */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* File I/O */
+/* */
+/* The client side of the dynamic loader must provide basic file I/O */
+/* capabilities so that the core loader has random access into any */
+/* object file that it is asked to load. */
+/* */
+/* The client side of the dynamic loader must provide a definition of */
+/* the LOADER_FILE_DESC in dload_filedefs.h. This allows the core loader */
+/* to be independent of how the client accesses raw data in an object */
+/* file. */
+/* */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_fseek() */
+/* */
+/* Seek to a position in a file (accessed via 'stream') based on the */
+/* values for offset and origin. */
+/* */
+/*---------------------------------------------------------------------------*/
+int DLIF_fseek(LOADER_FILE_DESC *stream, int32_t offset, int origin);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_ftell() */
+/* */
+/* Return the current file position in the file identified in the */
+/* LOADER_FILE_DESC pointed to by 'stream'. */
+/* */
+/*---------------------------------------------------------------------------*/
+int32_t DLIF_ftell(LOADER_FILE_DESC *stream);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_fread() */
+/* */
+/* Read 'size' * 'nmemb' bytes of data from the file identified in the */
+/* LOADER_FILE_DESC object pointed to by 'stream', and write that data */
+/* into the memory accessed via 'ptr'. */
+/* */
+/*---------------------------------------------------------------------------*/
+size_t DLIF_fread(void *ptr, size_t size, size_t nmemb,
+ LOADER_FILE_DESC *stream);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_fclose() */
+/* */
+/* Close a file that was opened on behalf of the core loader. Ownership */
+/* of the file pointer in question belongs to the core loader, but the */
+/* client has exclusive access to the file system. */
+/* */
+/*---------------------------------------------------------------------------*/
+int DLIF_fclose(LOADER_FILE_DESC *fd);
+
+/*---------------------------------------------------------------------------*/
+/* Host Memory Management */
+/* */
+/* Allocate and free host memory as needed for the dynamic loader's */
+/* internal data structures. If the dynamic loader resides on the */
+/* target architecture, then this memory is allocated from a target */
+/* memory heap that must be managed separately from memory that is */
+/* allocated for a dynamically loaded object file. */
+/* */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_malloc() */
+/* */
+/* Allocate 'size' bytes of memory space that is usable as scratch space */
+/* (appropriate for the loader's internal data structures) by the dynamic */
+/* loader. */
+/* */
+/*---------------------------------------------------------------------------*/
+void* DLIF_malloc(size_t size);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_free() */
+/* */
+/* Free memory space that was previously allocated by DLIF_malloc(). */
+/* */
+/*---------------------------------------------------------------------------*/
+void DLIF_free(void* ptr);
+
+/*---------------------------------------------------------------------------*/
+/* Target Memory Allocator Interface */
+/* */
+/* The client side of the dynamic loader must create and maintain an */
+/* infrastructure to manage target memory. The client must keep track */
+/* of what target memory is associated with each object segment, */
+/* allocating target memory for newly loaded objects and release target */
+/* memory that is associated with objects that are being unloaded from */
+/* the target architecture. */
+/* */
+/* The two client-supplied functions, DLIF_allocate() and DLIF_release(), */
+/* are used by the core loader to interface into the client side's */
+/* target memory allocator infrastructure. */
+/* */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_SEGMENT_FLAGS - segment characteristics. */
+/*---------------------------------------------------------------------------*/
+typedef uint32_t DLOAD_SEGMENT_FLAGS;
+static const int DLOAD_SF_executable = 0x1; /* Memory must be executable */
+static const int DLOAD_SF_relocatable = 0x2; /* Segment must be relocatable */
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_MEMORY_SEGMENT - Define structure to represent placement and size */
+/* details of a segment to be loaded. */
+/*---------------------------------------------------------------------------*/
+struct DLOAD_MEMORY_SEGMENT
+{
+ uint32_t target_page; /* requested/returned memory page */
+ TARGET_ADDRESS target_address; /* requested/returned address */
+ uint32_t objsz_in_bytes; /* size of init'd part of segment */
+ uint32_t memsz_in_bytes; /* size of memory block for segment */
+};
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_MEMORY_REQUEST - Define structure to represent a target memory */
+/* request made by the core loader on behalf of a segment that the */
+/* loader needs to relocate and write into target memory. */
+/*---------------------------------------------------------------------------*/
+struct DLOAD_MEMORY_REQUEST
+{
+ LOADER_FILE_DESC *fp; /* file being loaded */
+ struct DLOAD_MEMORY_SEGMENT *segment; /* obj for req/ret alloc */
+ void *host_address; /* ret hst ptr from DLIF_copy()*/
+ BOOL is_loaded; /* returned as true if segment */
+ /* is already in target memory */
+ uint32_t offset; /* file offset of segment's */
+ /* raw data */
+ uint32_t flip_endian; /* endianness of trg opp host */
+ DLOAD_SEGMENT_FLAGS flags; /* allocation request flags */
+ uint32_t align; /* align of trg memory block */
+};
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_allocate() */
+/* */
+/* Given a DLOAD_MEMORY_REQUEST created by the core loader, allocate */
+/* target memory to fulfill the request using the target memory */
+/* management infrastrucutre on the client side of the dynamic loader. */
+/* The contents of the DLOAD_MEMORY_REQUEST will be updated per the */
+/* details of a successful allocation. The allocated page and address */
+/* can be found in the DLOAD_MEMORY_SEGMENT attached to the request. */
+/* The boolean return value reflects whether the allocation was */
+/* successful or not. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLIF_allocate(struct DLOAD_MEMORY_REQUEST *req);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_release() */
+/* */
+/* Given a DLOAD_MEMORY_SEGMENT description, free the target memory */
+/* associated with the segment using the target memory management */
+/* infrastructure on the client side of the dynamic loader. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLIF_release(struct DLOAD_MEMORY_SEGMENT* ptr);
+
+/*---------------------------------------------------------------------------*/
+/* Target Memory Access / Write Services */
+/* */
+/* The client side's target memory allocator infrastructure communicates */
+/* with the core loader through the DLOAD_MEMORY_REQUEST and */
+/* DLOAD_MEMORY_SEGMENT data structures defined above. To complete the */
+/* loading of an object segment, the segment may need to be relocated */
+/* before it is actually written to target memory in the space that was */
+/* allocated for it by DLIF_allocate(). */
+/* */
+/* The client side of the dynamic loader provides two functions to help */
+/* complete the process of loading an object segment, DLIF_copy() and */
+/* DLIF_write(). */
+/* */
+/* These functions help to make the core loader truly independent of */
+/* whether it is running on the host or target architecture and how the */
+/* client provides for reading/writing from/to target memory. */
+/* */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* DLIF_copy() */
+/* */
+/* Copy segment data from the object file described in the 'fp' and */
+/* 'offset' of the DLOAD_MEMORY_REQUEST into host accessible memory so */
+/* that it can relocated or otherwise manipulated by the core loader. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLIF_copy(struct DLOAD_MEMORY_REQUEST* req);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_write() */
+/* */
+/* Once the segment data described in the DLOAD_MEMORY_REQUEST is ready */
+/* (relocated, if needed), write the segment contents to the target */
+/* memory identified in the DLOAD_MEMORY_SEGMENT attached to the request. */
+/* */
+/* After the segment contents have been written to target memory, the */
+/* core loader should discard the DLOAD_MEMORY_REQUEST object, but retain */
+/* the DLOAD_MEMORY_SEGMENT object so that the target memory associated */
+/* with the segment can be releases when the segment is unloaded. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLIF_write(struct DLOAD_MEMORY_REQUEST* req);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_read() */
+/* */
+/* Given a host accessible buffer, read content of indicated target */
+/* memory address into the buffer. */
+/*---------------------------------------------------------------------------*/
+BOOL DLIF_read(void *ptr, size_t size, size_t nmemb, TARGET_ADDRESS src);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_execute() */
+/* */
+/* Start execution on the target architecture from given 'exec_addr'. */
+/* If the dynamic loader is running on the target architecture, this can */
+/* be effected as a simple function call. */
+/* */
+/*---------------------------------------------------------------------------*/
+int32_t DLIF_execute(TARGET_ADDRESS exec_addr);
+
+/*---------------------------------------------------------------------------*/
+/* Loading and Unloading of Dependent Files */
+/* */
+/* The dynamic loader core loader must coordinate loading and unloading */
+/* dependent object files with the client side of the dynamic loader. */
+/* This allows the client to keep its bookkeeping information up to date */
+/* with what is currently loaded on the target architecture. */
+/* */
+/* For instance, the client may need to interact with a file system or */
+/* registry. The client may also need to update debug information in */
+/* synch with the loading and unloading of shared objects. */
+/* */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* DLIF_load_dependent() */
+/* */
+/* Ask client to find and open a dependent file identified by the */
+/* 'so_name' parameter, then, if necessary, initiate a DLOAD_load() */
+/* call to actually load the shared object onto the target. A */
+/* successful load will return a file handle ID that the client can */
+/* associate with the newly loaded file. */
+/* */
+/*---------------------------------------------------------------------------*/
+int DLIF_load_dependent(const char* so_name);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_unload_dependent() */
+/* */
+/* Ask client to unload a dependent file identified by the 'file_handle' */
+/* parameter. Initiate a call to DLOAD_unload() to actually free up */
+/* the target memory that was occupied by the object file. */
+/* */
+/*---------------------------------------------------------------------------*/
+void DLIF_unload_dependent(uint32_t handle);
+
+/*---------------------------------------------------------------------------*/
+/* Error/Warning Registration Functions */
+/* */
+/* The client will maintain an error/warning log. This will allow the */
+/* core loader to register errors and warnings in the load during a */
+/* given dynamic load. The client is required to check the log after */
+/* each load attempt to report any problems. */
+/* */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Loader Warning Types */
+/*---------------------------------------------------------------------------*/
+typedef enum {
+ DLWT_MISC = 0, /* Miscellaneous warning */
+ DLWT_FILE /* Warning missing/invalid file information */
+} LOADER_WARNING_TYPE;
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_warning() */
+/* */
+/* Log a warning message with the client's error/warning handling */
+/* infrastructure. */
+/* */
+/*---------------------------------------------------------------------------*/
+void DLIF_warning(LOADER_WARNING_TYPE wtype, const char *fmt, ...);
+
+/*---------------------------------------------------------------------------*/
+/* Loader Error Types */
+/*---------------------------------------------------------------------------*/
+typedef enum {
+ DLET_MISC = 0, /* Miscellaneous error */
+ DLET_FILE, /* Error reading/processing file */
+ DLET_SYMBOL, /* Symbol resolution error */
+ DLET_RELOC, /* Relocation error */
+ DLET_MEMORY, /* Host memory allocation/free error */
+ DLET_TRGMEM, /* Target memory allocation/free error */
+ DLET_DEBUG /* Shared object or DLL debug error */
+} LOADER_ERROR_TYPE;
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_error() */
+/* */
+/* Log an error message with the client's error/warning handling */
+/* infrastructure. */
+/* */
+/*---------------------------------------------------------------------------*/
+void DLIF_error(LOADER_ERROR_TYPE etype, const char *fmt, ...);
+
+
+/*---------------------------------------------------------------------------*/
+/* Dynamic Static Base Table (DSBT) Support Functions */
+/*---------------------------------------------------------------------------*/
+#define DSBT_INDEX_INVALID -1
+#define DSBT_DSBT_BASE_INVALID 0
+#define DSBT_STATIC_BASE_INVALID 0
+
+/*****************************************************************************/
+/* Core Loader Side of DSBT Support */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_get_dsbt_size() */
+/* */
+/* Query the size of the DSBT associated with a specified file. The */
+/* client will check the size of a module's DSBT before it writes a copy */
+/* of the master DSBT to the module's DSBT. If the module's DSBT is not */
+/* big enough, an error will be emitted and the load will fail. */
+/* */
+/*---------------------------------------------------------------------------*/
+uint32_t DLOAD_get_dsbt_size(int32_t file_handle);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_get_dsbt_base() */
+/* */
+/* Find DSBT address for specified file. The client will query for this */
+/* address after allocation and symbol relocation has been completed. */
+/* The client will write a copy of the master DSBT to the returned DSBT */
+/* address if the module's DSBT size is big enough. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLOAD_get_dsbt_base(int32_t file_handle, TARGET_ADDRESS *dsbt_base);
+
+/*---------------------------------------------------------------------------*/
+/* DLOAD_get_static_base() */
+/* */
+/* Find static base for a specified file. The client will query for this */
+/* address after allocation and symbol relocation has been completed. */
+/* The client will use the returned static base value to fill the slot */
+/* in the master DSBT that is associated with this module. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLOAD_get_static_base(int32_t file_handle, TARGET_ADDRESS *static_base);
+
+
+/*****************************************************************************/
+/* Client Side of DSBT Support */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_register_dsbt_index_request() */
+/* */
+/* Register a request for a DSBT index with the client. A module can */
+/* make a specific DSBT index request or it can allow the client to */
+/* assign a DSBT index on its behalf (requested_dsbt_index == -1). The */
+/* client implementation of this function must check that a specific DSBT */
+/* index request does not conflict with a previous specific DSBT index */
+/* request. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLIF_register_dsbt_index_request(const char *requestor_name,
+ int32_t requestor_file_handle,
+ int32_t requested_dsbt_index);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_assign_dsbt_indices() */
+/* */
+/* Bind each module that registered a request for a DSBT index to a */
+/* specific slot in the DSBT. Specific requests for DSBT indices will be */
+/* honored first. Any general requests that remain will be assigned to */
+/* the first available slot in the DSBT. */
+/* */
+/*---------------------------------------------------------------------------*/
+void DLIF_assign_dsbt_indices(void);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_get_dsbt_index() */
+/* */
+/* Given a module that uses the DSBT model, return the identity of the */
+/* DSBT slot that was assigned to it by the client. This function can */
+/* only be called after the client has assigned DSBT indices to all */
+/* loaded object modules that use the DSBT model. The implementation of */
+/* this function will check that a proper DSBT index has been assigned to */
+/* the specified module and an invalid index (-1) if there is a problem. */
+/* */
+/*---------------------------------------------------------------------------*/
+int32_t DLIF_get_dsbt_index(int32_t file_handle);
+
+/*---------------------------------------------------------------------------*/
+/* DLIF_update_all_dsbts() */
+/* */
+/* Populate the client's model of the master DSBT with the static base */
+/* for each assigned slot in the DSBT, then write a copy of the master */
+/* DSBT to each module's DSBT location. The implementation of this */
+/* function must check the size of each module's DSBT to make sure that */
+/* it is large enough to hold a copy of the master DSBT. The function */
+/* will return FALSE if there is a problem. */
+/* */
+/*---------------------------------------------------------------------------*/
+BOOL DLIF_update_all_dsbts(void);
+
+#endif
diff --git a/src/interp/elf/dload_endian.c b/src/interp/elf/dload_endian.c
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+* dload_endian.c
+*
+* Simple helper functions to assist core loader with endian-ness issues
+* when the host endian-ness may be opposite the endian-ness of the target.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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 "dload_endian.h"
+
+/*****************************************************************************/
+/* DLIMP_GET_ENDIAN() - Determine endianness of the host. Uses ELF */
+/* endianness constants. */
+/*****************************************************************************/
+int DLIMP_get_endian()
+{
+ int32_t x = 0x1;
+
+ if (*((int16_t*)(&x))) return ELFDATA2LSB;
+
+ return ELFDATA2MSB;
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_ENDIAN32() - Swap endianness of a 32-bit integer. */
+/*****************************************************************************/
+void DLIMP_change_endian32(int32_t* to_change)
+{
+ int32_t temp = 0;
+ temp += (*to_change & 0x000000FF) << 24;
+ temp += (*to_change & 0x0000FF00) << 8;
+ temp += (*to_change & 0x00FF0000) >> 8;
+ temp += (*to_change & 0xFF000000) >> 24;
+ *to_change = temp;
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_ENDIAN16() - Swap endianness of a 16-bit integer. */
+/*****************************************************************************/
+void DLIMP_change_endian16(int16_t* to_change)
+{
+ int16_t temp = 0;
+ temp += (*to_change & 0x00FF) << 8;
+ temp += (*to_change & 0xFF00) >> 8;
+ *to_change = temp;
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_EHDR_ENDIAN() - Swap endianness of an ELF file header. */
+/*****************************************************************************/
+void DLIMP_change_ehdr_endian(struct Elf32_Ehdr* ehdr)
+{
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_type));
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_machine));
+ DLIMP_change_endian32((int32_t*)(&ehdr->e_version));
+ DLIMP_change_endian32((int32_t*)(&ehdr->e_entry));
+ DLIMP_change_endian32((int32_t*)(&ehdr->e_phoff));
+ DLIMP_change_endian32((int32_t*)(&ehdr->e_shoff));
+ DLIMP_change_endian32((int32_t*)(&ehdr->e_flags));
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_ehsize));
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_phentsize));
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_phnum));
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_shentsize));
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_shnum));
+ DLIMP_change_endian16((int16_t*)(&ehdr->e_shstrndx));
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_PHDR_ENDIAN() - Swap endianness of an ELF program header. */
+/*****************************************************************************/
+void DLIMP_change_phdr_endian(struct Elf32_Phdr* phdr)
+{
+ DLIMP_change_endian32((int32_t*)(&phdr->p_type));
+ DLIMP_change_endian32((int32_t*)(&phdr->p_offset));
+ DLIMP_change_endian32((int32_t*)(&phdr->p_vaddr));
+ DLIMP_change_endian32((int32_t*)(&phdr->p_paddr));
+ DLIMP_change_endian32((int32_t*)(&phdr->p_filesz));
+ DLIMP_change_endian32((int32_t*)(&phdr->p_memsz));
+ DLIMP_change_endian32((int32_t*)(&phdr->p_flags));
+ DLIMP_change_endian32((int32_t*)(&phdr->p_align));
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_DYNENT_ENDIAN() - Swap endianness of a dynamic table entry. */
+/*****************************************************************************/
+void DLIMP_change_dynent_endian(struct Elf32_Dyn* dyn)
+{
+ DLIMP_change_endian32((int32_t*)(&dyn->d_tag));
+ DLIMP_change_endian32((int32_t*)(&dyn->d_un.d_val));
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_SYM_ENDIAN() - Swap endianness of an ELF symbol table entry. */
+/*****************************************************************************/
+void DLIMP_change_sym_endian(struct Elf32_Sym* sym)
+{
+ DLIMP_change_endian32((int32_t*)(&sym->st_name));
+ DLIMP_change_endian32((int32_t*)(&sym->st_value));
+ DLIMP_change_endian32((int32_t*)(&sym->st_size));
+ DLIMP_change_endian16((int16_t*)(&sym->st_shndx));
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_RELA_ENDIAN() - Swap endianness of a RELA-type relocation. */
+/*****************************************************************************/
+void DLIMP_change_rela_endian(struct Elf32_Rela* ra)
+{
+ DLIMP_change_endian32((int32_t*)(&ra->r_offset));
+ DLIMP_change_endian32((int32_t*)(&ra->r_info));
+ DLIMP_change_endian32((int32_t*)(&ra->r_addend));
+}
+
+/*****************************************************************************/
+/* DLIMP_CHANGE_REL_ENDIAN() - Swap endianness of a REL-type relocation. */
+/*****************************************************************************/
+void DLIMP_change_rel_endian(struct Elf32_Rel* r)
+{
+ DLIMP_change_endian32((int32_t*)(&r->r_offset));
+ DLIMP_change_endian32((int32_t*)(&r->r_info));
+}
diff --git a/src/interp/elf/dload_endian.h b/src/interp/elf/dload_endian.h
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+* dload_endian.h
+*
+* Specification of functions used to assist loader with endian-ness issues.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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.
+*
+*/
+
+#ifndef DLOAD_ENDIAN_H
+#define DLOAD_ENDIAN_H
+
+#include "elf32.h"
+
+/*---------------------------------------------------------------------------*/
+/* Prototypes for ELF file object reader endianness swap routines. */
+/*---------------------------------------------------------------------------*/
+
+int DLIMP_get_endian();
+void DLIMP_change_endian32(int32_t* to_change);
+void DLIMP_change_endian16(int16_t* to_change);
+void DLIMP_change_ehdr_endian(struct Elf32_Ehdr* to_change);
+void DLIMP_change_phdr_endian(struct Elf32_Phdr* to_change);
+void DLIMP_change_dynent_endian(struct Elf32_Dyn* to_change);
+void DLIMP_change_sym_endian(struct Elf32_Sym* to_change);
+void DLIMP_change_rela_endian(struct Elf32_Rela* to_change);
+void DLIMP_change_rel_endian(struct Elf32_Rel* to_change);
+
+#endif
diff --git a/src/interp/elf/dlw_client.c b/src/interp/elf/dlw_client.c
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+* dlw_client.c
+*
+* RIDL implementation of client functions required by dynamic loader API.
+* Please see list of client-required API functions in dload_api.h.
+*
+* This implementation of RIDL is expected to run on the DSP. It uses C6x
+* RTS functions for file I/O and memory management (both host and target
+* memory).
+*
+* A loader that runs on a GPP for the purposes of loading C6x code onto a
+* DSP will likely need to re-write all of the functions contained in this
+* module.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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 "types.h"
+#include "ewrap.h"
+#include "ArrayList.h"
+#include "dload_api.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "file_ovr.h"
+
+#if 0
+#include "dlw_debug.h"
+#include "dlw_dsbt.h"
+#include "dlw_trgmem.h"
+#endif
+
+/*****************************************************************************/
+/* Client Provided File I/O */
+/*****************************************************************************/
+/*****************************************************************************/
+/* DLIF_FSEEK() - Seek to a position in specified file. */
+/*****************************************************************************/
+int DLIF_fseek(LOADER_FILE_DESC *stream, int32_t offset, int origin)
+{
+ return fseek(stream, offset, origin);
+}
+
+/*****************************************************************************/
+/* DLIF_FTELL() - Return the current position in the given file. */
+/*****************************************************************************/
+int32_t DLIF_ftell(LOADER_FILE_DESC *stream)
+{
+ return ftell(stream);
+}
+
+/*****************************************************************************/
+/* DLIF_FREAD() - Read data from file into a host-accessible data buffer */
+/* that can be accessed through "ptr". */
+/*****************************************************************************/
+size_t DLIF_fread(void *ptr, size_t size, size_t nmemb,
+ LOADER_FILE_DESC *stream)
+{
+ return fread(ptr, size, nmemb, stream);
+}
+
+/*****************************************************************************/
+/* DLIF_FCLOSE() - Close a file that was opened on behalf of the core */
+/* loader. Core loader has ownership of the file pointer, but client */
+/* has access to file system. */
+/*****************************************************************************/
+int32_t DLIF_fclose(LOADER_FILE_DESC *fd)
+{
+ return fclose(fd);
+}
+
+/*****************************************************************************/
+/* Client Provided Host Memory Management */
+/*****************************************************************************/
+/*****************************************************************************/
+/* DLIF_MALLOC() - Allocate host memory suitable for loader scratch space. */
+/*****************************************************************************/
+void* DLIF_malloc(size_t size)
+{
+ return malloc(size*sizeof(uint8_t));
+}
+
+/*****************************************************************************/
+/* DLIF_FREE() - Free host memory previously allocated with DLIF_malloc(). */
+/*****************************************************************************/
+void DLIF_free(void* ptr)
+{
+ free(ptr);
+}
+
+/*****************************************************************************/
+/* Client Provided Target Memory Management */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* RIDL-Specific hack to facilitate target memory allocation. */
+/*****************************************************************************/
+/*****************************************************************************/
+/* DLIF_ALLOCATE() - Return the load address of the segment/section */
+/* described in its parameters and record the run address in */
+/* run_address field of DLOAD_MEMORY_REQUEST. */
+/*****************************************************************************/
+BOOL DLIF_allocate(struct DLOAD_MEMORY_REQUEST *targ_req)
+{
+ /*------------------------------------------------------------------------*/
+ /* Get pointers to API segment and file descriptors. */
+ /*------------------------------------------------------------------------*/
+ struct DLOAD_MEMORY_SEGMENT* obj_desc = targ_req->segment;
+ LOADER_FILE_DESC* f = targ_req->fp;
+
+ /*------------------------------------------------------------------------*/
+ /* Request target memory for this segment from the "blob". */
+ /*------------------------------------------------------------------------*/
+ if (!DLTMM_malloc(targ_req, obj_desc))
+ {
+ DLIF_error(DLET_MEMORY, "Failed to allocate target memory for segment.\n");
+ return 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* As required by API, copy the described segment into memory from file. */
+ /* We're the client, not the loader, so we can use fseek() and fread(). */
+ /*------------------------------------------------------------------------*/
+ /* ??? I don't think we want to do this if we are allocating target */
+ /* memory for the run only placement of this segment. If it is the */
+ /* load placement or both load and run placement, then we can do the */
+ /* copy. */
+ /*------------------------------------------------------------------------*/
+ memset(targ_req->host_address, 0, obj_desc->memsz_in_bytes);
+ fseek(f,targ_req->offset,SEEK_SET);
+ fread(targ_req->host_address,obj_desc->objsz_in_bytes,1,f);
+
+ /*------------------------------------------------------------------------*/
+ /* Once we have target address for this allocation, add debug information */
+ /* about this segment to the debug record for the module that is */
+ /* currently being loaded. */
+ /*------------------------------------------------------------------------*/
+ if (DLL_debug)
+ {
+ /*---------------------------------------------------------------------*/
+ /* Add information about this segment's location to the segment debug */
+ /* information associated with the module that is currently being */
+ /* loaded. */
+ /*---------------------------------------------------------------------*/
+ /* ??? We need a way to determine whether the target address in the */
+ /* segment applies to the load address of the segment or the */
+ /* run address. For the time being, we assume that it applies */
+ /* to both (that is, the dynamic loader does not support */
+ /* separate load and run placement for a given segment). */
+ /*---------------------------------------------------------------------*/
+ DLDBG_add_segment_record(obj_desc);
+ }
+
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("DLIF_allocate: buffer 0x%x\n", targ_req->host_address);
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Target memory request was successful. */
+ /*------------------------------------------------------------------------*/
+ return 1;
+}
+
+/*****************************************************************************/
+/* DLIF_RELEASE() - Unmap or free target memory that was previously */
+/* allocated by DLIF_allocate(). */
+/*****************************************************************************/
+BOOL DLIF_release(struct DLOAD_MEMORY_SEGMENT* ptr)
+{
+#if LOADER_DEBUG
+ if (debugging_on)
+ printf("DLIF_free: %d bytes starting at 0x%x\n",
+ ptr->memsz_in_bytes, ptr->target_address);
+#endif
+
+ /*------------------------------------------------------------------------*/
+ /* Find the target memory packet associated with this address and mark it */
+ /* as available (will also merge with adjacent free packets). */
+ /*------------------------------------------------------------------------*/
+ DLTMM_free(ptr->target_address);
+
+ return 1;
+}
+
+/*****************************************************************************/
+/* DLIF_COPY() - Copy data from file to host-accessible memory. */
+/* Returns a host pointer to the data in the host_address field of the */
+/* DLOAD_MEMORY_REQUEST object. */
+/*****************************************************************************/
+BOOL DLIF_copy(struct DLOAD_MEMORY_REQUEST* targ_req)
+{
+ targ_req->host_address = (void*)(targ_req->segment->target_address);
+ return 1;
+}
+
+/*****************************************************************************/
+/* DLIF_READ() - Read content from target memory address into host- */
+/* accessible buffer. */
+/*****************************************************************************/
+BOOL DLIF_read(void *ptr, size_t size, size_t nmemb, TARGET_ADDRESS src)
+{
+ if (!memcpy(ptr, (const void *)src, size * nmemb))
+ return 0;
+
+ return 1;
+}
+
+/*****************************************************************************/
+/* DLIF_WRITE() - Write updated (relocated) segment contents to target */
+/* memory. */
+/*****************************************************************************/
+BOOL DLIF_write(struct DLOAD_MEMORY_REQUEST* req)
+{
+ /*------------------------------------------------------------------------*/
+ /* Nothing to do since we are relocating directly into target memory. */
+ /*------------------------------------------------------------------------*/
+ return 1;
+}
+
+/*****************************************************************************/
+/* DLIF_EXECUTE() - Transfer control to specified target address. */
+/*****************************************************************************/
+int32_t DLIF_execute(TARGET_ADDRESS exec_addr)
+{
+ /*------------------------------------------------------------------------*/
+ /* This call will only work if the host and target are the same instance. */
+ /* The compiler may warn about this conversion from an object to a */
+ /* function pointer. */
+ /*------------------------------------------------------------------------*/
+ return ((int32_t(*)())(exec_addr))();
+}
+
+
+#if 0
+/*****************************************************************************/
+/* Client Provided Communication Mechanisms to assist with creation of */
+/* DLLView debug information. Client needs to know exactly when a segment */
+/* is being loaded or unloaded so that it can keep its debug information */
+/* up to date. */
+/*****************************************************************************/
+/*****************************************************************************/
+/* DLIF_LOAD_DEPENDENT() - Perform whatever maintenance is needed in the */
+/* client when loading of a dependent file is initiated by the core */
+/* loader. Open the dependent file on behalf of the core loader, */
+/* then invoke the core loader to get it into target memory. The core */
+/* loader assumes ownership of the dependent file pointer and must ask */
+/* the client to close the file when it is no longer needed. */
+/* */
+/* If debug support is needed under the Braveheart model, then create */
+/* a host version of the debug module record for this object. This */
+/* version will get updated each time we allocate target memory for a */
+/* segment that belongs to this module. When the load returns, the */
+/* client will allocate memory for the debug module from target memory */
+/* and write the host version of the debug module into target memory */
+/* at the appropriate location. After this takes place the new debug */
+/* module needs to be added to the debug module list. The client will */
+/* need to update the tail of the DLModules list to link the new debug */
+/* module onto the end of the list. */
+/* */
+/*****************************************************************************/
+int DLIF_load_dependent(const char* so_name)
+{
+ /*------------------------------------------------------------------------*/
+ /* Find the path and file name associated with the given so_name in the */
+ /* client's file registry. */
+ /*------------------------------------------------------------------------*/
+ /* If we can't find the so_name in the file registry (or if the registry */
+ /* is not implemented yet), we'll open the file using the so_name. */
+ /*------------------------------------------------------------------------*/
+ int to_ret = 0;
+ FILE* fp = fopen(so_name, "rb");
+
+ /*------------------------------------------------------------------------*/
+ /* We need to make sure that the file was properly opened. */
+ /*------------------------------------------------------------------------*/
+ if (!fp)
+ {
+ DLIF_error(DLET_FILE, "Can't open dependent file '%s'.\n", so_name);
+ return 0;
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* If the dynamic loader is providing debug support for a DLL View plug- */
+ /* in or script of some sort, then we are going to create a host version */
+ /* of the debug module record for the so_name module. */
+ /*------------------------------------------------------------------------*/
+ /* In the Braveheart view of the world, debug support is only to be */
+ /* provided if the DLModules symbol is defined in the base image. */
+ /* We will set up a DLL_debug flag when the command to load the base */
+ /* image is issued. */
+ /*------------------------------------------------------------------------*/
+ if (DLL_debug)
+ DLDBG_add_host_record(so_name);
+
+ /*------------------------------------------------------------------------*/
+ /* Tell the core loader to proceed with loading the module. */
+ /*------------------------------------------------------------------------*/
+ /* Note that the client is turning ownership of the file pointer over to */
+ /* the core loader at this point. The core loader will need to ask the */
+ /* client to close the dependent file when it is done using the dependent */
+ /* file pointer. */
+ /*------------------------------------------------------------------------*/
+ to_ret = DLOAD_load(fp, 0, NULL);
+
+ /*------------------------------------------------------------------------*/
+ /* If the dependent load was successful, update the DLModules list in */
+ /* target memory as needed. */
+ /*------------------------------------------------------------------------*/
+ if (to_ret != 0)
+ {
+ /*---------------------------------------------------------------------*/
+ /* We will need to copy the information from our host version of the */
+ /* debug record into actual target memory. */
+ /*---------------------------------------------------------------------*/
+ if (DLL_debug)
+ {
+ /*---------------------------------------------------------------*/
+ /* Allocate target memory for the module's debug record. Use */
+ /* host version of the debug information to determine how much */
+ /* target memory we need and how it is to be filled in. */
+ /*---------------------------------------------------------------*/
+ /* Note that we don't go through the normal API functions to get */
+ /* target memory and write the debug information since we're not */
+ /* dealing with object file content here. The DLL View debug is */
+ /* supported entirely on the client side. */
+ /*---------------------------------------------------------------*/
+ DLDBG_add_target_record(to_ret);
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+ /* Report failure to load dependent. */
+ /*------------------------------------------------------------------------*/
+ else
+ DLIF_error(DLET_MISC, "Failed load of dependent file '%s'.\n", so_name);
+
+ return to_ret;
+}
+
+#endif
+
+#if 0
+/*****************************************************************************/
+/* DLIF_UNLOAD_DEPENDENT() - Perform whatever maintenance is needed in the */
+/* client when unloading of a dependent file is initiated by the core */
+/* loader. Invoke the DLOAD_unload() function to get the core loader */
+/* to release any target memory that is associated with the dependent */
+/* file's segments. */
+/*****************************************************************************/
+void DLIF_unload_dependent(uint32_t handle)
+{
+ /*------------------------------------------------------------------------*/
+ /* If the specified module is no longer needed, DLOAD_load() will spin */
+ /* through the object descriptors associated with the module and free up */
+ /* target memory that was allocated to any segment in the module. */
+ /*------------------------------------------------------------------------*/
+ /* If DLL debugging is enabled, find module debug record associated with */
+ /* this module and remove it from the DLL debug list. */
+ /*------------------------------------------------------------------------*/
+ if (DLOAD_unload(handle))
+ {
+ DSBT_release_entry(handle);
+ if (DLL_debug) DLDBG_rm_target_record(handle);
+ }
+}
+
+#endif
+
+/*****************************************************************************/
+/* Client Provided API Functions to Support Logging Warnings/Errors */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* DLIF_WARNING() - Write out a warning message from the core loader. */
+/*****************************************************************************/
+void DLIF_warning(LOADER_WARNING_TYPE wtype, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap,fmt);
+ printf("<< D L O A D >> WARNING: ");
+ vprintf(fmt,ap);
+ va_end(ap);
+}
+
+/*****************************************************************************/
+/* DLIF_ERROR() - Write out an error message from the core loader. */
+/*****************************************************************************/
+void DLIF_error(LOADER_ERROR_TYPE etype, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap,fmt);
+ printf("<< D L O A D >> ERROR: ");
+ vprintf(fmt,ap);
+ va_end(ap);
+}
+
+/*****************************************************************************
+ * END API FUNCTION DEFINITIONS
+ *****************************************************************************/
diff --git a/src/interp/elf/elf32.h b/src/interp/elf/elf32.h
--- /dev/null
+++ b/src/interp/elf/elf32.h
@@ -0,0 +1,756 @@
+/*
+* elf32.h
+*
+* Basic Data Structures for 32-bit ELF Object Format Files
+*
+* The data structures in this file come primarily from this specification:
+*
+* Tool Interface Standard (TIS)
+* Executable and Linking Format (ELF) Specification
+* Version 1.2
+*
+* TIS Committee
+* May 1995
+*
+* Additions and enhancements from this specification are also included:
+*
+* System V Application Binary Interface
+* DRAFT 17
+* December 2003
+*
+* http://sco.com/developers/gabi/2003-12-17/contents.html
+*
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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.
+*
+*/
+
+#ifndef ELF32_H
+#define ELF32_H
+
+#include <inttypes.h>
+
+/*---------------------------------------------------------------------------*/
+/* 32-Bit Data Types (Figure 1-2, page 1-2) */
+/*---------------------------------------------------------------------------*/
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+
+
+/*****************************************************************************/
+/* ELF Header */
+/* PP. 1-4 */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* ELF Identification Indexes (indexes into Elf32_Ehdr.e_ident[] below) */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ EI_MAG0 = 0, /* File identification */
+ EI_MAG1 = 1, /* File identification */
+ EI_MAG2 = 2, /* File identification */
+ EI_MAG3 = 3, /* File identification */
+ EI_CLASS = 4, /* File class */
+ EI_DATA = 5, /* Data encoding */
+ EI_VERSION = 6, /* File version */
+ EI_OSABI = 7, /* Operating system / ABI */
+ EI_ABIVERSION = 8, /* ABI version */
+ EI_PAD = 9, /* Start of padding bytes */
+ EI_NIDENT = 16 /* Size of Elf32_Ehdr.e_ident[] */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* ELF Header Data Structure */
+/*---------------------------------------------------------------------------*/
+struct Elf32_Ehdr
+{
+ uint8_t e_ident[EI_NIDENT]; /* ELF Magic Number */
+ Elf32_Half e_type; /* Object File Type */
+ Elf32_Half e_machine; /* Target Processor */
+ Elf32_Word e_version; /* Object File Version */
+ Elf32_Addr e_entry; /* Entry Point */
+ Elf32_Off e_phoff; /* Program Header Table Offset */
+ Elf32_Off e_shoff; /* Section Header Table Offset */
+ Elf32_Word e_flags; /* Processor-Specific Flags */
+ Elf32_Half e_ehsize; /* Size of ELF header */
+ Elf32_Half e_phentsize; /* Size of a Program Header */
+ Elf32_Half e_phnum; /* # Entries in Program Header Table */
+ Elf32_Half e_shentsize; /* Size of a Section Header */
+ Elf32_Half e_shnum; /* # Entries in Section Header Table */
+ Elf32_Half e_shstrndx; /* Section Name String Table Section */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Object File Types (value of "e_type") */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ ET_NONE = 0, /* No file type */
+ ET_REL = 1, /* Relocatable file */
+ ET_EXEC = 2, /* Executable file */
+ ET_DYN = 3, /* Shared object file */
+ ET_CORE = 4, /* Core file */
+ ET_LOOS = 0xfe00, /* First OS-specific value */
+ ET_HIPS = 0xfeff, /* Last OS-specific value */
+ ET_LOPROC = 0xff00, /* First processor-specific value */
+ ET_HIPROC = 0xffff /* Last processor-specific value */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Target Processors (value of "e_machine") */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ EM_NONE = 0, /* No machine */
+ EM_M32 = 1, /* AT&T WE 32100 */
+ EM_SPARC = 2, /* SPARC */
+ EM_386 = 3, /* Intel 80386 */
+ EM_68K = 4, /* Motorola 68000 */
+ EM_88K = 5, /* Motorola 88000 */
+ EM_860 = 7, /* Intel 80860 */
+ EM_MIPS = 8, /* MIPS I Architecture */
+ EM_S370 = 9, /* IBM System/370 Processor */
+ EM_MIPS_RS3_LE = 10, /* MIPS RS3000 Little-endian */
+ EM_PARISC = 15, /* Hewlett-Packard PA-RISC */
+ EM_VPP500 = 17, /* Fujitsu VPP500 */
+ EM_SPARC32PLUS = 18, /* Enhanced instruction set SPARC */
+ EM_960 = 19, /* Intel 80960 */
+ EM_PPC = 20, /* PowerPC */
+ EM_PPC64 = 21, /* 64-bit PowerPC */
+ EM_S390 = 22, /* IBM System/390 Processor */
+ EM_V800 = 36, /* NEC V800 */
+ EM_FR20 = 37, /* Fujitsu FR20 */
+ EM_RH32 = 38, /* TRW RH-32 */
+ EM_RCE = 39, /* Motorola RCE */
+ EM_ARM = 40, /* Advanced RISC Machines ARM */
+ EM_ALPHA = 41, /* Digital Alpha */
+ EM_SH = 42, /* Hitachi SH */
+ EM_SPARCV9 = 43, /* SPARC Version 9 */
+ EM_TRICORE = 44, /* Siemens TriCore embedded processor */
+ EM_ARC = 45, /* "Argonaut RISC Core, Argonaut Technologies Inc. */
+ EM_H8_300 = 46, /* Hitachi H8/300 */
+ EM_H8_300H = 47, /* Hitachi H8/300H */
+ EM_H8S = 48, /* Hitachi H8S */
+ EM_H8_500 = 49, /* Hitachi H8/500 */
+ EM_IA_64 = 50, /* Intel IA-64 processor architecture */
+ EM_MIPS_X = 51, /* Stanford MIPS-X */
+ EM_COLDFIRE = 52, /* Motorola ColdFire */
+ EM_68HC12 = 53, /* Motorola M68HC12 */
+ EM_MMA = 54, /* Fujitsu MMA Multimedia Accelerator */
+ EM_PCP = 55, /* Siemens PCP */
+ EM_NCPU = 56, /* Sony nCPU embedded RISC processor */
+ EM_NDR1 = 57, /* Denso NDR1 microprocessor */
+ EM_STARCORE = 58, /* Motorola Star*Core processor */
+ EM_ME16 = 59, /* Toyota ME16 processor */
+ EM_ST100 = 60, /* STMicroelectronics ST100 processor */
+ EM_TINYJ = 61, /* Advanced Logic Corp. TinyJ embedded processor f */
+ EM_X86_64 = 62, /* AMD x86-64 architecture */
+ EM_PDSP = 63, /* Sony DSP Processor */
+ EM_PDP10 = 64, /* Digital Equipment Corp. PDP-10 */
+ EM_PDP11 = 65, /* Digital Equipment Corp. PDP-11 */
+ EM_FX66 = 66, /* Siemens FX66 microcontroller */
+ EM_ST9PLUS = 67, /* STMicroelectronics ST9+ 8/16 bit microcontrolle */
+ EM_ST7 = 68, /* STMicroelectronics ST7 8-bit microcontroller */
+ EM_68HC16 = 69, /* Motorola MC68HC16 Microcontroller */
+ EM_68HC11 = 70, /* Motorola MC68HC11 Microcontroller */
+ EM_68HC08 = 71, /* Motorola MC68HC08 Microcontroller */
+ EM_68HC05 = 72, /* Motorola MC68HC05 Microcontroller */
+ EM_SVX = 73, /* Silicon Graphics SVx */
+ EM_ST19 = 74, /* STMicroelectronics ST19 8-bit microcontroller */
+ EM_VAX = 75, /* Digital VAX */
+ EM_CRIS = 76, /* Axis Communications 32-bit embedded processor */
+ EM_JAVELIN = 77, /* Infineon Technologies 32-bit embedded processor */
+ EM_FIREPATH = 78, /* Element 14 64-bit DSP Processor */
+ EM_ZSP = 79, /* LSI Logic 16-bit DSP Processor */
+ EM_MMIX = 80, /* Donald Knuth's educational 64-bit processor */
+ EM_HUANY = 81, /* Harvard University machine-independent object f */
+ EM_PRISM = 82, /* SiTera Prism */
+ EM_AVR = 83, /* Atmel AVR 8-bit microcontroller */
+ EM_FR30 = 84, /* Fujitsu FR30 */
+ EM_D10V = 85, /* Mitsubishi D10V */
+ EM_D30V = 86, /* Mitsubishi D30V */
+ EM_V850 = 87, /* NEC v850 */
+ EM_M32R = 88, /* Mitsubishi M32R */
+ EM_MN10300 = 89, /* Matsushita MN10300 */
+ EM_MN10200 = 90, /* Matsushita MN10200 */
+ EM_PJ = 91, /* picoJava */
+ EM_OPENRISC = 92, /* OpenRISC 32-bit embedded processor */
+ EM_ARC_A5 = 93, /* ARC Cores Tangent-A5 */
+ EM_XTENSA = 94, /* Tensilica Xtensa Architecture */
+ EM_VIDEOCORE = 95, /* Alphamosaic VideoCore processor */
+ EM_TMM_GPP = 96, /* Thompson Multimedia General Purpose Processor */
+ EM_NS32K = 97, /* National Semiconductor 32000 series */
+ EM_TPC = 98, /* Tenor Network TPC processor */
+ EM_SNP1K = 99, /* Trebia SNP 1000 processor */
+ EM_ST200 = 100, /* STMicroelectronics (www.st.com) ST200 microcont */
+ EM_IP2K = 101, /* Ubicom IP2xxx microcontroller family */
+ EM_MAX = 102, /* MAX Processor */
+ EM_CR = 103, /* National Semiconductor CompactRISC microprocess */
+ EM_F2MC16 = 104, /* Fujitsu F2MC16 */
+ EM_MSP430 = 105, /* Texas Instruments embedded microcontroller msp4 */
+ EM_BLACKFIN = 106, /* Analog Devices Blackfin (DSP) processor */
+ EM_SE_C33 = 107, /* S1C33 Family of Seiko Epson processors */
+ EM_SEP = 108, /* Sharp embedded microprocessor */
+ EM_ARCA = 109, /* Arca RISC Microprocessor */
+ EM_UNICORE = 110, /* Microprocessor series from PKU-Unity Ltd. and M */
+
+ /*------------------------------------------------------------------------*/
+ /* ELF Magic Numbers Reserved For Texas Instruments */
+ /* */
+ /* The magic numbers 140-159 were reserved through SCO to be included */
+ /* in the official ELF specification. Please see Don Darling */
+ /* regarding any changes or allocation of the numbers below. */
+ /* */
+ /* When we allocate a number for use, SCO needs to be notified so they */
+ /* can update the ELF specification accordingly. */
+ /*------------------------------------------------------------------------*/
+ EM_TI_C6000 = 140, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED02 = 141, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED03 = 142, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED04 = 143, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED05 = 144, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED06 = 145, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED07 = 146, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED08 = 147, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED09 = 148, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED10 = 149, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED11 = 150, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED12 = 151, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED13 = 152, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED14 = 153, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED15 = 154, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED16 = 155, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED17 = 156, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED18 = 157, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED19 = 158, /* Reserved for Texas Instruments; unused */
+ EM_TI_UNUSED20 = 159 /* Reserved for Texas Instruments; unused */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Object File Version (value of "e_version") */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ EV_NONE = 0, /* Invalid version */
+ EV_CURRENT = 1 /* Current version */
+};
+
+
+/*****************************************************************************/
+/* ELF Identification */
+/* PP. 1-6 */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Identification Values for ELF Files */
+/*---------------------------------------------------------------------------*/
+
+/* EI_MAG0 to EI_MAG3 */
+enum
+{
+ ELFMAG0 = 0x7f, /* e_ident[EI_MAG0] */
+ ELFMAG1 = 'E', /* e_ident[EI_MAG1] */
+ ELFMAG2 = 'L', /* e_ident[EI_MAG2] */
+ ELFMAG3 = 'F' /* e_ident[EI_MAG3] */
+};
+
+/* EI_CLASS */
+enum
+{
+ ELFCLASSNONE = 0, /* Invalid class */
+ ELFCLASS32 = 1, /* 32-bit objects */
+ ELFCLASS64 = 2 /* 64-bit objects */
+};
+
+/* EI_DATA */
+enum
+{
+ ELFDATANONE = 0, /* Invalid data encoding */
+ ELFDATA2LSB = 1, /* Little-endian data */
+ ELFDATA2MSB = 2 /* Big-endian data */
+};
+
+/* EI_OSABI */
+enum
+{
+ ELFOSABI_NONE = 0, /* No extensions or unspecified */
+ ELFOSABI_HPUX = 1, /* Hewlett-Packard HP-UX */
+ ELFOSABI_NETBSD = 2, /* NetBSD */
+ ELFOSABI_LINUX = 3, /* Linux */
+ ELFOSABI_SOLARIS = 6, /* Sun Solaris */
+ ELFOSABI_AIX = 7, /* AIX */
+ ELFOSABI_IRIX = 8, /* IRIX */
+ ELFOSABI_FREEBSD = 9, /* FreeBSD */
+ ELFOSABI_TRU64 = 10, /* Compaq TRU64 UNIX */
+ ELFOSABI_MODESTO = 11, /* Novell Modesto */
+ ELFOSABI_OPENBSD = 12, /* Open BSD */
+ ELFOSABI_OPENVMS = 13, /* Open VMS */
+ ELFOSABI_NSK = 14, /* Hewlett-Packard Non-Stop Kernel */
+ ELFOSABI_AROS = 15 /* Amiga Research OS */
+};
+
+/*****************************************************************************/
+/* Program Header */
+/* PP. 2-2 */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Program Header Data Structure */
+/*---------------------------------------------------------------------------*/
+struct Elf32_Phdr
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment file image size */
+ Elf32_Word p_memsz; /* Segment memory image size */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Segment Types (value of "p_type") */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ PT_NULL = 0, /* Unused table entry */
+ PT_LOAD = 1, /* Loadable segment */
+ PT_DYNAMIC = 2, /* Dynamic linking information */
+ PT_INTERP = 3, /* Interpreter path string location */
+ PT_NOTE = 4, /* Location and size of auxiliary information */
+ PT_SHLIB = 5, /* Shared library information */
+ PT_PHDR = 6, /* Location and size of program header table */
+ PT_TLS = 7, /* Specifies the Thread-Local Storage template */
+ PT_LOOS = 0x60000000, /* First OS-specific value */
+ PT_HIOS = 0x6fffffff, /* Last OS-specific value */
+ PT_LOPROC = 0x70000000, /* First processor-specific value */
+ PT_HIPROC = 0x7fffffff /* Last processor-specific value */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Segment Permissions (value of "p_flags") */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ PF_X = 0x1, /* Execute */
+ PF_W = 0x2, /* Write */
+ PF_R = 0x4, /* Read */
+ PF_MASKOS = 0x0ff00000, /* OS-specific mask */
+ PF_MASKPROC = 0xf0000000 /* Processor-specific mask */
+};
+
+/*****************************************************************************/
+/* Sections */
+/* PP. 1-9 */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Section Header Data Structure */
+/*---------------------------------------------------------------------------*/
+struct Elf32_Shdr
+{
+ Elf32_Word sh_name; /* Section name (offset into string section) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Address in memory image */
+ Elf32_Off sh_offset; /* File offset of section data */
+ Elf32_Word sh_size; /* Size of the section in bytes */
+ Elf32_Word sh_link; /* Link to the section header table */
+ Elf32_Word sh_info; /* Extra information depending on section type */
+ Elf32_Word sh_addralign; /* Address alignment constraints */
+ Elf32_Word sh_entsize; /* Size of fixed-size entries in section */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Special Section Indexes */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ SHN_UNDEF = 0, /* Referenced by undefined values */
+ SHN_LORESERVE = 0xff00, /* First reserved index */
+ SHN_LOPROC = 0xff00, /* First processor-specific index */
+ SHN_HIPROC = 0xff1f, /* Last processor-specific index */
+ SHN_LOOS = 0xff20, /* First OS-specific index */
+ SHN_HIOS = 0xff3f, /* Last OS-specific index */
+ SHN_ABS = 0xfff1, /* Referenced by absolute values */
+ SHN_COMMON = 0xfff2, /* Referenced by common values */
+ SHN_XINDEX = 0xffff, /* Indirect index reference (escape value) */
+ SHN_HIRESERVE = 0xffff /* Last reserved index */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Section Types (value of "sh_type") */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ SHT_NULL = 0, /* Inactive section */
+ SHT_PROGBITS = 1, /* Application-specific information */
+ SHT_SYMTAB = 2, /* Symbol table */
+ SHT_STRTAB = 3, /* String table */
+ SHT_RELA = 4, /* Relocation entries (explicit addends) */
+ SHT_HASH = 5, /* Symbol hash table */
+ SHT_DYNAMIC = 6, /* Dynamic linking information */
+ SHT_NOTE = 7, /* Miscellaneous information */
+ SHT_NOBITS = 8, /* Contains no data in file */
+ SHT_REL = 9, /* Relocation entries (no expl. addends) */
+ SHT_SHLIB = 10, /* Shared library */
+ SHT_DYNSYM = 11, /* Dynamic symbol table */
+ SHT_INIT_ARRAY = 14, /* Pointers to initialization functions */
+ SHT_FINI_ARRAY = 15, /* Pointers to termination functions */
+ SHT_PREINIT_ARRAY = 16, /* Pointers to pre-init functions */
+ SHT_GROUP = 17, /* Section group */
+ SHT_SYMTAB_SHNDX = 18, /* Section indexes for SHN_XINDEX refs. */
+ SHT_LOOS = 0x60000000, /* First OS-specific type */
+ SHT_HIOS = 0x6fffffff, /* Last OS-specific type */
+ SHT_LOPROC = 0x70000000, /* First processor-specific type */
+ SHT_HIPROC = 0x7fffffff, /* Last processor-specific type */
+ SHT_LOUSER = 0x80000000, /* First application-specific type */
+ SHT_HIUSER = 0xffffffff /* Last application-specific type */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Section Attribute Flags (value of "sh_flags") */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ SHF_WRITE = 0x1, /* Writable during process execution */
+ SHF_ALLOC = 0x2, /* Loaded into processor memory */
+ SHF_EXECINSTR = 0x4, /* Contains executable instructions */
+ SHF_MERGE = 0x10, /* Can be merged */
+ SHF_STRINGS = 0x20, /* Contains null-terminated strings */
+ SHF_INFO_LINK = 0x40, /* sh_info contains a section index */
+ SHF_LINK_ORDER = 0x80, /* Maintain section ordering */
+ SHF_OS_NONCONFORMING = 0x100, /* OS-specific processing required */
+ SHF_GROUP = 0x200, /* Member of a section group */
+ SHF_TLS = 0x400, /* Contains Thread-Local Storage */
+ SHF_MASKOS = 0x0ff00000, /* Mask of OS-specific flags */
+ SHF_MASKPROC = 0xf0000000 /* Mask for processor-specific flags */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Section Group Flags */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ GRP_COMDAT = 0x1, /* Common data; only one is kept by linker */
+ GRP_MASKOS = 0x0ff00000, /* Mask for OS-specific group flags */
+ GRP_MASKPROC = 0xf0000000 /* Mask for processor-specific group flags */
+};
+
+
+/*****************************************************************************/
+/* Symbol Table */
+/* PP. 1-18 */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Symbol Table Entry Data Structure */
+/*---------------------------------------------------------------------------*/
+struct Elf32_Sym
+{
+ Elf32_Word st_name; /* String table offset for symbol name */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ uint8_t st_info; /* Symbol type and binding */
+ uint8_t st_other; /* Symbol visibility */
+ Elf32_Half st_shndx; /* Symbol type / defining section */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Undefined Symbol Index */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ STN_UNDEF = 0 /* First symbol table entry is always undefined */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Symbol Binding and Type Utility Functions. */
+/*---------------------------------------------------------------------------*/
+static inline uint8_t ELF32_ST_BIND(uint8_t i) { return (i >> 4); }
+static inline uint8_t ELF32_ST_TYPE(uint8_t i) { return (i & 0xf); }
+static inline uint8_t ELF32_ST_INFO(uint8_t b, uint8_t t)
+ { return ((b << 4) + (t & 0xf)); }
+static inline uint8_t ELF32_ST_VISIBILITY(uint8_t o) { return (o & 0x3); }
+
+
+/*---------------------------------------------------------------------------*/
+/* Symbol Binding (value returned by ELF32_ST_BIND()) */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ STB_LOCAL = 0, /* Symbol does not have external linkage */
+ STB_GLOBAL = 1, /* Symbol has external linkage */
+ STB_WEAK = 2, /* Symbol has weak external linkage */
+ STB_LOOS = 10, /* First OS-specific binding */
+ STB_HIOS = 12, /* Last OS-specific binding */
+ STB_LOPROC = 13, /* First processor-specific binding */
+ STB_HIPROC = 15 /* Last processor-specific binding */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Symbol Types (value returned by ELF32_ST_TYPE()) */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ STT_NOTYPE = 0, /* Unspecified type */
+ STT_OBJECT = 1, /* Associated with a data object */
+ STT_FUNC = 2, /* Associated with executable code */
+ STT_SECTION = 3, /* Associated with a section */
+ STT_FILE = 4, /* Associated with a source file */
+ STT_COMMON = 5, /* Labels an uninitialized common block */
+ STT_TLS = 6, /* Specifies a thread-local storage entity */
+ STT_LOOS = 10, /* First OS-specific type */
+ STT_HIOS = 12, /* Last OS-specific type */
+ STT_LOPROC = 13, /* First processor-specific type */
+ STT_HIPROC = 15 /* Last processor-specific type */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Symbol Visibility (value returned by ELF32_ST_VISIBILITY()) */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ STV_DEFAULT = 0, /* Visibility specified by binding type */
+ STV_INTERNAL = 1, /* Like STV_HIDDEN, with processor-specific semantics */
+ STV_HIDDEN = 2, /* Not visible to other components */
+ STV_PROTECTED = 3 /* Visible in other components but not preemptable */
+};
+
+/*****************************************************************************/
+/* Relocation */
+/* PP. 1-22 */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Relocation Entries Data Structures */
+/*---------------------------------------------------------------------------*/
+struct Elf32_Rel
+{
+ Elf32_Addr r_offset; /* Offset of the relocatable value in the section */
+ Elf32_Word r_info; /* Symbol table index and relocation type */
+};
+
+struct Elf32_Rela
+{
+ Elf32_Addr r_offset; /* Offset of the relocatable value in the section */
+ Elf32_Word r_info; /* Symbol table index and relocation type */
+ Elf32_Sword r_addend; /* Constant addend used to compute new value */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Relocation Symbol and Type Utility Functions. */
+/*---------------------------------------------------------------------------*/
+static inline uint32_t ELF32_R_SYM(uint32_t i) { return (i >> 8); }
+static inline uint8_t ELF32_R_TYPE(uint32_t i) { return (i & 0xFF); }
+static inline uint32_t ELF32_R_INFO(uint32_t s, uint8_t t)
+ { return ((s << 8) + t); }
+
+
+/*****************************************************************************/
+/* Dynamic Section */
+/* PP. 2-8 */
+/*****************************************************************************/
+struct Elf32_Dyn
+{
+ Elf32_Sword d_tag;
+ union
+ {
+ Elf32_Word d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+};
+
+/* Name Value d_un Executable Shared Obj. */
+/* ---- ----- ---- ---------- ----------- */
+enum
+{
+ DT_NULL = 0, /* ignored mandatory mandatory */
+ DT_NEEDED = 1, /* d_val optional optional */
+ DT_PLTRELSZ = 2, /* d_val optional optional */
+ DT_PLTGOT = 3, /* d_ptr optional optional */
+ DT_HASH = 4, /* d_ptr mandatory mandatory */
+ DT_STRTAB = 5, /* d_ptr mandatory mandatory */
+ DT_SYMTAB = 6, /* d_ptr mandatory mandatory */
+ DT_RELA = 7, /* d_ptr mandatory optional */
+ DT_RELASZ = 8, /* d_val mandatory optional */
+ DT_RELAENT = 9, /* d_val mandatory optional */
+ DT_STRSZ = 10, /* d_val mandatory mandatory */
+ DT_SYMENT = 11, /* d_val mandatory mandatory */
+ DT_INIT = 12, /* d_ptr optional optional */
+ DT_FINI = 13, /* d_ptr optional optional */
+ DT_SONAME = 14, /* d_val ignored optional */
+ DT_RPATH = 15, /* d_val optional ignored */
+ DT_SYMBOLIC = 16, /* ignored ignored optional */
+ DT_REL = 17, /* d_ptr mandatory optional */
+ DT_RELSZ = 18, /* d_val mandatory optional */
+ DT_RELENT = 19, /* d_val mandatory optional */
+ DT_PLTREL = 20, /* d_val optional optional */
+ DT_DEBUG = 21, /* d_ptr optional ignored */
+ DT_TEXTREL = 22, /* ignored optional optional */
+ DT_JMPREL = 23, /* d_ptr optional optional */
+ DT_BIND_NOW = 24, /* ignored optional optional */
+ DT_INIT_ARRAY = 25, /* d_ptr optional optional */
+ DT_FINI_ARRAY = 26, /* d_ptr optional optional */
+ DT_INIT_ARRAYSZ = 27, /* d_val optional optional */
+ DT_FINI_ARRAYSZ = 28, /* d_val optional optional */
+ DT_RUNPATH = 29, /* d_val optional optional */
+ DT_FLAGS = 30, /* d_val optional optional */
+ DT_ENCODING = 32, /* unspecified unspecified unspecified */
+ DT_PREINIT_ARRAY = 32, /* d_ptr optional ignored */
+ DT_PREINIT_ARRAYSZ = 33, /* d_val optional ignored */
+ DT_LOOS = 0x60000000, /* unspecified unspecified unspecified */
+ DT_HIOS = 0x6ffff000, /* unspecified unspecified unspecified */
+ DT_LOPROC = 0x70000000, /* unspecified unspecified unspecified */
+ DT_HIPROC = 0x7fffffff /* unspecified unspecified unspecified */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* DT_FLAGS values. */
+/*---------------------------------------------------------------------------*/
+enum
+{
+ DF_ORIGIN = 0x01, /* loaded object may reference $ORIGIN subst. string */
+ DF_SYMBOLIC = 0x02, /* changes dynamic linker symbol resolution */
+ DF_TEXTREL = 0x04, /* do not allow relocation of non-writable segments */
+ DF_BIND_NOW = 0x08, /* don't use lazy binding */
+ DF_STATIC_TLS = 0x10, /* do not load this file dynamically */
+ DF_DIRECT_DEPENDENT = 0x20, /* limit global sym lookup to dependent list */
+ DF_WORLD = 0x40 /* Linux style global sym lookup, breadth-first */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Dynamic Tag Database. */
+/*---------------------------------------------------------------------------*/
+
+/* Specifiers for which d_un union member to use */
+
+enum
+{
+ EDYN_UNTYPE_IGNORED,
+ EDYN_UNTYPE_VAL,
+ EDYN_UNTYPE_PTR,
+ EDYN_UNTYPE_UNSPECIFIED
+};
+
+
+/* Specifiers for executable/shared object file requirements */
+
+enum
+{
+ EDYN_TAGREQ_IGNORED,
+ EDYN_TAGREQ_MANDATORY,
+ EDYN_TAGREQ_OPTIONAL,
+ EDYN_TAGREQ_UNSPECIFIED
+};
+
+
+/* Data structure for one dynamic tag database entry */
+
+struct EDYN_TAG
+{
+ const char* d_tag_name; /* tag name string */
+ Elf32_Sword d_tag_value; /* DT_* tag value */
+ Elf32_Word d_untype; /* which d_un union member to use */
+ Elf32_Word d_exec_req; /* requirement for executable files */
+ Elf32_Word d_shared_req; /* requirement for shared object files */
+};
+
+extern const struct EDYN_TAG EDYN_TAG_DB[];
+
+/*****************************************************************************/
+/* Special Section Database */
+/*****************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Special Section Names */
+/*---------------------------------------------------------------------------*/
+#define ESCN_BSS_name ".bss"
+#define ESCN_COMMENT_name ".comment"
+#define ESCN_DATA1_name ".data1"
+#define ESCN_DATA_name ".data"
+#define ESCN_DEBUG_name ".debug"
+#define ESCN_DYNAMIC_name ".dynamic"
+#define ESCN_DYNSTR_name ".dynstr"
+#define ESCN_DYNSYM_name ".dynsym"
+#define ESCN_FINI_ARRAY_name ".fini_array"
+#define ESCN_FINI_name ".fini"
+#define ESCN_GOT_name ".got"
+#define ESCN_HASH_name ".hash"
+#define ESCN_INIT_ARRAY_name ".init_array"
+#define ESCN_INIT_name ".init"
+#define ESCN_INTERP_name ".interp"
+#define ESCN_LINE_name ".line"
+#define ESCN_NOTE_name ".note"
+#define ESCN_PLT_name ".plt"
+#define ESCN_PREINIT_ARRAY_name ".preinit_array"
+#define ESCN_RELA_name ".rela"
+#define ESCN_REL_name ".rel"
+#define ESCN_RODATA1_name ".rodata1"
+#define ESCN_RODATA_name ".rodata"
+#define ESCN_SHSTRTAB_name ".shstrtab"
+#define ESCN_STRTAB_name ".strtab"
+#define ESCN_SYMTAB_SHNDX_name ".symtab_shndx"
+#define ESCN_SYMTAB_name ".symtab"
+#define ESCN_TBSS_name ".tbss"
+#define ESCN_TDATA1_name ".tdata1"
+#define ESCN_TDATA_name ".tdata"
+#define ESCN_TEXT_name ".text"
+#define ESCN_ATTRIBUTES_name "__TI_build_attributes"
+#define ESCN_ICODE_name "__TI_ICODE"
+#define ESCN_XREF_name "__TI_XREF"
+
+/*---------------------------------------------------------------------------*/
+/* Special Section Information Data Structure. */
+/*---------------------------------------------------------------------------*/
+struct ESCN
+{
+ const char *name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_entsize;
+ Elf32_Word sh_flags;
+};
+
+extern const struct ESCN ESCN_DB[];
+
+#endif /* ELF32_H */
diff --git a/src/interp/elf/elfwrap.c b/src/interp/elf/elfwrap.c
--- /dev/null
+++ b/src/interp/elf/elfwrap.c
@@ -0,0 +1,30 @@
+/**
+ * @file elfwrap.c
+ *
+ * @brief
+ * IBL wrapper for the elf loader
+ */
+
+#include "types.h"
+#include "ibl.h"
+#include "iblloc.h"
+#include "ewrap.h"
+#include "dload_api.h"
+#include "ibl_elf.h"
+#include "file_ovr.h"
+
+BOOL DLL_debug = FALSE;
+
+/**
+ * @brief
+ * Load an elf file
+ */
+void iblBootElf (BOOT_MODULE_FXN_TABLE *bootFxn, Uint32 *ientry_point)
+{
+ int argc;
+ char **argv;
+
+ DLOAD_load (bootFxn, argc, argv, ientry_point);
+
+}
+
diff --git a/src/interp/elf/ewrap.h b/src/interp/elf/ewrap.h
--- /dev/null
+++ b/src/interp/elf/ewrap.h
@@ -0,0 +1,25 @@
+#ifndef _EWRAP_H
+#define _EWRAP_H
+/**
+ * @file ewrap.h
+ *
+ * @brief
+ * Defines the wrapper used to attach the elf loader to the IBL
+ */
+
+#include "iblloc.h"
+
+#define LOADER_FILE_DESC BOOT_MODULE_FXN_TABLE
+
+
+#define TYPE_STACK_DEFINITION(x,y)
+#define C60_TARGET 1
+#define DLDBG_add_segment_record(x)
+#define DLTMM_malloc(x,y) (((x)->host_address = (y)->target_address) == 0 ? 1 : 1)
+#define DLTMM_free(x)
+#define dload_dynamic_segment(x,y) TRUE
+#define DLSYM_copy_globals(x)
+
+extern BOOL DLL_debug;
+
+#endif /* _EWRAP_H */
diff --git a/src/interp/elf/file_ovr.h b/src/interp/elf/file_ovr.h
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _FILE_OVR_H
+#define _FILE_OVR_H
+/**
+ * @file file_ovr.h
+ *
+ * @brief
+ * Overrides the standard file operations (fseek, fread, ftell, fclose).
+ * This file must be included after the standard elf includes
+ */
+#include <limits.h>
+
+
+/* Redirect seek and reads */
+#define fseek(x,y,z) (*x->seek)((Int32)(y),(Int32)(z))
+#define fread(w,x,y,z) (((*z->read)((Uint8 *)(w),(Uint32)((x)*(y)))) == 0 ? (y) : 0)
+#define ftell(x) UINT_MAX
+#define fclose(x) 0
+
+
+#define FILE BOOT_MODULE_FXN_TABLE
+
+#endif /* _FILE_OVR_H */
diff --git a/src/interp/elf/ibl_elf.h b/src/interp/elf/ibl_elf.h
--- /dev/null
+++ b/src/interp/elf/ibl_elf.h
@@ -0,0 +1,23 @@
+#ifndef _IBL_ELF_H
+#define _IBL_ELF_H
+/**
+ * @file ibl_elf.h
+ *
+ * @brief
+ * Defines the API to the ibl elf loader
+ */
+#include "types.h"
+#include "ibl.h"
+#include "iblloc.h"
+
+
+void iblBootElf (BOOT_MODULE_FXN_TABLE *bootFxn, Uint32 *ientry_point);
+
+
+#endif /* _IBL_ELF_H */
+
+
+
+
+
+
diff --git a/src/interp/elf/util.h b/src/interp/elf/util.h
--- /dev/null
+++ b/src/interp/elf/util.h
@@ -0,0 +1,91 @@
+/*
+* util.h
+*
+* Definition of some useful string comparison routines (not
+* not provided on all platforms) and a few generic macros.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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.
+*
+*/
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <ctype.h>
+
+#if !defined(__linux)
+
+/*****************************************************************************/
+/* STRCASECMP() - Case-insensitive strcmp. */
+/*****************************************************************************/
+static int strcasecmp(const char* s1, const char* s2)
+{
+ char c1, c2;
+ do { c1 = *s1++; c2 = *s2++; }
+ while (c1 && c2 && (tolower(c1) == tolower(c2)));
+
+ return tolower(c1) - tolower(c2);
+}
+
+/*****************************************************************************/
+/* STRNCASECMP() - Case-insensitive strncmp. */
+/*****************************************************************************/
+static int strncasecmp(const char* s1, const char* s2, size_t n)
+{
+ char c1, c2;
+
+ if (!n) return 0;
+
+ do { c1 = *s1++; c2 = *s2++; }
+ while (--n && c1 && c2 && (tolower(c1) == tolower(c2)));
+
+ return tolower(c1) - tolower(c2);
+}
+
+#endif
+
+/*****************************************************************************/
+/* Define MIN and MAX macros. */
+/*****************************************************************************/
+#define MIN(x,y) (((x) > (y)) ? (y) : (x))
+#define MAX(x,y) (((x) >= (y)) ? (x) : (y))
+
+/*****************************************************************************/
+/* C implementation of 'bool' type. */
+/*****************************************************************************/
+#if 0
+typedef int BOOL;
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#endif
diff --git a/src/interp/elf/version.h b/src/interp/elf/version.h
--- /dev/null
+++ b/src/interp/elf/version.h
@@ -0,0 +1,63 @@
+/*
+* version.h
+*
+* Dynamic Loader source version identifictaion.
+*
+* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 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.
+*
+* Neither the name of Texas Instruments Incorporated 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.
+*
+*/
+
+#ifndef _VERSION_H_
+#define _VERSION_H_
+
+/*****************************************************************************/
+/* VERSION NUMBER COMPONENTS - ALWAYS INCREASING!! */
+/* Initial version ID is 1.0.0. Successive version ID's will be incremented */
+/* by automated processes during release port. */
+/*****************************************************************************/
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 0
+#define VERSION_PATCH 0
+
+/******************************************************************************/
+/* Macros used to convert version macros into strings. */
+/******************************************************************************/
+#define MKCSTR(_str) #_str
+#define MKMSTR(_str) MKCSTR(_str)
+
+/******************************************************************************/
+/* VERSION string construction macros. */
+/******************************************************************************/
+#define VERSTR MKMSTR(VERSION_MAJOR) "." MKMSTR(VERSION_MINOR) "." MKMSTR(VERSION_PATCH)
+#define VERSION "Texas Instruments Dynamic Loader API/Core v"VERSTR
+
+#endif