Added elf interpreter
authorunknown <a0216664@.dhcp.itg.ti.com>
Fri, 1 Oct 2010 12:18:01 +0000 (08:18 -0400)
committerunknown <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]
src/interp/elf/ArrayList.h [new file with mode: 0644]
src/interp/elf/dload.c [new file with mode: 0644]
src/interp/elf/dload.h [new file with mode: 0644]
src/interp/elf/dload_api.h [new file with mode: 0644]
src/interp/elf/dload_endian.c [new file with mode: 0644]
src/interp/elf/dload_endian.h [new file with mode: 0644]
src/interp/elf/dlw_client.c [new file with mode: 0644]
src/interp/elf/elf32.h [new file with mode: 0644]
src/interp/elf/elfwrap.c [new file with mode: 0644]
src/interp/elf/ewrap.h [new file with mode: 0644]
src/interp/elf/file_ovr.h [new file with mode: 0644]
src/interp/elf/ibl_elf.h [new file with mode: 0644]
src/interp/elf/util.h [new file with mode: 0644]
src/interp/elf/version.h [new file with mode: 0644]

diff --git a/src/interp/elf/ArrayList.c b/src/interp/elf/ArrayList.c
new file mode 100644 (file)
index 0000000..f602563
--- /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
new file mode 100644 (file)
index 0000000..f912df4
--- /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
new file mode 100644 (file)
index 0000000..cf7ddf3
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..646ba4e
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..9d74206
--- /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
new file mode 100644 (file)
index 0000000..cae5efc
--- /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
new file mode 100644 (file)
index 0000000..aa7f45d
--- /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
new file mode 100644 (file)
index 0000000..0d57829
--- /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
new file mode 100644 (file)
index 0000000..7b57a5e
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..d2e8290
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..5ee2651
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..d3e2619
--- /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
new file mode 100644 (file)
index 0000000..5c02c2a
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..6b3ebde
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..b671306
--- /dev/null
@@ -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