45ea19b1e5568483de76e62724c0eafed6a23222
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / procMgr / hlos / knl / loaders / Elf / Qnx / DLOAD / DLOAD / dload.c
1 /*
2 * dload.c
3 *
4 * Core Dynamic Loader Reference Implementation
5 *
6 * This implementation of the core dynamic loader is platform independent,
7 * but it is object file format dependent.  In particular, this
8 * implementation supports ELF object file format.
9 *
10 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
11 *
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the
23 * distribution.
24 *
25 * Neither the name of Texas Instruments Incorporated nor the names of
26 * its contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 */
43 #if defined (__KERNEL__)
44 #include <linux/kernel.h>  // For INT_MAX
45 #define INT16_MAX 0x7fff
46 #define UINT16_MAX (__CONCAT(INT16_MAX, U) * 2U + 1U)
47 #include <linux/types.h>   // For uintNN_t types
48 #include <linux/string.h>  // For strc* fxns.
49 #else
50 #include <limits.h>
51 #include <inttypes.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <time.h>
56 #endif
58 #include "ArrayList.h"
59 #include "Queue.h"
61 #include "symtab.h"
62 #include "dload_endian.h"
63 #include "elf32.h"
64 #include "dload.h"
65 #include "relocate.h"
66 #include "dload_api.h"
68 #ifdef ARM_TARGET
69 #include "arm_dynamic.h"
70 #endif
72 #ifdef C60_TARGET
73 #include "c60_dynamic.h"
74 #endif
76 #undef LOADER_DEBUG
77 #define LOADER_DEBUG 0
78 /*---------------------------------------------------------------------------*/
79 /* Contains objects (type DLIMP_Loaded_Module) that the system has loaded into     */
80 /* target memory.                                                            */
81 /*---------------------------------------------------------------------------*/
82 TYPE_QUEUE_IMPLEMENTATION(DLIMP_Loaded_Module*, loaded_module_ptr)
85 /*---------------------------------------------------------------------------*/
86 /* Dependency Graph Queue - FIFO queue of dynamic modules that are loaded    */
87 /* when client asks to load a dynamic executable or library. Note that       */
88 /* dependents that have already been loaded with another module will not     */
89 /* appear on this queue.                                                     */
90 /*---------------------------------------------------------------------------*/
91 TYPE_STACK_IMPLEMENTATION(DLIMP_Dynamic_Module*, dynamic_module_ptr)
93 /*---------------------------------------------------------------------------*/
94 /* Support for profiling performance of dynamic loader core.                 */
95 /*---------------------------------------------------------------------------*/
96 #if LOADER_DEBUG && LOADER_PROFILE
97 static clock_t cycle0 = 0;
98 static clock_t cycle_end = 0;
99 #define profile_start_clock() (cycle0 = clock())
100 #define profile_stop_clock()  (cycle_end = clock())
101 #define profile_cycle_count() (cycle_end - cycle0)
102 #endif
104 /*---------------------------------------------------------------------------*/
105 /* DLOAD_create()                                                            */
106 /*                                                                           */
107 /*    Create an instance of the dynamic loader core.                         */
108 /*                                                                           */
109 /*    client_handle:  Private client token to be returned during select DLIF */
110 /*                   function calls.                                         */
111 /*                                                                           */
112 /*    returns: an opaque DLOAD core loader handle, identifying this instance.*/
113 /*                                                                           */
114 /*---------------------------------------------------------------------------*/
115 DLOAD_HANDLE  DLOAD_create(void * client_handle)
117     LOADER_OBJECT     * pLoaderObject;
119     pLoaderObject = DLIF_malloc(sizeof(LOADER_OBJECT));
121     /* Fill out the Loader Object: */
122     if (pLoaderObject != NULL) {
123         /*-------------------------------------------------------------------*/
124         /* Set up initial objects_loading queue.                             */
125         /*-------------------------------------------------------------------*/
126         AL_initialize(&(pLoaderObject->DLIMP_module_dependency_list),
127                       sizeof (const char*), 1);
129         /* Initialize Loaded Module Ptr Queue */
130         loaded_module_ptr_initialize_queue(&pLoaderObject->DLIMP_loaded_objects);
132         /* Initialize Dynamic Module Ptr Stack */
133         dynamic_module_ptr_initialize_stack(&pLoaderObject->DLIMP_dependency_stack);
135         pLoaderObject->file_handle = 1;
137         pLoaderObject->DLOAD_TARGET_MACHINE = DLOAD_DEFAULT_TARGET_MACHINE;
139         /* Store client token, so it can be handed back during DLIF calls */
140         pLoaderObject->client_handle = client_handle;
141     }
143     return((DLOAD_HANDLE)pLoaderObject);
146 /*---------------------------------------------------------------------------*/
147 /* DLOAD_destroy()                                                           */
148 /*                                                                           */
149 /*    Remove an instance of the dynamic loader core, and free all resources  */
150 /*    allocated during DLOAD_create().                                       */
151 /*                                                                           */
152 /*    client_handle:  Private client token to be returned during select DLIF */
153 /*                   function calls.                                         */
154 /*    Preconditions: 1) handle must be valid.                                */
155 /*                   2) Loader instance must be in "UNLOADED" state.         */
156 /*                                                                           */
157 /*---------------------------------------------------------------------------*/
158 void  DLOAD_destroy(DLOAD_HANDLE handle)
160     LOADER_OBJECT     * pLoaderObject;
162     pLoaderObject = (LOADER_OBJECT *)handle;
164     AL_destroy(&(pLoaderObject->DLIMP_module_dependency_list));
166     /* Free the instance object */
167     DLIF_free (pLoaderObject);
170 /*****************************************************************************/
171 /* DLIMP_get_first_dyntag()                                                  */
172 /*                                                                           */
173 /*    Return value for first tag entry in the given dynamic table whose      */
174 /*    tag type matches the given key.                                        */
175 /*                                                                           */
176 /*****************************************************************************/
177 uint32_t DLIMP_get_first_dyntag(int tag, struct Elf32_Dyn* dyn_table)
179    /*------------------------------------------------------------------------*/
180    /* Spin through dynamic segment looking for a specific dynamic tag.       */
181    /* Return the value associated with the tag, if the tag is found.         */
182    /*------------------------------------------------------------------------*/
183    struct Elf32_Dyn *dtp = dyn_table;
184    while (dtp->d_tag != DT_NULL)
185    {
186       if (dtp->d_tag == tag) return dtp->d_un.d_val;
187       else dtp++;
188    }
190    /*------------------------------------------------------------------------*/
191    /* Tag wasn't found, return a known bogus value for the tag.              */
192    /*------------------------------------------------------------------------*/
193    return INT_MAX;
196 /*****************************************************************************/
197 /* dload_and_allocate_dependencies()                                         */
198 /*                                                                           */
199 /*    If not already loaded, load each dependent file identified in the      */
200 /*    dynamic segment with a DT_NEEDED tag.  Dependent files are listed in   */
201 /*    order and should be loaded in the same order that they appear in the   */
202 /*    dynamic segment.                                                       */
203 /*                                                                           */
204 /*****************************************************************************/
205 static BOOL dload_and_allocate_dependencies(DLOAD_HANDLE handle,
206                                             DLIMP_Dynamic_Module *dyn_module)
208    /*------------------------------------------------------------------------*/
209    /* Spin through each dynamic tag entry in the dynamic segment.            */
210    /*------------------------------------------------------------------------*/
211    struct Elf32_Dyn* dyn_nugget = dyn_module->dyntab;
212     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
214 #if LOADER_DEBUG
215    if (debugging_on)
216       DLIF_trace("Starting dload_and_allocate_dependencies() for %s ...\n",
217              dyn_module->name);
218 #endif
220    while(dyn_nugget->d_tag != DT_NULL)
221    {
222       /*---------------------------------------------------------------------*/
223       /* For each DT_NEEDED dynamic tag that we find in the dynamic segment, */
224       /* load the dependent file identified by the so_name value attached    */
225       /* to the DT_NEEDED dynamic tag.                                       */
226       /*---------------------------------------------------------------------*/
227       if (dyn_nugget->d_tag == DT_NEEDED)
228       {
229          loaded_module_ptr_Queue_Node* ptr;
231 #if LOADER_DEBUG
232          if (debugging_on)
233             DLIF_trace("Found DT_NEEDED: %s\n",
234                    dyn_module->strtab+dyn_nugget->d_un.d_val);
235 #endif
237          /*------------------------------------------------------------------*/
238          /* Find out if the file named by the DT_NEEDED tag has already      */
239          /* been loaded.  If it has, then we only have to bump the use count */
240          /* of the named dependent file.                                     */
241          /*------------------------------------------------------------------*/
242             for (ptr = pHandle->DLIMP_loaded_objects.front_ptr; ptr != NULL;
243               ptr = ptr->next_ptr)
244          {
245             if (!strcmp(ptr->value->name,
246                                    dyn_module->strtab + dyn_nugget->d_un.d_val))
247             {
248                ptr->value->use_count++;
249                AL_append(&(dyn_module->loaded_module->dependencies),
250                                                 &(ptr->value->file_handle));
251                break;
252             }
253          }
255          /*------------------------------------------------------------------*/
256          /* If the named dependent file has not been loaded, then we ask the */
257          /* client to invoke a load of the dependent file on our behalf.     */
258          /*------------------------------------------------------------------*/
259          if (ptr == NULL)
260          {
261             int32_t dependent_handle = DLIF_load_dependent(
262                                                        pHandle->client_handle,
263                                                        dyn_module->strtab +
264                                                        dyn_nugget->d_un.d_val);
265             AL_append(&(dyn_module->loaded_module->dependencies),
266                                                         &dependent_handle);
267             if (dependent_handle == 0) return FALSE;
268          }
269       }
271       dyn_nugget++;
272    }
274 #if LOADER_DEBUG
275    if (debugging_on)
276       DLIF_trace("Finished dload_and_allocate_dependencies() for %s\n",
277              dyn_module->name);
278 #endif
280    return TRUE;
283 /*****************************************************************************/
284 /* load_object()                                                             */
285 /*                                                                           */
286 /*    Finish the process of loading an object file.                          */
287 /*                                                                           */
288 /*****************************************************************************/
289 static int load_object(LOADER_FILE_DESC *fd, DLIMP_Dynamic_Module *dyn_module)
291    /*------------------------------------------------------------------------*/
292    /* With the dynamic loader already running on the target, we are able to  */
293    /* relocate directly into target memory, so there is nothing more to be   */
294    /* done (at least in the bare-metal dynamic linking ABI model).           */
295    /*------------------------------------------------------------------------*/
296    return 1;
299 /*****************************************************************************/
300 /* initialize_loaded_module()                                                */
301 /*                                                                           */
302 /*    Initialize DLIMP_Loaded_Module internal data object associated with a  */
303 /*    dynamic module.  This function will also set up a queue of             */
304 /*    DLIMP_Loaded_Segment(s) associated with the loaded module.             */
305 /*    This function is called as we are getting ready to actually load the   */
306 /*    object file contents into target memory.  Each segment will get a      */
307 /*    target memory request that it can use to ask the client for target     */
308 /*    memory space.  This function will also assign a file handle to the     */
309 /*    loaded module.                                                         */
310 /*                                                                           */
311 /*---------------------------------------------------------------------------*/
312 /*                                                                           */
313 /* In applications that use the DSBT model, this function will also need to  */
314 /* negotiate the module's DSBT index with the client.                        */
315 /*                                                                           */
316 /*****************************************************************************/
317 static void initialize_loaded_module(DLOAD_HANDLE handle,
318                                      DLIMP_Dynamic_Module *dyn_module)
320    int i;
321     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
323    /*------------------------------------------------------------------------*/
324    /* Allocate a DLIMP_Loaded_Module data structure for the specified ELF    */
325    /* file and assign a file handle for it (bumping the file handle counter  */
326    /* as we go).                                                             */
327    /*------------------------------------------------------------------------*/
328    DLIMP_Loaded_Module *loaded_module =
329           dyn_module->loaded_module = DLIF_malloc(sizeof(DLIMP_Loaded_Module));
331    if(loaded_module == NULL) {
332 #if LOADER_DEBUG && LOADER_PROFILE
333       if(debugging_on)
334          DLIF_error(DLET_MISC, "Error allocating memory %d...\n",__LINE__);
335 #endif
336       return;
337    }
338 #if LOADER_DEBUG && LOADER_PROFILE
339    /*------------------------------------------------------------------------*/
340    /* Start clock on initialization of loaded module object.                 */
341    /*------------------------------------------------------------------------*/
342    if (debugging_on || profiling_on)
343    {
344       DLIF_trace("Starting initialize_loaded_module() ...\n");
345       if (profiling_on) profile_start_clock();
346    }
347 #endif
349    loaded_module->name = DLIF_malloc(strlen(dyn_module->name) + 1);
350    if (NULL == loaded_module->name) {
351       DLIF_error(DLET_MISC, "Error allocating memory %d...\n",__LINE__);
352       return;
353    }
354    strcpy(loaded_module->name, dyn_module->name);
356     loaded_module->file_handle = pHandle->file_handle++;
357    loaded_module->direct_dependent_only = dyn_module->direct_dependent_only;
358    loaded_module->use_count = 1;
360    /*------------------------------------------------------------------------*/
361    /* In case we wrapped around the file handle, return error.               */
362    /*------------------------------------------------------------------------*/
363     if (pHandle->file_handle == 0)
364       DLIF_error(DLET_MISC, "DLOAD File handle overflowed.\n");
366    /*------------------------------------------------------------------------*/
367    /* Initially the loaded module does not have access to its global         */
368    /* symbols.  These need to be copied from the dynamic module (see call    */
369    /* to DLSYM_copy_globals() below).                                        */
370    /*                                                                        */
371    /* THESE INITIALIZATIONS SHOULD BE MOVED TO AN INIT ROUTINE FOR THE       */
372    /* LOADED MODULE                                                          */
373    /*------------------------------------------------------------------------*/
374    loaded_module->gsymtab = NULL;
375    loaded_module->gstrtab = NULL;
376    loaded_module->gsymnum = loaded_module->gstrsz = 0;
378    /*------------------------------------------------------------------------*/
379    /* Initialize the Array_List of dependencies.                             */
380    /*------------------------------------------------------------------------*/
381    AL_initialize(&(loaded_module->dependencies), sizeof(int), 1);
383    if (dyn_module->symtab)
384       DLSYM_copy_globals(dyn_module);
386    /*------------------------------------------------------------------------*/
387    /* Initialize the module loaded segments Array_List.                      */
388    /*------------------------------------------------------------------------*/
389    AL_initialize(&(loaded_module->loaded_segments),
390                  sizeof(DLIMP_Loaded_Segment), dyn_module->phnum);
392    /*------------------------------------------------------------------------*/
393    /* Spin thru segment headers and process each load segment encountered.   */
394    /*------------------------------------------------------------------------*/
395    for (i = 0; i < dyn_module->phnum; i++)
396       if (dyn_module->phdr[i].p_type == PT_LOAD)
397       {
398          /*------------------------------------------------------------------*/
399          /* Note that this is parallel to and does not supplant the ELF      */
400          /* phdr tables.                                                     */
401          /*------------------------------------------------------------------*/
402          DLIMP_Loaded_Segment seg;
403          seg.obj_desc = DLIF_malloc(sizeof(struct DLOAD_MEMORY_SEGMENT));
404          seg.phdr.p_vaddr = dyn_module->phdr[i].p_vaddr;
405          seg.phdr.p_offset = dyn_module->phdr[i].p_offset;
406          seg.modified = 0;
407          if(seg.obj_desc) {
408             seg.obj_desc->target_page = 0; /*not used*/
409             seg.phdr.p_filesz = seg.obj_desc->objsz_in_bytes
410                           = dyn_module->phdr[i].p_filesz;
411             seg.phdr.p_memsz = seg.obj_desc->memsz_in_bytes
412                          = dyn_module->phdr[i].p_memsz;
413          }
414          seg.phdr.p_align = dyn_module->phdr[i].p_align;
415          seg.phdr.p_flags = dyn_module->phdr[i].p_flags;
416          seg.input_vaddr = 0;
417          seg.phdr.p_paddr = 0;
418          seg.phdr.p_type = PT_LOAD;
419          seg.reloc_offset = 0;
420          AL_append(&(loaded_module->loaded_segments), &seg);
421       }
423    /*------------------------------------------------------------------------*/
424    /* Initialize the module sections Array_List.                             */
425    /*------------------------------------------------------------------------*/
426    AL_initialize(&(loaded_module->sections),
427                  sizeof(DLIMP_Section_Info), dyn_module->shnum);
429    /*------------------------------------------------------------------------*/
430    /* Spin thru section headers and process each section encountered.   */
431    /*------------------------------------------------------------------------*/
432    for (i = 0; i < dyn_module->shnum; i++) {
433          /*------------------------------------------------------------------*/
434          /* Note that this is parallel to and does not supplant the ELF      */
435          /* shdr tables.                                                     */
436          /*------------------------------------------------------------------*/
437          DLIMP_Section_Info sect;
438          sect.shdr.sh_name = dyn_module->shdr[i].sh_name;
439          sect.sh_name = (char *)(sect.shdr.sh_name + (Elf32_Word) dyn_module->shstrtab);
440          sect.shdr.sh_type = dyn_module->shdr[i].sh_type;
441          sect.shdr.sh_flags = dyn_module->shdr[i].sh_flags;
442          sect.shdr.sh_addr = dyn_module->shdr[i].sh_addr;
443          sect.shdr.sh_offset = dyn_module->shdr[i].sh_offset;
444          sect.shdr.sh_size = dyn_module->shdr[i].sh_size;
445          sect.shdr.sh_link = dyn_module->shdr[i].sh_link;
446          sect.shdr.sh_info = dyn_module->shdr[i].sh_info;
447          sect.shdr.sh_addralign = dyn_module->shdr[i].sh_addralign;
448          sect.shdr.sh_entsize = dyn_module->shdr[i].sh_entsize;
449 #if LOADER_DEBUG
450          if (debugging_on) {
451             DLIF_trace("Found section name %s @ addr 0x%08x\n", sect.sh_name ? : "(no name)", sect.shdr.sh_addr);
452          }
453 #endif
454          AL_append(&(loaded_module->sections), &sect);
455    }
457    /*------------------------------------------------------------------------*/
458    /* Initialize the DSO termination information for this module.            */
459    /* It will be copied over from the enclosing dyn_module object when       */
460    /* placement is completed and dyn_module's local copy of the dynamic      */
461    /* table is updated.                                                      */
462    /*------------------------------------------------------------------------*/
463    loaded_module->fini_array = (Elf32_Addr)NULL;
464    loaded_module->fini_arraysz = 0;
465    loaded_module->fini = (Elf32_Addr) NULL;
467 #if LOADER_DEBUG && LOADER_PROFILE
468    if (debugging_on || profiling_on)
469    {
470       DLIF_trace("Finished initialize_loaded_module()\n");
471       if (profiling_on)
472       {
473          profile_stop_clock();
474          DLIF_trace("Took %d cycles.\n", (int32_t)profile_cycle_count());
475       }
476    }
477 #endif
481 /*****************************************************************************/
482 /* load_static_segment()                                                     */
483 /*                                                                           */
484 /*    The core dynamic loader requires that a statically linked executable   */
485 /*    be placed in target memory at the location that was determined during  */
486 /*    the static link that created the executable.  Failure to get the       */
487 /*    required target memory where the static executable is to be loaded     */
488 /*    will cause the dynamic loader to emit an error and abort the load.     */
489 /*                                                                           */
490 /*****************************************************************************/
491 static BOOL load_static_segment(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd,
492                                 DLIMP_Dynamic_Module *dyn_module)
494    int i;
495    DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
496                               (dyn_module->loaded_module->loaded_segments.buf);
497     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
499 #if LOADER_DEBUG
500     if (debugging_on) {
501         DLIF_trace("dynmodule is 0x%x\n",(UInt32) dyn_module);
502         DLIF_trace("loaded_module is 0x%x\n",(UInt32)dyn_module->loaded_module);
503         DLIF_trace("loaded_segments is 0x%x\n",
504                    (UInt32)&dyn_module->loaded_module->loaded_segments);
505         DLIF_trace("seg is 0x%x\n",
506                    (UInt32)dyn_module->loaded_module->loaded_segments.buf);
507     }
508 #endif
509    /*------------------------------------------------------------------------*/
510    /* For each segment in the loaded module, build up a target memory        */
511    /* request for the segment, get rights to target memory where we want     */
512    /* to load the segment from the client, then get the client to write the  */
513    /* segment contents out to target memory to the appropriate address.      */
514    /*------------------------------------------------------------------------*/
515    for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
516    {
517       struct DLOAD_MEMORY_REQUEST targ_req;
518       seg[i].obj_desc->target_page = 0;
519       targ_req.flags = 0;
521       /*---------------------------------------------------------------------*/
522       /* This is a static executable.  DLIF_allocate should give us the      */
523       /* address we ask for or fail.                                         */
524       /*---------------------------------------------------------------------*/
525       if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
527       targ_req.align = seg[i].phdr.p_align;
528       seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
529       targ_req.flags &= ~DLOAD_SF_relocatable;
530       targ_req.fp = fd;
531       targ_req.segment = seg[i].obj_desc;
532       targ_req.offset = seg[i].phdr.p_offset;
533       targ_req.flip_endian = dyn_module->wrong_endian;
534 #if LOADER_DEBUG
535         if (debugging_on) {
536             DLIF_trace("============================================\n");
537             DLIF_trace("targ_req.align %d\n", targ_req.align);
538             DLIF_trace("targ_req.segment 0x%x\n", (UInt32) targ_req.segment);
539             DLIF_trace("targ_req.offset 0x%x\n", targ_req.offset);
540             DLIF_trace("targ_req.flags 0x%x\n", targ_req.flags);
541         }
542 #endif
543       /*---------------------------------------------------------------------*/
544       /* Ask the client side of the dynamic loader to allocate target memory */
545       /* for this segment to be loaded into.                                 */
546       /*---------------------------------------------------------------------*/
547       if (!DLIF_allocate(pHandle->client_handle, &targ_req)) return FALSE;
549       /*---------------------------------------------------------------------*/
550       /* If there is any initialized data in the segment, we'll first write  */
551       /* it into a host writable buffer (DLIF_copy()) and then flush it to   */
552       /* target memory.                                                      */
553       /*---------------------------------------------------------------------*/
554       if (seg[i].phdr.p_filesz)
555       {
556          DLIF_copy(pHandle->client_handle, &targ_req);
557          DLIF_write(pHandle->client_handle, &targ_req);
558       }
559    }
561    return TRUE;
564 /*****************************************************************************/
565 /* relocate_target_dynamic_tag_info()                                        */
566 /*                                                                           */
567 /*    Update a target specific dynamic tag value that happens to be a        */
568 /*    virtual address of a section. Returns TRUE if the tag was updated or   */
569 /*    is not a virtual address and FALSE if it was not successfully updated  */
570 /*    or was not recognized.                                                 */
571 /*****************************************************************************/
572 static BOOL relocate_target_dynamic_tag_info(DLIMP_Dynamic_Module *dyn_module,
573                                              int i)
575 #ifdef ARM_TARGET
576    if (is_arm_module(&dyn_module->fhdr))
577        return DLDYN_arm_relocate_dynamic_tag_info(dyn_module, i);
578 #endif
580 #ifdef C60_TARGET
581    if (is_c60_module(&dyn_module->fhdr))
582       return DLDYN_c60_relocate_dynamic_tag_info(dyn_module, i);
583 #endif
585    return FALSE;
588 /*****************************************************************************/
589 /* DLIMP_update_dyntag_section_address()                                     */
590 /*                                                                           */
591 /*    Given the index of a dynamic tag which we happen to know points to a   */
592 /*    section address, find the program header table entry associated with   */
593 /*    the specified address and update the tag value with the real address   */
594 /*    of the section.                                                        */
595 /*                                                                           */
596 /*****************************************************************************/
597 BOOL DLIMP_update_dyntag_section_address(DLIMP_Dynamic_Module *dyn_module,
598                                          int32_t i)
600    int j;
601    DLIMP_Loaded_Segment *seg = (DLIMP_Loaded_Segment *)
602                               (dyn_module->loaded_module->loaded_segments.buf);
603    for (j = 0; j < dyn_module->loaded_module->loaded_segments.size; j++)
604    {
605       if ((dyn_module->dyntab[i].d_un.d_ptr >= seg[j].input_vaddr) &&
606           (dyn_module->dyntab[i].d_un.d_ptr <
607        (seg[j].input_vaddr + seg[j].phdr.p_memsz)))
608       {
609          dyn_module->dyntab[i].d_un.d_ptr +=
610                                     (seg[j].phdr.p_vaddr - seg[j].input_vaddr);
611          return TRUE;
612       }
613    }
615    return FALSE;
618 /*****************************************************************************/
619 /* relocate_dynamic_tag_info()                                               */
620 /*                                                                           */
621 /*    Once segment allocation has been completed, we'll need to go through   */
622 /*    the dynamic table and update any tag values that happen to be virtual  */
623 /*    addresses of segments (DT_C6000_DSBT_BASE, for example).               */
624 /*                                                                           */
625 /*****************************************************************************/
626 static BOOL relocate_dynamic_tag_info(LOADER_FILE_DESC *fd,
627                                       DLIMP_Dynamic_Module *dyn_module)
629    /*------------------------------------------------------------------------*/
630    /* Spin through dynamic table loking for tags that have a value which is  */
631    /* the virtual address of a section. After the sections are allocated,    */
632    /* we'll need to update these values with the new address of the section. */
633    /*------------------------------------------------------------------------*/
634    int i;
635    for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
636    {
637       switch (dyn_module->dyntab[i].d_tag)
638       {
639          /*------------------------------------------------------------------*/
640      /* Only tag values that are virtual addresses will be affected.     */
641          /*------------------------------------------------------------------*/
642          case DT_NEEDED:
643          case DT_PLTRELSZ:
644          case DT_HASH:
645          case DT_STRTAB:
646          case DT_SYMTAB:
647          case DT_RELA:
648          case DT_RELASZ:
649          case DT_RELAENT:
650          case DT_STRSZ:
651          case DT_SYMENT:
652          case DT_SONAME:
653          case DT_RPATH:
654          case DT_SYMBOLIC:
655          case DT_REL:
656          case DT_RELSZ:
657          case DT_RELENT:
658          case DT_PLTREL:
659          case DT_DEBUG:
660          case DT_TEXTREL:
661          case DT_BIND_NOW:
662          case DT_INIT_ARRAYSZ:
663          case DT_RUNPATH:
664          case DT_FLAGS:
665          case DT_PREINIT_ARRAYSZ:
666             continue;
668          /*------------------------------------------------------------------*/
669      /* NOTE!!!                                                          */
670          /* case DT_ENCODING:  -- tag type has same "id" as DT_PREINIT_ARRAY */
671          /*------------------------------------------------------------------*/
673          /*------------------------------------------------------------------*/
674          /* This is a generic dynamic tag whose value is a virtual address   */
675          /* of a section. It needs to be relocated to the section's actual   */
676          /* address in target memory.                                        */
677          /*------------------------------------------------------------------*/
678          case DT_PREINIT_ARRAY:
679          case DT_INIT:
680          case DT_INIT_ARRAY:
681         if (!DLIMP_update_dyntag_section_address(dyn_module, i))
682            return FALSE;
684             continue;
686          /*------------------------------------------------------------------*/
687      /* Once we have resolved the actual address of termination function */
688      /* sections, we need to copy their addresses over to the loaded     */
689      /* module object (dyn_module will be deleted before we get to       */
690      /* unloading the module).                                           */
691          /*------------------------------------------------------------------*/
692          case DT_FINI_ARRAY:
693          case DT_FINI:
694         if (!DLIMP_update_dyntag_section_address(dyn_module, i))
695            return FALSE;
697         if (dyn_module->dyntab[i].d_tag == DT_FINI)
698            dyn_module->loaded_module->fini =
699                                           dyn_module->dyntab[i].d_un.d_ptr;
700         else
701            dyn_module->loaded_module->fini_array =
702                                           dyn_module->dyntab[i].d_un.d_ptr;
704             continue;
706          case DT_FINI_ARRAYSZ:
707         dyn_module->loaded_module->fini_arraysz =
708                                           dyn_module->dyntab[i].d_un.d_val;
709         continue;
711          /*------------------------------------------------------------------*/
712      /* Is this a virtual address???                                     */
713          /*------------------------------------------------------------------*/
714          case DT_JMPREL: /* is this a virtual address??? */
715             continue;
717          /*------------------------------------------------------------------*/
718          /* The remaining dynamic tag types should be target specific. If    */
719          /* something generic slips through to here, then the handler for    */
720          /* relocating target specific dynamic tags should fail.             */
721          /*------------------------------------------------------------------*/
722          default:
723             if (!relocate_target_dynamic_tag_info(dyn_module, i))
724                return FALSE;
725       }
726    }
728    /*------------------------------------------------------------------------*/
729    /* We've gotten through all of the dynamic table without incident.        */
730    /* All dynamic tag values that were virtual section addresses should have */
731    /* been updated with the final address of the section that they point to. */
732    /*------------------------------------------------------------------------*/
733    return TRUE;
736 /*****************************************************************************/
737 /* allocate_dynamic_segments_and relocate_symbols()                          */
738 /*                                                                           */
739 /*    Allocate target memory for each segment in this module, getting a      */
740 /*    host-accessible space to copy the content of each segment into.  Then  */
741 /*    update the symbol table and program header table to reflect the new    */
742 /*    target address for each segment.  Processing of the dynamic relocation */
743 /*    entries will wait until all dependent files have been loaded and       */
744 /*    allocated into target memory.                                          */
745 /*                                                                           */
746 /*---------------------------------------------------------------------------*/
747 /*                                                                           */
748 /* The relocation entries in the ELF file do not handle the necessary        */
749 /* adjustments to the memory addresses in the program header or symbol       */
750 /* tables.  These must be done manually.                                     */
751 /*                                                                           */
752 /* This is harder for us than for most dynamic loaders, because we have to   */
753 /* work in environments without virtual memory and thus where the offsets    */
754 /* between segments in memory may be different than they were in the file.   */
755 /* So, even though a dynamic loader usually only has to adjust all the       */
756 /* segments by a single fixed offset, we need to offset the symbols and      */
757 /* program header addresses segment by segment.  This job is done by the     */
758 /* function below.                                                           */
759 /*                                                                           */
760 /*****************************************************************************/
761 static BOOL allocate_dynamic_segments_and_relocate_symbols
762                                              (DLOAD_HANDLE handle,
763                                               LOADER_FILE_DESC *fd,
764                                               DLIMP_Dynamic_Module *dyn_module)
766    int i,j;
767    DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
768                              (dyn_module->loaded_module->loaded_segments.buf);
769    struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
770     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
772 #if LOADER_DEBUG && LOADER_PROFILE
773    if (debugging_on || profiling_on)
774    {
775       DLIF_trace("Dynamic executable found.\n"
776              "Starting allocate_dynamic_segments_and_relocate_symbols() ...\n");
777       if (profiling_on) profile_start_clock();
778    }
779 #endif
781    /*------------------------------------------------------------------------*/
782    /* Spin through the list of loaded segments from the current module.      */
783    /*------------------------------------------------------------------------*/
784    for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
785    {
786       /*--------------------------------------------------------------------*/
787       /* Allocate target memory for segment via client-provided target      */
788       /* memory API.                                                        */
789       /*--------------------------------------------------------------------*/
790       int32_t addr_offset;
791       struct DLOAD_MEMORY_REQUEST targ_req;
792       seg[i].obj_desc->target_page = 0;
793       targ_req.flags = 0;
794       if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
795       targ_req.align = 0x20;
796       seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
797       targ_req.flags |= DLOAD_SF_relocatable;
798       targ_req.fp = fd;
799       targ_req.segment = seg[i].obj_desc;
800       targ_req.offset = seg[i].phdr.p_offset;
801       targ_req.flip_endian = dyn_module->wrong_endian;
803 #if LOADER_DEBUG
804         if (debugging_on)
805             DLIF_trace("Segment %d flags 0x%x\n", i, targ_req.flags);
806 #endif
807       if (!DLIF_allocate(pHandle->client_handle, &targ_req))
808       {
809          DLIF_error(DLET_MEMORY, "DLIF allocation failure.\n");
810          return FALSE;
811       }
813       /*--------------------------------------------------------------------*/
814       /* Calculate the offset we need to adjust segment header and symbol   */
815       /* table addresses.                                                   */
816       /*--------------------------------------------------------------------*/
817       addr_offset = (int32_t)(seg[i].obj_desc->target_address) -
818                                                (int32_t)(seg[i].phdr.p_vaddr);
820 #if LOADER_DEBUG
821       if (debugging_on)
822       {
823          DLIF_trace("Segment %d (at 0x%x, 0x%x bytes) relocated to 0x%x\n", i,
824                 (int32_t)(seg[i].phdr.p_vaddr),
825                 (int32_t)(seg[i].phdr.p_memsz),
826                 (int32_t)(seg[i].obj_desc->target_address));
827          DLIF_trace( "Addr Offset is 0x%x\n", addr_offset);
828       }
829 #endif
831       /*--------------------------------------------------------------------*/
832       /* Update program entry point if needed.  Need to replace to deal     */
833       /* with full ELF initialization routine.                              */
834       /*--------------------------------------------------------------------*/
835       if (dyn_module->relocate_entry_point &&
836           fhdr->e_entry >= (Elf32_Addr)(seg[i].phdr.p_vaddr) &&
837           fhdr->e_entry < (Elf32_Addr)((uint8_t*)(seg[i].phdr.p_vaddr) +
838                                        (uint32_t)(seg[i].phdr.p_memsz)))
839       {
840 #if LOADER_DEBUG
841          if (debugging_on)
842          {
843             DLIF_trace("Entry point 0x%x relocated to 0x%x\n",
844                    fhdr->e_entry, fhdr->e_entry + addr_offset);
845          }
846 #endif
847          fhdr->e_entry += addr_offset;
849          /*------------------------------------------------------------------*/
850          /* Mark the entry point as being relocated so we will not do it     */
851          /* again.                                                           */
852          /*------------------------------------------------------------------*/
853          dyn_module->relocate_entry_point = FALSE;
854       }
856       /*---------------------------------------------------------------------*/
857       /* Fix program header entries in segment and Elf32_Phdr structs.       */
858       /*---------------------------------------------------------------------*/
859       for (j = 0; j < fhdr->e_phnum; j++)
860          if (dyn_module->phdr[j].p_vaddr == (Elf32_Addr)seg[i].phdr.p_vaddr)
861          {
862             dyn_module->phdr[j].p_vaddr += addr_offset;
863             dyn_module->phdr[i].p_paddr += addr_offset;
864             break;
865          }
867       seg[i].input_vaddr = (Elf32_Addr)(seg[i].phdr.p_vaddr);
868       seg[i].phdr.p_vaddr += addr_offset;
870       /*---------------------------------------------------------------------*/
871       /* Great, now the hard part: fix offsets in symbols.  It would be nice */
872       /* if there were an easier way to deal with this.                      */
873       /*---------------------------------------------------------------------*/
874       {
875          struct Elf32_Sym *gsymtab =
876                     ((struct Elf32_Sym*)(dyn_module->loaded_module->gsymtab));
877          Elf32_Addr segment_start = (Elf32_Addr)seg[i].phdr.p_vaddr;
878          Elf32_Addr segment_end   = (Elf32_Addr)seg[i].phdr.p_vaddr +
879                                                            seg[i].phdr.p_memsz;
880          Elf32_Word global_index  = dyn_module->symnum -
881                                     dyn_module->loaded_module->gsymnum;
883          for (j = 0; j < dyn_module->symnum; j++)
884          {
885             /*---------------------------------------------------------------*/
886             /* Get the relocated symbol value.                               */
887             /*---------------------------------------------------------------*/
888             Elf32_Addr symval_adj = dyn_module->symtab[j].st_value +
889                                     addr_offset;
891             /*---------------------------------------------------------------*/
892             /* If the symbol is defined in this segment, update the symbol   */
893             /* value and mark the symbol so that we don't relocate it again. */
894             /*---------------------------------------------------------------*/
895             if (symval_adj >= segment_start && symval_adj <  segment_end &&
896                 dyn_module->symtab[j].st_shndx != INT16_MAX)
897             {
898                dyn_module->symtab[j].st_value = symval_adj;
900                /*------------------------------------------------------------*/
901                /* The module symbol table only has the global symbols.       */
902                /*------------------------------------------------------------*/
903                if (j >= global_index)
904                   gsymtab[j-global_index].st_value = symval_adj;
906                /*------------------------------------------------------------*/
907                /* Mark the symbol as relocated.                              */
908                /*------------------------------------------------------------*/
909                dyn_module->symtab[j].st_shndx = INT16_MAX;
910             }
911          }
912       }
913    }
915    /*------------------------------------------------------------------------*/
916    /* Update dynamic tag information. Some dynamic tags have values which    */
917    /* are virtual addresses of sections. These values need to be updated     */
918    /* once segment allocation is completed and the new segment addresses are */
919    /* known.                                                                 */
920    /*------------------------------------------------------------------------*/
921    /* We should only traverse through the dynamic table once because we want */
922    /* to avoid the possibility of updating the same tag multiple times (an   */
923    /* error, if it happens).                                                 */
924    /*------------------------------------------------------------------------*/
925    if (!relocate_dynamic_tag_info(fd, dyn_module))
926    {
927       DLIF_error(DLET_MISC, "Failed dynamic table update.\n");
928       return FALSE;
929    }
931 #if LOADER_DEBUG && LOADER_PROFILE
932    if (debugging_on || profiling_on)
933    {
934       DLIF_trace("allocate_dynamic_segments_and_relocate_symbols() Done\n");
935       if (profiling_on)
936       {
937          profile_stop_clock();
938          DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
939       }
940    }
941 #endif
943    return TRUE;
946 /*****************************************************************************/
947 /* delete_DLIMP_Loaded_Module()                                              */
948 /*                                                                           */
949 /*    Free host memory associated with a DLIMP_Loaded_Module data structure  */
950 /*    and all of the DLIMP_Loaded_Segment objects that are associated with   */
951 /*    it.                                                                    */
952 /*                                                                           */
953 /*****************************************************************************/
954 static void delete_DLIMP_Loaded_Module(DLOAD_HANDLE handle,
955                                        DLIMP_Loaded_Module **pplm)
957     DLIMP_Loaded_Module *loaded_module = *pplm;
958     DLIMP_Loaded_Segment *segments = (DLIMP_Loaded_Segment*)
959                                           (loaded_module->loaded_segments.buf);
960     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
962     /*-----------------------------------------------------------------------*/
963     /* Spin through the segments attached to this loaded module, freeing up  */
964     /* any target memory that was allocated by the client for the segment.   */
965     /*-----------------------------------------------------------------------*/
966     int i;
967     for (i = 0; i < loaded_module->loaded_segments.size; i++)
968     {
969         if (!DLIF_release(pHandle->client_handle, segments[i].obj_desc))
970             DLIF_error(DLET_MISC, "Failed call to DLIF_release!\n");;
971         DLIF_free(segments[i].obj_desc);
972     }
974     /*----------------------------------------------------------------------*/
975     /* Hacky way of indicating that the base image is no longer available.  */
976     /* WHHHHAAAAAAATTT!?!?!?!?!?!                                           */
977     /*----------------------------------------------------------------------*/
978     if (loaded_module->file_handle == DLIMP_application_handle)
979         DLIMP_application_handle = 0;
981     /*-----------------------------------------------------------------------*/
982     /* Free host heap memory that was allocated for the internal loaded      */
983     /* module data structure members.                                        */
984     /*-----------------------------------------------------------------------*/
985     if (loaded_module->name)    DLIF_free(loaded_module->name);
986     if (loaded_module->gsymtab) DLIF_free(loaded_module->gsymtab);
987     loaded_module->gsymnum = 0;
988     if (loaded_module->gstrtab) DLIF_free(loaded_module->gstrtab);
989     loaded_module->gstrsz = 0;
990     AL_destroy(&(loaded_module->sections));
991     AL_destroy(&(loaded_module->loaded_segments));
992     AL_destroy(&(loaded_module->dependencies));
994     /*-----------------------------------------------------------------------*/
995     /* Finally, free the host memory for the loaded module object, then NULL */
996     /* the pointer that was passed in.                                       */
997     /*-----------------------------------------------------------------------*/
998     DLIF_free(loaded_module);
999     *pplm = NULL;
1002 /*****************************************************************************/
1003 /* new_DLIMP_Dynamic_Module()                                                */
1004 /*                                                                           */
1005 /*   Allocate a dynamic module data structure from host memory and           */
1006 /*   initialize its members to their default values.                         */
1007 /*                                                                           */
1008 /*****************************************************************************/
1009 static DLIMP_Dynamic_Module *new_DLIMP_Dynamic_Module(LOADER_FILE_DESC *fd)
1011     /*-----------------------------------------------------------------------*/
1012     /* Allocate space for dynamic module data structure from host memory.    */
1013     /*-----------------------------------------------------------------------*/
1014     DLIMP_Dynamic_Module *dyn_module =
1015              (DLIMP_Dynamic_Module *)DLIF_malloc(sizeof(DLIMP_Dynamic_Module));
1017     if (!dyn_module)
1018         return NULL;
1020     /*-----------------------------------------------------------------------*/
1021     /* Initialize data members of the new dynamic module data structure.     */
1022     /*-----------------------------------------------------------------------*/
1023     dyn_module->name = NULL;
1024     dyn_module->fd = fd;
1025     dyn_module->phdr = NULL;
1026     dyn_module->phnum = 0;
1027     dyn_module->shdr = NULL;
1028     dyn_module->shnum = 0;
1029     dyn_module->strtab = NULL;
1030     dyn_module->strsz = 0;
1031     dyn_module->dyntab = NULL;
1032     dyn_module->symtab = NULL;
1033     dyn_module->symnum = 0;
1034     dyn_module->gsymtab_offset = 0;
1035     dyn_module->gstrtab_offset = 0;
1036     dyn_module->c_args = NULL;
1037     dyn_module->argc = 0;
1038     dyn_module->argv = NULL;
1039     dyn_module->loaded_module = NULL;
1040     dyn_module->wrong_endian = 0;
1041     dyn_module->direct_dependent_only = TRUE;
1042     dyn_module->relocatable = FALSE;
1043     dyn_module->relocate_entry_point = TRUE;
1045     dyn_module->dsbt_size = 0;
1046     dyn_module->dsbt_index = DSBT_INDEX_INVALID;
1047     dyn_module->dsbt_base_tagidx = -1;
1049     dyn_module->preinit_array_idx = -1;
1050     dyn_module->preinit_arraysz = 0;
1051     dyn_module->init_idx = -1;
1052     dyn_module->init_array_idx = -1;
1053     dyn_module->init_arraysz = 0;
1055     return dyn_module;
1058 /*****************************************************************************/
1059 /* detach_loaded_module()                                                    */
1060 /*                                                                           */
1061 /*    Detach loaded module data structure from given dynamic module.  When   */
1062 /*    an object file has been successfully loaded, the loader core will      */
1063 /*    detach the loaded module data structure from the dynamic module data   */
1064 /*    structure because the loaded module must continue to persist until is  */
1065 /*    is actually unloaded from target memory.  If there is a problem with   */
1066 /*    the load, then the host memory associated with the loaded module will  */
1067 /*    be released as part of the destruction of the dynamic module.          */
1068 /*                                                                           */
1069 /*****************************************************************************/
1070 static DLIMP_Loaded_Module *detach_loaded_module(DLIMP_Dynamic_Module *dyn_module)
1072     if (dyn_module && dyn_module->loaded_module)
1073     {
1074         DLIMP_Loaded_Module *loaded_module = dyn_module->loaded_module;
1075         dyn_module->loaded_module = NULL;
1076         return loaded_module;
1077     }
1079     return NULL;
1081 /*****************************************************************************/
1082 /* delete_DLIMP_Dynamic_Module()                                             */
1083 /*                                                                           */
1084 /*    Remove local copies of the string table, symbol table, program header  */
1085 /*    table, and dynamic table.                                              */
1086 /*                                                                           */
1087 /*****************************************************************************/
1088 static void delete_DLIMP_Dynamic_Module(DLOAD_HANDLE handle,
1089                                         DLIMP_Dynamic_Module **ppdm)
1091    DLIMP_Dynamic_Module *dyn_module = NULL;
1093    if (!ppdm || (*ppdm == NULL))
1094    {
1095       DLIF_error(DLET_MISC,
1096                  "Internal Error: invalid argument to dynamic module "
1097          "destructor function; aborting loader\n");
1098 #if !defined (__KERNEL__)
1099       exit(1);
1100 #endif
1101    }
1103    dyn_module = *ppdm;
1104    if (dyn_module->name)     DLIF_free(dyn_module->name);
1105    if (dyn_module->strtab)   DLIF_free(dyn_module->strtab);
1106    if (dyn_module->symtab)   DLIF_free(dyn_module->symtab);
1107    if (dyn_module->phdr)     DLIF_free(dyn_module->phdr);
1108    if (dyn_module->shdr)     DLIF_free(dyn_module->shdr);
1109    if (dyn_module->dyntab)   DLIF_free(dyn_module->dyntab);
1110    if (dyn_module->shstrtab) DLIF_free(dyn_module->shstrtab);
1112    /*------------------------------------------------------------------------*/
1113    /* If we left the loaded module attached to the dynamic module, then      */
1114    /* something must have gone wrong with the load.  Remove the loaded       */
1115    /* module from the queue of loaded modules, if it is there.  Then free    */
1116    /* the host memory allocated to the loaded module and its segments.       */
1117    /*------------------------------------------------------------------------*/
1118    if (dyn_module->loaded_module != NULL)
1119         delete_DLIMP_Loaded_Module(handle, &(dyn_module->loaded_module));
1121    /*------------------------------------------------------------------------*/
1122    /* Finally, free the host memory for this dynamic module object and NULL  */
1123    /* the pointer to the object.                                             */
1124    /*------------------------------------------------------------------------*/
1125    DLIF_free(dyn_module);
1126    *ppdm = NULL;
1129 /*****************************************************************************/
1130 /* file_header_magic_number_is_valid()                                       */
1131 /*                                                                           */
1132 /*    Given an object file header, check the magic number to ensure that it  */
1133 /*    is an object file format that we recognize.  This implementation of    */
1134 /*    the dynamic loader core will handle ELF object file format.            */
1135 /*                                                                           */
1136 /*****************************************************************************/
1137 static BOOL file_header_magic_number_is_valid(struct Elf32_Ehdr* header)
1139    /*------------------------------------------------------------------------*/
1140    /* Check for correct ELF magic numbers in file header.                    */
1141    /*------------------------------------------------------------------------*/
1142    if (!header->e_ident[EI_MAG0] == ELFMAG0 ||
1143        !header->e_ident[EI_MAG1] == ELFMAG1 ||
1144        !header->e_ident[EI_MAG2] == ELFMAG2 ||
1145        !header->e_ident[EI_MAG3] == ELFMAG3)
1146    {
1147       DLIF_error(DLET_FILE, "Invalid ELF magic number.\n");
1148       return FALSE;
1149    }
1151    return TRUE;
1154 /*****************************************************************************/
1155 /* file_header_machine_is_valid()                                            */
1156 /*                                                                           */
1157 /*    Check if the machine specified in the file header is supported by the  */
1158 /*    loader.  If the loader was compiled with support for all targets,      */
1159 /*    the machine will be initially set to EM_NONE.  Once a module has been  */
1160 /*    loaded, all remaining modules must have the same machine value.        */
1161 /*****************************************************************************/
1162 static BOOL file_header_machine_is_valid(DLOAD_HANDLE handle, Elf32_Half e_machine)
1164     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
1166     if (pHandle->DLOAD_TARGET_MACHINE == EM_NONE)
1167         pHandle->DLOAD_TARGET_MACHINE = e_machine;
1169     if (e_machine != pHandle->DLOAD_TARGET_MACHINE)
1170       return FALSE;
1172    return TRUE;
1175 /*****************************************************************************/
1176 /* is_valid_elf_object_file()                                                */
1177 /*                                                                           */
1178 /*    Check file size against anticipated end location of string table,      */
1179 /*    symbol table, program header tables, etc.  If we anything untoward,    */
1180 /*    then we declare that the ELF file is corrupt and the load is aborted.  */
1181 /*                                                                           */
1182 /*****************************************************************************/
1183 static BOOL is_valid_elf_object_file(LOADER_FILE_DESC *fd,
1184                                      DLIMP_Dynamic_Module *dyn_module)
1186    uint32_t fsz;
1187    int i;
1189    /*------------------------------------------------------------------------*/
1190    /* Get file size.                                                         */
1191    /*------------------------------------------------------------------------*/
1192    DLIF_fseek(fd, 0, LOADER_SEEK_END);
1193    fsz = DLIF_ftell(fd);
1195    /*------------------------------------------------------------------------*/
1196    /* Check for invalid table sizes (string table, symbol table, and         */
1197    /* program header tables).                                                */
1198    /*------------------------------------------------------------------------*/
1199    if (!((dyn_module->strsz < fsz) &&
1200          (dyn_module->symnum < fsz) &&
1201          (dyn_module->phnum * sizeof(struct Elf32_Phdr)) < fsz))
1202    {
1203       DLIF_error(DLET_FILE, "Invalid ELF table bounds.\n");
1204       return FALSE;
1205    }
1207    /*------------------------------------------------------------------------*/
1208    /* Check for null so_name string in file with dynamic information.        */
1209    /*------------------------------------------------------------------------*/
1210    if (dyn_module->dyntab && !strcmp(dyn_module->name, ""))
1211    {
1212       DLIF_error(DLET_MISC, "Dynamic file lacks SO_NAME identifier.\n");
1213       return FALSE;
1214    }
1216    /*------------------------------------------------------------------------*/
1217    /* Check for invalid program header information.                          */
1218    /*------------------------------------------------------------------------*/
1219    for (i = 0; i < dyn_module->phnum; i++)
1220    {
1221       struct Elf32_Phdr* phdr = dyn_module->phdr + i;
1223       /*---------------------------------------------------------------------*/
1224       /* Sanity check for relative sizes of filesz and memsz.                */
1225       /*---------------------------------------------------------------------*/
1226       if (!(phdr->p_type != PT_LOAD || phdr->p_filesz <= phdr->p_memsz))
1227       {
1228          DLIF_error(DLET_MISC,
1229                     "Invalid file or memory size for segment %d.\n", i);
1230          return FALSE;
1231       }
1233       /*---------------------------------------------------------------------*/
1234       /* Check that segment file offset doesn't go off the end of the file.  */
1235       /*---------------------------------------------------------------------*/
1236       if (!(phdr->p_offset + phdr->p_filesz < fsz))
1237       {
1238          DLIF_error(DLET_FILE,
1239                   "File location of segment %d is past the end of file.\n", i);
1240          return FALSE;
1241       }
1242    }
1244    /*------------------------------------------------------------------------*/
1245    /* Check that a ET_DYN-type file is relocatable.                          */
1246    /*------------------------------------------------------------------------*/
1247    if (dyn_module->fhdr.e_type == ET_DYN && !dyn_module->symtab) return FALSE;
1249    /*------------------------------------------------------------------------*/
1250    /* All checks passed.                                                     */
1251    /*------------------------------------------------------------------------*/
1252    return TRUE;
1255 /*****************************************************************************/
1256 /* process_eiosabi()                                                         */
1257 /*                                                                           */
1258 /*   Check the EI_OSABI field to validate it and set any parameters based on */
1259 /*   it.                                                                     */
1260 /*****************************************************************************/
1261 static BOOL process_eiosabi(DLIMP_Dynamic_Module* dyn_module)
1263 #ifdef ARM_TARGET
1264    if (is_arm_module(&dyn_module->fhdr))
1265       return DLDYN_arm_process_eiosabi(dyn_module);
1266 #endif
1268 #ifdef C60_TARGET
1269    if (is_c60_module(&dyn_module->fhdr))
1270       return DLDYN_c60_process_eiosabi(dyn_module);
1271 #endif
1273    return FALSE;
1275 /*****************************************************************************/
1276 /* dload_file_header()                                                       */
1277 /*                                                                           */
1278 /*    Read ELF file header.  Store critical information in the provided      */
1279 /*    DLIMP_Dynamic_Module record.  Check file header for validity.          */
1280 /*                                                                           */
1281 /*****************************************************************************/
1282 static BOOL dload_file_header(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd,
1283                               DLIMP_Dynamic_Module *dyn_module)
1285    /*------------------------------------------------------------------------*/
1286    /* Read ELF file header from given input file.                            */
1287    /*------------------------------------------------------------------------*/
1288    DLIF_fread(&(dyn_module->fhdr), sizeof(struct Elf32_Ehdr), 1, fd);
1290    /*------------------------------------------------------------------------*/
1291    /* Determine target vs. host endian-ness.  Does header data need to be    */
1292    /* byte swapped?                                                          */
1293    /*------------------------------------------------------------------------*/
1294    dyn_module->wrong_endian =
1295                      (dyn_module->fhdr.e_ident[EI_DATA] != DLIMP_get_endian());
1297    /*------------------------------------------------------------------------*/
1298    /* Swap file header structures, if needed.                                */
1299    /*------------------------------------------------------------------------*/
1300    if (dyn_module->wrong_endian)
1301       DLIMP_change_ehdr_endian(&(dyn_module->fhdr));
1303 #if LOADER_DEBUG
1304    if (debugging_on) {
1305       /*---------------------------------------------------------------------*/
1306       /* Write out magic ELF information for debug purposes.                 */
1307       /*---------------------------------------------------------------------*/
1308       DLIF_trace("ELF: %c%c%c\n", dyn_module->fhdr.e_ident[1],
1309                               dyn_module->fhdr.e_ident[2],
1310                               dyn_module->fhdr.e_ident[3]);
1311       DLIF_trace("ELF file header entry point: %x\n",
1312                  dyn_module->fhdr.e_entry);
1313    }
1314 #endif
1316    /*------------------------------------------------------------------------*/
1317    /* Verify magic numbers in ELF file header.                               */
1318    /*------------------------------------------------------------------------*/
1319    if (!file_header_magic_number_is_valid(&(dyn_module->fhdr)))
1320    {
1321       DLIF_error(DLET_FILE, "Invalid ELF file header magic number.\n");
1322       return FALSE;
1323    }
1325    if (!file_header_machine_is_valid(handle, dyn_module->fhdr.e_machine))
1326    {
1327        DLIF_error(DLET_FILE, "Invalid ELF file target machine.\n");
1328        return FALSE;
1329    }
1331    /*------------------------------------------------------------------------*/
1332    /* Verify file is an executable or dynamic shared object or library.      */
1333    /*------------------------------------------------------------------------*/
1334    if ((dyn_module->fhdr.e_type != ET_EXEC) &&
1335        (dyn_module->fhdr.e_type != ET_DYN))
1336    {
1337       DLIF_error(DLET_FILE, "Invalid ELF file type.\n");
1338       return FALSE;
1339    }
1341 #if LOADER_DEBUG && LOADER_PROFILE
1342    /*------------------------------------------------------------------------*/
1343    /* Stop profiling clock when file header information has finished         */
1344    /* loading.  Re-start clock on initialization of symbol table, and        */
1345    /* dynamic table pointers.                                                */
1346    /*------------------------------------------------------------------------*/
1347    if (debugging_on || profiling_on)
1348    {
1349       DLIF_trace("done.\n");
1350       if (profiling_on)
1351       {
1352          profile_stop_clock();
1353          DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
1354          profile_start_clock();
1355       }
1356    }
1357 #endif
1359    return TRUE;
1362 /*****************************************************************************/
1363 /* dload_program_header_table()                                              */
1364 /*                                                                           */
1365 /*    Make a local copy of the ELF object file's program header table in the */
1366 /*    dynamic module data structure.                                         */
1367 /*                                                                           */
1368 /*****************************************************************************/
1369 static void dload_program_header_table(LOADER_FILE_DESC *fd,
1370                                        DLIMP_Dynamic_Module *dyn_module)
1372    /*------------------------------------------------------------------------*/
1373    /* Read the program header tables from the object file.                   */
1374    /*------------------------------------------------------------------------*/
1375    struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
1376    dyn_module->phdr = (struct Elf32_Phdr*)
1377                               (DLIF_malloc(fhdr->e_phnum * fhdr->e_phentsize));
1378    DLIF_fseek(fd, fhdr->e_phoff, LOADER_SEEK_SET);
1379    if(dyn_module->phdr) {
1380       DLIF_fread(dyn_module->phdr, fhdr->e_phentsize, fhdr->e_phnum,fd);
1381       dyn_module->phnum = fhdr->e_phnum;
1383       /*---------------------------------------------------------------------*/
1384       /* Byte swap the program header tables if the target endian-ness is not*/
1385       /* the same as the host endian-ness.                                   */
1386       /*---------------------------------------------------------------------*/
1387       if (dyn_module->wrong_endian)
1388       {
1389          int i;
1390          for (i = 0; i < dyn_module->phnum; i++)
1391             DLIMP_change_phdr_endian(dyn_module->phdr + i);
1392       }
1393    }
1396 /*****************************************************************************/
1397 /* dload_section_header_table()                                              */
1398 /*                                                                           */
1399 /*    Make a local copy of the ELF object file's section header table in the */
1400 /*    dynamic module data structure.                                         */
1401 /*                                                                           */
1402 /*****************************************************************************/
1403 static void dload_section_header_table(LOADER_FILE_DESC *fd,
1404                                        DLIMP_Dynamic_Module *dyn_module)
1406    /*------------------------------------------------------------------------*/
1407    /* Read the section header tables from the object file.                   */
1408    /*------------------------------------------------------------------------*/
1409    struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
1410    dyn_module->shdr = (struct Elf32_Shdr*)
1411                               (DLIF_malloc(fhdr->e_shnum * fhdr->e_shentsize));
1412    DLIF_fseek(fd, fhdr->e_shoff, LOADER_SEEK_SET);
1413    if(dyn_module->shdr) {
1414       DLIF_fread(dyn_module->shdr, fhdr->e_shentsize, fhdr->e_shnum,fd);
1415       dyn_module->shnum = fhdr->e_shnum;
1417       /*---------------------------------------------------------------------*/
1418       /* Byte swap the section header tables if the target endian-ness is not*/
1419       /* the same as the host endian-ness.                                   */
1420       /*---------------------------------------------------------------------*/
1421       if (dyn_module->wrong_endian)
1422       {
1423          int i;
1424          for (i = 0; i < dyn_module->shnum; i++)
1425             DLIMP_change_shdr_endian(dyn_module->shdr + i);
1426       }
1427    }
1430 /*****************************************************************************/
1431 /* dload_headers()                                                           */
1432 /*                                                                           */
1433 /*    Read ELF object file header and program header table information into  */
1434 /*    the given dynamic module data structure.  If the object file contains  */
1435 /*    dynamic information, read in the dynamic tags, dynamic symbol table,   */
1436 /*    and global string table.  Check to make sure that we are not already   */
1437 /*    in the process of loading the module (circular dependencies), then     */
1438 /*    perform some level of sanity checking on the content of the file to    */
1439 /*    provide some assurance that the file is not corrupted.                 */
1440 /*                                                                           */
1441 /*****************************************************************************/
1442 static BOOL dload_headers(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd,
1443                           DLIMP_Dynamic_Module *dyn_module)
1445 #if LOADER_DEBUG && LOADER_PROFILE
1446    /*------------------------------------------------------------------------*/
1447    /* More progress information.  Start timing if profiling is enabled.      */
1448    /*------------------------------------------------------------------------*/
1449    if (debugging_on || profiling_on)
1450    {
1451       DLIF_trace("\nReading file headers ...\n");
1452       if (profiling_on) profile_start_clock();
1453    }
1454 #endif
1456    /*------------------------------------------------------------------------*/
1457    /* Read file header information and check vs. expected ELF object file    */
1458    /* header content.                                                        */
1459    /*------------------------------------------------------------------------*/
1460     if (!dload_file_header(handle, fd, dyn_module))
1461       return FALSE;
1463    /*------------------------------------------------------------------------*/
1464    /* Read program header table information into the dynamic module object.  */
1465    /*------------------------------------------------------------------------*/
1466    dload_program_header_table(fd, dyn_module);
1468    /*------------------------------------------------------------------------*/
1469    /* Read section header table information into the dynamic module object.  */
1470    /*------------------------------------------------------------------------*/
1471    dload_section_header_table(fd, dyn_module);
1473    return TRUE;
1476 /*****************************************************************************/
1477 /* process_section_table()                                                   */
1478 /*                                                                           */
1479 /*    Process section tag entries from the section table.  At the conclusion */
1480 /*    of this function, we should have made a copy of the global symbols     */
1481 /*    and the global symbol names.                                           */
1482 /*                                                                           */
1483 /*****************************************************************************/
1484 static BOOL process_section_table(LOADER_FILE_DESC *fd,
1485                                   DLIMP_Dynamic_Module *dyn_module)
1487    int        i;
1488    Elf32_Addr shstrtab_offset = 0;
1490    /*------------------------------------------------------------------------*/
1491    /* Iterate over the section table in order to find the string table info.       */
1492    /*------------------------------------------------------------------------*/
1493    for (i = 0; i < dyn_module->shnum; i++)
1494    {
1495       switch(dyn_module->shdr[i].sh_type)
1496       {
1497          /*------------------------------------------------------------------*/
1498          /* SHT_STRTAB: Contains the section information of the string table.  The    */
1499          /*------------------------------------------------------------------*/
1500          case SHT_STRTAB:
1501             if (i == dyn_module->fhdr.e_shstrndx) {
1502                dyn_module->shstrsz = dyn_module->shdr[i].sh_size;
1503                shstrtab_offset = dyn_module->shdr[i].sh_offset;
1504 #if LOADER_DEBUG
1505                if (debugging_on)
1506                   DLIF_trace("Found string table Size: [0x%x]\n", dyn_module->shstrsz);
1507 #endif
1508             }
1509             break;
1511          /*------------------------------------------------------------------*/
1512          /* Unrecognized tag, may not be illegal, but is not explicitly      */
1513          /* handled by this function.  Should it be?                         */
1514          /*------------------------------------------------------------------*/
1515          default:
1516          {
1517             break;
1518          }
1520       }
1521    }
1523    /*------------------------------------------------------------------------*/
1524    /* If string table offset and size were found, read string table in from  */
1525    /* the ELF object file.                                                   */
1526    /*------------------------------------------------------------------------*/
1527    if (shstrtab_offset && dyn_module->shstrsz)
1528    {
1529       DLIF_fseek(fd, shstrtab_offset, LOADER_SEEK_SET);
1530       dyn_module->shstrtab = DLIF_malloc(dyn_module->shstrsz);
1531       DLIF_fread(dyn_module->shstrtab, sizeof(uint8_t), dyn_module->shstrsz, fd);
1532    }
1533    else
1534    {
1535       DLIF_warning(DLWT_MISC, "Mandatory string section SHT_STRTAB not found!\n");
1536       return FALSE;
1537    }
1539    return TRUE;
1542 /*****************************************************************************/
1543 /* find_dynamic_segment()                                                    */
1544 /*                                                                           */
1545 /*    Find the dynamic segment in the given ELF object file, if there is     */
1546 /*    one.  If the segment is found, then the segment ID output parameter    */
1547 /*    is set to the index of the dynamic segment in the program header       */
1548 /*    table.  If the dynamic segment is not found, the dynamic module's      */
1549 /*    relocatable flag is set to FALSE, and return FALSE.                    */
1550 /*                                                                           */
1551 /*****************************************************************************/
1552 static BOOL find_dynamic_segment(DLIMP_Dynamic_Module *dyn_module,
1553                                  Elf32_Word *dyn_seg_idx)
1555    int i;
1557    /*------------------------------------------------------------------------*/
1558    /* We should have a valid dynamic module pointer and somewhere to put the */
1559    /* dynamic segment id, if we find one.  If either of these are missing,   */
1560    /* we should get an internal error and abort the loader.                  */
1561    /*------------------------------------------------------------------------*/
1562    if ((dyn_module == NULL) || (dyn_seg_idx == NULL))
1563    {
1564       DLIF_error(DLET_MISC, "Internal error: find_dynamic_segment() needs "
1565                             "non-NULL arguments.\n");
1566 #if !defined (__KERNEL__)
1567       exit(1);
1568 #endif
1569    }
1571    /*------------------------------------------------------------------------*/
1572    /* Spin through segment program headers to find the dynamic segment.      */
1573    /*------------------------------------------------------------------------*/
1574    dyn_module->relocatable = TRUE;
1575    for (i = 0; i < dyn_module->phnum; i++)
1576       if (dyn_module->phdr[i].p_type == PT_DYNAMIC)
1577          { *dyn_seg_idx = i; return TRUE; }
1579    /*------------------------------------------------------------------------*/
1580    /* No dynamic segment found, mark the object module as not relocatable    */
1581    /* and warn the user.                                                     */
1582    /*------------------------------------------------------------------------*/
1583    dyn_module->relocatable = FALSE;
1584 #if LOADER_DEBUG
1585    if (debugging_on)
1586       DLIF_warning("'%s' does not have a dynamic segment; assuming "
1587                    "that it is a static executable and it cannot "
1588                    "be relocated.\n", dyn_module->name ? : "");
1589 #endif
1590    return FALSE;
1593 /*****************************************************************************/
1594 /* copy_dynamic_table()                                                      */
1595 /*                                                                           */
1596 /*    Make a local copy of the dynamic table read from the dynamic segment   */
1597 /*    in the ELF object file.                                                */
1598 /*                                                                           */
1599 /*****************************************************************************/
1600 static void copy_dynamic_table(LOADER_FILE_DESC *fd,
1601                                DLIMP_Dynamic_Module *dyn_module,
1602                                Elf32_Word dyn_seg_idx)
1605    /*------------------------------------------------------------------------*/
1606    /* Allocate space for the dynamic table from host memory and read its     */
1607    /* content from the ELF object file.                                      */
1608    /*------------------------------------------------------------------------*/
1609    Elf32_Word num_elem;
1610    dyn_module->dyntab = DLIF_malloc(dyn_module->phdr[dyn_seg_idx].p_filesz);
1611    num_elem =
1612         dyn_module->phdr[dyn_seg_idx].p_filesz / sizeof(struct Elf32_Dyn);
1613    DLIF_fseek(fd, dyn_module->phdr[dyn_seg_idx].p_offset, LOADER_SEEK_SET);
1614    if(dyn_module->dyntab) {
1615       DLIF_fread(dyn_module->dyntab, sizeof(struct Elf32_Dyn), num_elem, fd);
1617       /*---------------------------------------------------------------------*/
1618       /* If necessary, byte swap each entry in the dynamic table.            */
1619       /*---------------------------------------------------------------------*/
1620       if (dyn_module->wrong_endian)
1621       {
1622          int i;
1623          for (i = 0; i < num_elem; i++)
1624             DLIMP_change_dynent_endian(&dyn_module->dyntab[i]);
1625       }
1626    }
1629 /*****************************************************************************/
1630 /* process_target_dynamic_tag()                                              */
1631 /*                                                                           */
1632 /* Process a target specific dynamic tag entry.  Returns TRUE if the tag     */
1633 /* was handled and FALSE if it was not recognized.                           */
1634 /*****************************************************************************/
1635 static BOOL process_target_dynamic_tag(DLIMP_Dynamic_Module* dyn_module, int i)
1637 #ifdef ARM_TARGET
1638    if (is_arm_module(&dyn_module->fhdr))
1639        return DLDYN_arm_process_dynamic_tag(dyn_module, i);
1640 #endif
1642 #ifdef C60_TARGET
1643    if (is_c60_module(&dyn_module->fhdr))
1644       return DLDYN_c60_process_dynamic_tag(dyn_module, i);
1645 #endif
1647    return FALSE;
1650 /*****************************************************************************/
1651 /* process_dynamic_table()                                                   */
1652 /*                                                                           */
1653 /*    Process dynamic tag entries from the dynamic table.  At the conclusion */
1654 /*    of this function, we should have made a copy of the global symbols     */
1655 /*    and the global symbol names.                                           */
1656 /*                                                                           */
1657 /*****************************************************************************/
1658 static BOOL process_dynamic_table(LOADER_FILE_DESC *fd,
1659                                   DLIMP_Dynamic_Module *dyn_module)
1661    int        i;
1662    BOOL       soname_found  = FALSE;
1663    Elf32_Addr soname_offset = 0;
1664    Elf32_Addr strtab_offset = 0;
1665    Elf32_Addr hash_offset   = 0;
1666    Elf32_Addr symtab_offset = 0;
1668    /*------------------------------------------------------------------------*/
1669    /* Iterate over the dynamic table in order to process dynamic tags.       */
1670    /* See ELF TIS Specification for details on the meaning of each dynamic   */
1671    /* tag.  The C6000 ELF ABI Specification provides more details about the  */
1672    /* TI specific C6000 ELF ABI tags.                                        */
1673    /*------------------------------------------------------------------------*/
1674    for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
1675    {
1676       switch(dyn_module->dyntab[i].d_tag)
1677       {
1678          /*------------------------------------------------------------------*/
1679          /* DT_SONAME: Contains name of dynamic object, used for dependency  */
1680          /*            comparisons.  Its value is an offset from the start   */
1681          /*            of the string table.  We need to copy the string at   */
1682          /*            this offset into dmodule->name.                       */
1683          /*------------------------------------------------------------------*/
1684          case DT_SONAME:
1685 #if LOADER_DEBUG
1686             if (debugging_on) DLIF_trace("Found SO_NAME.\n");
1687 #endif
1688             /*---------------------------------------------------------------*/
1689             /* We store the offset of the so_name in the dynamic string      */
1690             /* table so that it doesn't matter which dynamic tag we see      */
1691             /* first (DT_SONAME actually is generated before DT_STRTAB).     */
1692             /*---------------------------------------------------------------*/
1693             soname_found = TRUE;
1694             soname_offset = dyn_module->dyntab[i].d_un.d_ptr;
1695             break;
1697          /*------------------------------------------------------------------*/
1698          /* DT_STRSZ: Contains the size of the string table.                 */
1699          /*------------------------------------------------------------------*/
1700          case DT_STRSZ:
1701             dyn_module->strsz = dyn_module->dyntab[i].d_un.d_val;
1703 #if LOADER_DEBUG
1704         if (debugging_on)
1705            DLIF_trace("Found string table Size: 0x%x\n", dyn_module->strsz);
1706 #endif
1707             break;
1709          /*------------------------------------------------------------------*/
1710          /* DT_STRTAB: Contains the file offset of the string table.  The    */
1711          /*            tag directly after this is guaranteed to be DT_STRSZ, */
1712          /*            containing the string table size.  We need to         */
1713          /*            allocate memory for the string table and copy it from */
1714          /*            the file.                                             */
1715          /*------------------------------------------------------------------*/
1716          case DT_STRTAB:
1717             strtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1718 #if LOADER_DEBUG
1719             if (debugging_on)
1720                DLIF_trace("Found string table: 0x%x\n", strtab_offset);
1721 #endif
1722             break;
1724          /*------------------------------------------------------------------*/
1725          /* DT_HASH: Contains the file offset of the symbol hash table.      */
1726          /*------------------------------------------------------------------*/
1727          case DT_HASH:
1728             hash_offset = dyn_module->dyntab[i].d_un.d_ptr;
1729 #if LOADER_DEBUG
1730             if (debugging_on)
1731                DLIF_trace("Found symbol hash table: 0x%x\n", hash_offset);
1732 #endif
1733             break;
1735          /*------------------------------------------------------------------*/
1736          /* DT_SYMTAB: Contains the file offset of the symbol table.         */
1737          /*------------------------------------------------------------------*/
1738          case DT_SYMTAB:
1739             symtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1740 #if LOADER_DEBUG
1741             if (debugging_on)
1742                DLIF_trace("Found symbol table: 0x%x\n", symtab_offset);
1743 #endif
1744             break;
1746          /*------------------------------------------------------------------*/
1747      /* DSO Initialization / Termination Model Dynamic Tags              */
1748          /*------------------------------------------------------------------*/
1749      /* For initialization tags, we store indices and array sizes in     */
1750      /* the dyn_module. Termination works a little different, the        */
1751      /* indices into the local copy of the dynamic table are stored in   */
1752      /* dyn_module, but the DT_FINI_ARRAYSZ value is recorded with the   */
1753      /* loaded module.                                                   */
1754          /*------------------------------------------------------------------*/
1755      /* After placement is done, the DT_FINI and DT_FINI_ARRAY values    */
1756      /* need to be copied from the local dynamic table into the loaded   */
1757      /* module object.                                                   */
1758          /*------------------------------------------------------------------*/
1759      case DT_PREINIT_ARRAY:
1760         dyn_module->preinit_array_idx = i;
1761         break;
1763      case DT_PREINIT_ARRAYSZ:
1764         dyn_module->preinit_arraysz = dyn_module->dyntab[i].d_un.d_val;
1765         break;
1767      case DT_INIT:
1768         dyn_module->init_idx = i;
1769         break;
1771      case DT_INIT_ARRAY:
1772         dyn_module->init_array_idx = i;
1773         break;
1775      case DT_INIT_ARRAYSZ:
1776         dyn_module->init_arraysz = dyn_module->dyntab[i].d_un.d_val;
1777         break;
1779          /*------------------------------------------------------------------*/
1780      /* This information will be copied over to the loaded module        */
1781      /* object after placement has been completed and the information    */
1782      /* in the dynamic table has been relocated.                         */
1783          /*------------------------------------------------------------------*/
1784      case DT_FINI_ARRAY:
1785      case DT_FINI_ARRAYSZ:
1786      case DT_FINI:
1787         break;
1789          /*------------------------------------------------------------------*/
1790          /* Unrecognized tag, may not be illegal, but is not explicitly      */
1791          /* handled by this function.  Should it be?                         */
1792          /*------------------------------------------------------------------*/
1793          default:
1794          {
1795             if (!process_target_dynamic_tag(dyn_module, i))
1796             {
1797 #if LOADER_DEBUG
1798                if (debugging_on)
1799                   DLIF_trace("Unrecognized dynamic tag: 0x%X\n",
1800                                dyn_module->dyntab[i].d_tag);
1801 #endif
1802             }
1804             break;
1805          }
1807       }
1808    }
1810    /*------------------------------------------------------------------------*/
1811    /* If string table offset and size were found, read string table in from  */
1812    /* the ELF object file.                                                   */
1813    /*------------------------------------------------------------------------*/
1814    if (strtab_offset && dyn_module->strsz)
1815    {
1816       DLIF_fseek(fd, strtab_offset, LOADER_SEEK_SET);
1817       dyn_module->strtab = DLIF_malloc(dyn_module->strsz);
1818       if(dyn_module->strtab)
1819          DLIF_fread(dyn_module->strtab, sizeof(uint8_t), dyn_module->strsz,
1820                     fd);
1821       else
1822          return FALSE;
1823    }
1824    else
1825    {
1826       DLIF_warning(DLWT_MISC,
1827                    "Mandatory dynamic tag DT_STRTAB/DT_STRSZ not found!\n");
1828       return FALSE;
1829    }
1832    /*------------------------------------------------------------------------*/
1833    /* If symbol hash table is found read-in the hash table.                  */
1834    /*------------------------------------------------------------------------*/
1835    if (hash_offset)
1836    {
1837       /*---------------------------------------------------------------------*/
1838       /* Hash table has the following format. nchain equals the number of    */
1839       /* entries in the symbol table (symnum)                                */
1840       /*                                                                     */
1841       /*             +----------------------------+                          */
1842       /*             |          nbucket           |                          */
1843       /*             +----------------------------+                          */
1844       /*             |          nchain            |                          */
1845       /*             +----------------------------+                          */
1846       /*             |         bucket[0]          |                          */
1847       /*             |            ...             |                          */
1848       /*             |     bucket[nbucket-1]      |                          */
1849       /*             +----------------------------+                          */
1850       /*             |          chain[0]          |                          */
1851       /*             |            ...             |                          */
1852       /*             |       chain[nchain-1]      |                          */
1853       /*             +----------------------------+                          */
1854       /*---------------------------------------------------------------------*/
1855       Elf32_Word hash_nbucket;
1856       Elf32_Word hash_nchain;
1858       /*---------------------------------------------------------------------*/
1859       /* Seek to the hash offset and read first two words into nbucket and   */
1860       /* symnum.                                                             */
1861       /*---------------------------------------------------------------------*/
1862       DLIF_fseek(fd, hash_offset, LOADER_SEEK_SET);
1863       DLIF_fread(&(hash_nbucket), sizeof(Elf32_Word), 1, fd);
1864       DLIF_fread(&(hash_nchain), sizeof(Elf32_Word), 1, fd);
1865       if (dyn_module->wrong_endian)
1866       {
1867          DLIMP_change_endian32((int32_t*)(&(hash_nbucket)));
1868          DLIMP_change_endian32((int32_t*)(&(hash_nchain)));
1869       }
1871       /*---------------------------------------------------------------------*/
1872       /* The number of entires in the dynamic symbol table is not encoded    */
1873       /* anywhere in the elf file. However, the nchain is guaranteed to be   */
1874       /* the same as the number of symbols. Use nchain to set the symnum.    */
1875       /*---------------------------------------------------------------------*/
1876       dyn_module->symnum = hash_nchain;
1877 #if LOADER_DEBUG
1878       if (debugging_on) DLIF_trace("symnum=%d\n", hash_nchain);
1879 #endif
1880    }
1881    else
1882    {
1883       DLIF_warning(DLWT_MISC,
1884                    "Mandatory dynamic tag DT_HASH is not found!\n");
1885       return FALSE;
1886    }
1888    /*------------------------------------------------------------------------*/
1889    /* Read dynamic symbol table.                                             */
1890    /*------------------------------------------------------------------------*/
1891    if (symtab_offset)
1892    {
1893       int j = 0;
1894       DLIF_fseek(fd, symtab_offset, LOADER_SEEK_SET);
1895       dyn_module->symtab =
1896                  DLIF_malloc(dyn_module->symnum * sizeof(struct Elf32_Sym));
1897       if(dyn_module->symtab == NULL)
1898          return FALSE;
1899       DLIF_fread(dyn_module->symtab, sizeof(struct Elf32_Sym),
1900                  dyn_module->symnum, fd);
1901       if (dyn_module->wrong_endian)
1902       {
1903          for (j = 0; j < dyn_module->symnum; j++)
1904             DLIMP_change_sym_endian(dyn_module->symtab + j);
1905       }
1907       /*---------------------------------------------------------------------*/
1908       /* The st_name field of an Elf32_Sym entity is an offset into the      */
1909       /* string table. Convert it into a pointer to the string.              */
1910       /*---------------------------------------------------------------------*/
1911       if (strtab_offset)
1912          for (j = 0; j < dyn_module->symnum; j++)
1913             dyn_module->symtab[j].st_name += (Elf32_Word) dyn_module->strtab;
1914    }
1915    else
1916    {
1917       DLIF_warning(DLWT_MISC,
1918                    "Mandatory dynamic tag DT_SYMTAB is not found!\n");
1919       return FALSE;
1920    }
1922    /*------------------------------------------------------------------------*/
1923    /* Read the SONAME.                                                       */
1924    /*------------------------------------------------------------------------*/
1925    if (!soname_found)
1926    {
1927       DLIF_warning(DLWT_MISC, "Dynamic tag DT_SONAME is not found!\n");
1928       dyn_module->name = DLIF_malloc(sizeof(char));
1929       if(dyn_module->name)
1930           *dyn_module->name = '\0';
1931       else
1932           return FALSE;
1933    }
1934    else
1935    {
1936       dyn_module->name =
1937                     DLIF_malloc(strlen(dyn_module->strtab + soname_offset) + 1);
1938       if(dyn_module->name) {
1939          strcpy(dyn_module->name, dyn_module->strtab + soname_offset);
1941 #if LOADER_DEBUG
1942          if (debugging_on)
1943             DLIF_trace("Name of dynamic object: %s\n", dyn_module->name);
1944 #endif
1945       }
1946       else {
1947          DLIF_error(DLET_MISC, "Error allocating memory %d.\n",__LINE__);
1948          return FALSE;
1949       }
1950    }
1952    return TRUE;
1956 /*****************************************************************************/
1957 /* dload_dynamic_information()                                               */
1958 /*                                                                           */
1959 /*    Given a dynamic module with a dynamic segment which is located via     */
1960 /*    given dynamic segment index, make a local copy of the dynamic table    */
1961 /*    in the dynamic module object, then process the dynamic tag entries in  */
1962 /*    the table.                                                             */
1963 /*                                                                           */
1964 /*****************************************************************************/
1965 static BOOL dload_dynamic_information(LOADER_FILE_DESC *fd,
1966                                       DLIMP_Dynamic_Module *dyn_module,
1967                                       Elf32_Word dyn_seg_idx)
1969    /*------------------------------------------------------------------------*/
1970    /* Read a copy of the dynamic table into the dynamic module object.       */
1971    /*------------------------------------------------------------------------*/
1972    copy_dynamic_table(fd, dyn_module, dyn_seg_idx);
1974    /*------------------------------------------------------------------------*/
1975    /* Process dynamic entries in the dynamic table.  If any problems are     */
1976    /* encountered, the loader should emit an error or warning and return     */
1977    /* FALSE here.                                                            */
1978    /*------------------------------------------------------------------------*/
1979    return process_dynamic_table(fd, dyn_module);
1982 /*****************************************************************************/
1983 /* check_circular_dependency()                                               */
1984 /*                                                                           */
1985 /*    Determine whether a dynamic module is already in the process of being  */
1986 /*    loaded before we try to start loading it again.  If it is already      */
1987 /*    being loaded, then the dynamic loader has detected a circular          */
1988 /*    dependency.  An error will be emitted and the load will be aborted.    */
1989 /*                                                                           */
1990 /*****************************************************************************/
1991 static BOOL check_circular_dependency(DLOAD_HANDLE handle,
1992                                       const char *dyn_mod_name)
1994    /*------------------------------------------------------------------------*/
1995    /* Check the name of the given dependency module to be loaded against the */
1996    /* list of modules that are currently in the process of being loaded.     */
1997    /* Report an error if any circular dependencies are detected.             */
1998    /*------------------------------------------------------------------------*/
1999    int i;
2000     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2001     for (i = 0; i < pHandle->DLIMP_module_dependency_list.size; i++)
2002         if (!strcmp(dyn_mod_name,
2003             ((char**)(pHandle->DLIMP_module_dependency_list.buf))[i]))
2004       {
2005          DLIF_error(DLET_MISC,
2006                     "Circular dependency detected, '%s' is already in the "
2007                     "process of loading.\n", dyn_mod_name);
2008          return FALSE;
2009       }
2011    return TRUE;
2014 /*****************************************************************************/
2015 /* dload_dynamic_segment()                                                   */
2016 /*                                                                           */
2017 /*    Find the dynamic segment in the given ELF module, if there is one.     */
2018 /*    If there is a dynamic segment, then make a local copy of the dynamic   */
2019 /*    table in the dynamic module object provided, then process the dynamic  */
2020 /*    tag entries in the table.                                              */
2021 /*                                                                           */
2022 /*    If there is no dynamic segment, then we return success from this       */
2023 /*    function, marking the dynamic module as "not relocatable".             */
2024 /*                                                                           */
2025 /*****************************************************************************/
2026 static BOOL dload_dynamic_segment(DLOAD_HANDLE handle,
2027                                   LOADER_FILE_DESC *fd,
2028                                   DLIMP_Dynamic_Module *dyn_module)
2030    /*------------------------------------------------------------------------*/
2031    /* If we don't find dynamic segment, the relocatable flag will have been  */
2032    /* set to false to indicate that the module is a static executable.  We   */
2033    /* still return TRUE from this function so that we can proceed with       */
2034    /* static loading.                                                        */
2035    /*------------------------------------------------------------------------*/
2036    Elf32_Word dyn_seg_idx = 0;
2037    if (!find_dynamic_segment(dyn_module, &dyn_seg_idx))
2038       return TRUE;
2040    /*------------------------------------------------------------------------*/
2041    /* Process the OSABI now, after we know if the module is relocatable.     */
2042    /*------------------------------------------------------------------------*/
2043    if (!process_eiosabi(dyn_module))
2044    {
2045       DLIF_error(DLET_FILE, "Unsupported EI_OSABI value.\n");
2046       return FALSE;
2047    }
2049    /*------------------------------------------------------------------------*/
2050    /* Read the dynamic table from the ELF file, then process the dynamic     */
2051    /* tags in the table.                                                     */
2052    /*------------------------------------------------------------------------*/
2053    if (!dload_dynamic_information(fd, dyn_module, dyn_seg_idx))
2054       return FALSE;
2056    /*------------------------------------------------------------------------*/
2057    /* Check to make sure that this module is not already being loaded.  If   */
2058    /* is, then it will cause a circular dependency to be introduced.         */
2059    /* Loader should detect circular dependencies and emit an error.          */
2060    /*------------------------------------------------------------------------*/
2061     if (!check_circular_dependency(handle, dyn_module->name))
2062       return FALSE;
2064    return TRUE;
2067 /*****************************************************************************/
2068 /* COPY_SEGMENTS() -                                                         */
2069 /*                                                                           */
2070 /*   Copy all segments into host memory.                                     */
2071 /*****************************************************************************/
2072 static void copy_segments(DLOAD_HANDLE handle, LOADER_FILE_DESC* fp,
2073                           DLIMP_Dynamic_Module* dyn_module, int* data)
2075     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2076    DLIMP_Loaded_Segment* seg =
2077       (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
2078    int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
2079    void **va = DLIF_malloc(seg_size * sizeof(void*));
2081    if (!va) {
2082       DLIF_error(DLET_MISC, "Failed to allocate va in copy_segments.\n");
2083       return;
2084    }
2085    else
2086       *data = (int)va;
2088    for (s=0; s<seg_size; s++)
2089    {
2090       struct DLOAD_MEMORY_REQUEST targ_req;
2091       targ_req.fp = fp;
2092       targ_req.segment = seg[s].obj_desc;
2093       targ_req.offset = seg[s].phdr.p_offset;
2094       targ_req.flags = DLOAD_SF_relocatable;
2095       if (seg[s].phdr.p_flags & PF_X)
2096          seg[s].phdr.p_flags |= DLOAD_SF_executable;
2097       targ_req.align = seg[s].phdr.p_align;
2099       /*---------------------------------------------------------------------*/
2100       /* Copy segment data from the file into host buffer where it can       */
2101       /* be relocated.                                                       */
2102       /*---------------------------------------------------------------------*/
2103         DLIF_copy(pHandle->client_handle, &targ_req);
2105       va[s] = targ_req.host_address;
2107       /*---------------------------------------------------------------------*/
2108       /* Calculate offset for relocations.                                   */
2109       /*---------------------------------------------------------------------*/
2110       seg[s].reloc_offset = (int32_t)(targ_req.host_address) -
2111                             (int32_t)(seg[s].obj_desc->target_address);
2112    }
2115 /*****************************************************************************/
2116 /* WRITE_SEGMENTS() -                                                        */
2117 /*                                                                           */
2118 /*   Write all segments to target memory.                                    */
2119 /*****************************************************************************/
2120 static void write_segments(DLOAD_HANDLE handle, LOADER_FILE_DESC* fp,
2121                           DLIMP_Dynamic_Module* dyn_module, int* data)
2123     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2124    DLIMP_Loaded_Segment* seg =
2125       (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
2126    int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
2127    void **va = (void *)*data;
2129    if (!va) {
2130       DLIF_error(DLET_MISC, "Invalid host virtual address array passed into"
2131                  "write_segments.\n");
2132       return;
2133    }
2135    for (s=0; s<seg_size; s++)
2136    {
2137       struct DLOAD_MEMORY_REQUEST targ_req;
2138       targ_req.fp = fp;
2139       targ_req.segment = seg[s].obj_desc;
2140       targ_req.offset = seg[s].phdr.p_offset;
2141       targ_req.flags = DLOAD_SF_relocatable;
2142       if (seg[s].phdr.p_flags & PF_X)
2143          seg[s].phdr.p_flags |= DLOAD_SF_executable;
2144       targ_req.align = seg[s].phdr.p_align;
2145       targ_req.host_address = va[s];
2147       /*---------------------------------------------------------------------*/
2148       /* Copy segment data from the file into host buffer where it can       */
2149       /* be relocated.                                                       */
2150       /*---------------------------------------------------------------------*/
2151         DLIF_write(pHandle->client_handle, &targ_req);
2152    }
2154    DLIF_free(va);
2157 /*****************************************************************************/
2158 /* DLOAD_initialize()                                                        */
2159 /*                                                                           */
2160 /*    Construct and initialize data structures internal to the dynamic       */
2161 /*    loader core.                                                           */
2162 /*                                                                           */
2163 /*---------------------------------------------------------------------------*/
2164 /*                                                                           */
2165 /*    This implementation of DLOAD_initialize() will set up the list of      */
2166 /*    dependency modules maintained by the loader core.  This list contains  */
2167 /*    the names of the files that the loader is in the process of loading.   */
2168 /*    The list is used to keep track of what objects are waiting on their    */
2169 /*    dependents to be loaded so thath circular dependencies can be detected */
2170 /*    and reported by the core loader.                                       */
2171 /*                                                                           */
2172 /*****************************************************************************/
2173 void DLOAD_initialize(DLOAD_HANDLE handle)
2175      LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2177    /*------------------------------------------------------------------------*/
2178    /* Set up initial objects_loading queue.                                  */
2179    /*------------------------------------------------------------------------*/
2180     AL_initialize(&pHandle->DLIMP_module_dependency_list,
2181                   sizeof (const char*), 1);
2185 /*****************************************************************************/
2186 /* DLOAD_finalize()                                                          */
2187 /*                                                                           */
2188 /*    Destroy and finalize data structures internal to the dynamic           */
2189 /*    loader core.                                                           */
2190 /*                                                                           */
2191 /*---------------------------------------------------------------------------*/
2192 /*                                                                           */
2193 /*    This implementation of DLOAD_finalize() will destroy the list of       */
2194 /*    dependency modules maintained by the loader core that is created       */
2195 /*    during DLOAD_initialize().                                             */
2196 /*                                                                           */
2197 /*****************************************************************************/
2198 void DLOAD_finalize(DLOAD_HANDLE handle)
2200     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2202     /*-----------------------------------------------------------------------*/
2203     /* Destroy initial objects_loading queue.                                */
2204     /*-----------------------------------------------------------------------*/
2205     AL_destroy(&pHandle->DLIMP_module_dependency_list);
2209 /*****************************************************************************/
2210 /* dload_static_executable()                                                 */
2211 /*                                                                           */
2212 /*    Account for target memory allocated to static executable and wrap up   */
2213 /*    loading.  No relocation is necessary.                                  */
2214 /*                                                                           */
2215 /*****************************************************************************/
2216 static int32_t dload_static_executable(DLOAD_HANDLE handle,
2217                                        LOADER_FILE_DESC *fd,
2218                                        DLIMP_Dynamic_Module *dyn_module)
2220    int32_t local_file_handle = 0;
2222 #if LOADER_DEBUG
2223    if (debugging_on) DLIF_trace("Starting dload_static_executable() ...\n");
2224 #endif
2226    /*------------------------------------------------------------------------*/
2227    /* Set entry point for static executable and attempt to allocate target   */
2228    /* memory for the static executable.                                      */
2229    /*------------------------------------------------------------------------*/
2230    dyn_module->loaded_module->entry_point = dyn_module->fhdr.e_entry;
2231     if (load_static_segment(handle, fd, dyn_module) &&
2232         load_object(fd, dyn_module))
2233    {
2234       /*---------------------------------------------------------------------*/
2235       /* If successful, we'll want to detach the loaded module object from   */
2236       /* the dynamic module object that created it.  Take note of the file   */
2237       /* handle.                                                             */
2238       /*---------------------------------------------------------------------*/
2239       DLIMP_Loaded_Module *loaded_module = detach_loaded_module(dyn_module);
2240         if (loaded_module)
2241             local_file_handle = loaded_module->file_handle;
2242         else {
2243             DLIF_error(DLET_MISC, "Failed to detach module.\n");
2244             delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2245             return local_file_handle;
2246         }
2247    }
2249    /*------------------------------------------------------------------------*/
2250    /* Static load failed.  Flag an error.                                    */
2251    /*------------------------------------------------------------------------*/
2252    else
2253     {
2254         DLIF_trace("%s:%d EMEMORY\n",__func__,__LINE__);
2255       DLIF_error(DLET_MEMORY,
2256                  "Failed to allocate target memory for static executable.\n");
2257     }
2259    /*------------------------------------------------------------------------*/
2260    /* Destruct dynamic module object.                                        */
2261    /*------------------------------------------------------------------------*/
2262     delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2264 #if LOADER_DEBUG
2265    if (debugging_on) DLIF_trace("Finished dload_static_executable()\n");
2266 #endif
2268    return local_file_handle;
2271 /*****************************************************************************/
2272 /* process_dynamic_module_relocations()                                      */
2273 /*                                                                           */
2274 /*    Make a host-accessible copy of all of the segments, process all        */
2275 /*    relocation entries associated with the given module within that        */
2276 /*    space, then write the updated segment buffers back out to target       */
2277 /*    memory.                                                                */
2278 /*                                                                           */
2279 /*****************************************************************************/
2280 static void process_dynamic_module_relocations(DLOAD_HANDLE handle,
2281                                                LOADER_FILE_DESC *fd,
2282                                                DLIMP_Dynamic_Module *dyn_module)
2284     int data = 0;
2286 #if LOADER_DEBUG && LOADER_PROFILE
2287    if(debugging_on || profiling_on)
2288    {
2289       DLIF_trace("Running relocate()...\n");
2290       if (profiling_on) profile_start_clock();
2291    }
2292 #endif
2294    /*------------------------------------------------------------------------*/
2295    /* Copy segments from file to host memory                                 */
2296    /*------------------------------------------------------------------------*/
2297    copy_segments(handle, fd, dyn_module, &data);
2299    /*------------------------------------------------------------------------*/
2300    /* Process dynamic relocations.                                           */
2301    /*------------------------------------------------------------------------*/
2302 #if ARM_TARGET
2303    if (is_arm_module(&dyn_module->fhdr))
2304       DLREL_relocate(handle, fd, dyn_module);
2305 #endif
2307 #if C60_TARGET
2308    if (is_c60_module(&dyn_module->fhdr))
2309       DLREL_relocate_c60(handle, fd, dyn_module);
2310 #endif
2312    /*------------------------------------------------------------------------*/
2313    /* Write segments from host memory to target memory                       */
2314    /*------------------------------------------------------------------------*/
2315    write_segments(handle, fd, dyn_module, &data);
2317 #if 0
2318    /*------------------------------------------------------------------------*/
2319    /* Report timing and progress information for relocation step.            */
2320    /*------------------------------------------------------------------------*/
2321    if (debugging_on || profiling_on)
2322    {
2323       if (profiling_on)
2324       {
2325          profile_stop_clock();
2326          DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
2327          DLIF_trace("Total reloc time: %d\n", (int)DLREL_total_reloc_time);
2328          DLIF_trace("Time per relocation: %d\n",
2329                     (DLREL_relocations ?
2330                     (int)(DLREL_total_reloc_time / DLREL_relocations) : 0));
2331       }
2333       DLIF_trace("Number of relocations: %d\n", DLREL_relocations);
2334       DLIF_trace("\nAbout to run load_object()...");
2335       DLREL_total_reloc_time = DLREL_relocations = 0;
2336       if (profiling_on) profile_start_clock();
2337    }
2338 #endif
2341 /*****************************************************************************/
2342 /* execute_module_pre_initialization()                                       */
2343 /*                                                                           */
2344 /*    Given a dynamic module object, execute any pre-initialization          */
2345 /*    functions for the specified dynamic executable module. Such functions  */
2346 /*    must be provided by the user and their addresses written to the        */
2347 /*    .preinit_array section. These functions should be executed in the      */
2348 /*    order that they are specified in the array before the initialization   */
2349 /*    process for this dynamic executable module begins.                     */
2350 /*                                                                           */
2351 /*---------------------------------------------------------------------------*/
2352 /*                                                                           */
2353 /*    Note that dynamic shared objects (libraries) should not have a         */
2354 /*    .preinit_array (should be caught during static link-time if the user   */
2355 /*    attempts to link a .preinit_array section into a shared object.        */
2356 /*                                                                           */
2357 /*****************************************************************************/
2358 static void execute_module_pre_initialization(DLOAD_HANDLE handle, DLIMP_Dynamic_Module *dyn_module)
2360    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2362    /*------------------------------------------------------------------------*/
2363    /* Check for presence of DT_PREINIT_ARRAY and DT_PREINIT_ARRAYSZ          */
2364    /* dynamic tags associated with this module. The dyn_module object will   */
2365    /* hold the relevant indices into the local copy of the dynamic table.    */
2366    /* The value of the DT_INIT_ARRAY tag will have been updated after        */
2367    /* placement of the  module was completed.                                */
2368    /*------------------------------------------------------------------------*/
2369    if (dyn_module->preinit_arraysz != 0)
2370    {
2371       /*---------------------------------------------------------------------*/
2372       /* Retrieve the address of the .preinit_array section from the value   */
2373       /* of the DT_PREINIT_ARRAY tag.                                        */
2374       /*---------------------------------------------------------------------*/
2375       TARGET_ADDRESS preinit_array_loc = (TARGET_ADDRESS)
2376                 (dyn_module->dyntab[dyn_module->preinit_array_idx].d_un.d_ptr);
2378       /*---------------------------------------------------------------------*/
2379       /* Now make a loader-accessible copy of the .preinit_array section.    */
2380       /*---------------------------------------------------------------------*/
2381       int32_t i;
2382       int32_t num_preinit_fcns =
2383                             dyn_module->preinit_arraysz/sizeof(TARGET_ADDRESS);
2384       TARGET_ADDRESS *preinit_array_buf = (TARGET_ADDRESS *)
2385                                       DLIF_malloc(dyn_module->preinit_arraysz);
2386       if(preinit_array_buf) {
2387          DLIF_read(pHandle->client_handle, preinit_array_buf, 1,
2388                                             dyn_module->preinit_arraysz,
2389                                             (TARGET_ADDRESS)preinit_array_loc);
2391          /*------------------------------------------------------------------*/
2392          /* Call each function whose address occupies an entry in the array  */
2393          /* in the order that it appears in the array. The sizeof the array  */
2394          /* is provided by the preinit_arraysz field in the dynamic module   */
2395          /* (copied) earlier when the dynamic table was read in). We need to */
2396          /* divide the sizeof value down to get the number of actual entries */
2397          /* in the array.                                                    */
2398          /*------------------------------------------------------------------*/
2399          for (i = 0; i < num_preinit_fcns; i++)
2400             DLIF_execute(pHandle->client_handle,
2401                          (TARGET_ADDRESS)(preinit_array_buf[i]));
2403          DLIF_free(preinit_array_buf);
2404       }
2405    }
2408 /*****************************************************************************/
2409 /* execute_module_initialization()                                           */
2410 /*                                                                           */
2411 /*    Given a dynamic module object, execute initialization function(s) for  */
2412 /*    all global and static data objects that are defined in the module      */
2413 /*    which require construction. The user may also provide a custom         */
2414 /*    iniitialization function that needs to be executed before the compiler */
2415 /*    generated static initialization functions are executed.                */
2416 /*                                                                           */
2417 /*****************************************************************************/
2418 static void execute_module_initialization(DLOAD_HANDLE handle,
2419                                           DLIMP_Dynamic_Module *dyn_module)
2421    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2423    /*------------------------------------------------------------------------*/
2424    /* Check for presence of a DT_INIT dynamic tag associated with this       */
2425    /* module. The dynamic module will hold the index into the local copy of  */
2426    /* the dynamic table. This entry in the dynamic table will have been      */
2427    /* updated after placement of the module is completed.                    */
2428    /*------------------------------------------------------------------------*/
2429    if (dyn_module->init_idx != -1)
2430    {
2431       /*---------------------------------------------------------------------*/
2432       /* Retrieve the address of the initialization function from the value  */
2433       /* of the DT_INIT tag, and get the client to execute the function.     */
2434       /*---------------------------------------------------------------------*/
2435       TARGET_ADDRESS init_fcn = (TARGET_ADDRESS)
2436                          (dyn_module->dyntab[dyn_module->init_idx].d_un.d_ptr);
2437       DLIF_execute(pHandle->client_handle, init_fcn);
2438    }
2440    /*------------------------------------------------------------------------*/
2441    /* Check for presence of a DT_INIT_ARRAY and DT_INIT_ARRAYSZ dynamic tags */
2442    /* associated with this module. The dyn_module object will hold the       */
2443    /* relevant indices into the local copy of the dynamic table. The value   */
2444    /* of the DT_INIT_ARRAY tag will have been updated after placement of the */
2445    /* module was completed.                                                  */
2446    /*------------------------------------------------------------------------*/
2447    if (dyn_module->init_arraysz != 0)
2448    {
2449       /*---------------------------------------------------------------------*/
2450       /* Retrieve the address of the .init_array section from the value of   */
2451       /* DT_INIT_ARRAY tag.                                                  */
2452       /*---------------------------------------------------------------------*/
2453       TARGET_ADDRESS init_array_loc = (TARGET_ADDRESS)
2454                    (dyn_module->dyntab[dyn_module->init_array_idx].d_un.d_ptr);
2456       /*---------------------------------------------------------------------*/
2457       /* Now make a loader-accessible copy of the .init_array section.       */
2458       /*---------------------------------------------------------------------*/
2459       int32_t i;
2460       int32_t num_init_fcns = dyn_module->init_arraysz/sizeof(TARGET_ADDRESS);
2461       TARGET_ADDRESS *init_array_buf = (TARGET_ADDRESS *)
2462                                          DLIF_malloc(dyn_module->init_arraysz);
2463       if(init_array_buf) {
2464          DLIF_read(pHandle->client_handle, init_array_buf, 1,
2465                    dyn_module->init_arraysz, (TARGET_ADDRESS)init_array_loc);
2467          /*------------------------------------------------------------------*/
2468          /* Call each function whose address occupies an entry in the array  */
2469          /* in the order that they appear in the array. The size of the array*/
2470          /* is provided by the init_arraysz field in the dynamic module      */
2471          /* (copied earlier when the dynamic table was read in).             */
2472          /*------------------------------------------------------------------*/
2473          for (i = 0; i < num_init_fcns; i++)
2474             DLIF_execute(pHandle->client_handle,
2475                          (TARGET_ADDRESS)(init_array_buf[i]));
2477          DLIF_free(init_array_buf);
2478       }
2479    }
2482 /*****************************************************************************/
2483 /* relocate_dependency_graph_modules()                                       */
2484 /*                                                                           */
2485 /*    For each dynamic module on the dependency stack, process dynamic       */
2486 /*    relocation entries then perform initialization for all global and      */
2487 /*    static objects that are defined in tha given module. The stack is      */
2488 /*    emptied from the top (LIFO).  Each dynamic module object is popped     */
2489 /*    off the top of the stack, the module gets relocated, its global and    */
2490 /*    static objects that need to be constructed will be constructed, and    */
2491 /*    then, after detaching the loaded module object from its dynamic        */
2492 /*    module, the dynamic module object is destructed.                       */
2493 /*                                                                           */
2494 /*****************************************************************************/
2495 static int32_t relocate_dependency_graph_modules(DLOAD_HANDLE handle,
2496                                                  LOADER_FILE_DESC *fd,
2497                                                  DLIMP_Dynamic_Module *dyn_module)
2499    /*------------------------------------------------------------------------*/
2500    /* Processing of relocations will only be triggered when this function    */
2501    /* is called from the top-level object module (at the bottom of the       */
2502    /* dependency graph stack).                                               */
2503    /*------------------------------------------------------------------------*/
2504    int32_t local_file_handle = dyn_module->loaded_module->file_handle;
2505    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2506    dynamic_module_ptr_Stack_Node *ptr =
2507       pHandle->DLIMP_dependency_stack.bottom_ptr;
2508    if (ptr && (ptr->value != dyn_module)) {return local_file_handle;}
2510    /*------------------------------------------------------------------------*/
2511    /* Assign DSBT indices.                                                   */
2512    /*------------------------------------------------------------------------*/
2513    DLIF_assign_dsbt_indices();
2515    /*------------------------------------------------------------------------*/
2516    /* Update the content of all DSBTs for any module that uses the DSBT      */
2517    /* model.                                                                 */
2518    /*------------------------------------------------------------------------*/
2519    DLIF_update_all_dsbts();
2521    /*------------------------------------------------------------------------*/
2522    /* Ok, we are ready to process relocations. The relocation tables         */
2523    /* associated with dependent files will be processed first. Consume       */
2524    /* dynamic module objects from the dependency graph stack from dependents */
2525    /* to the root of the dependency graph.                                   */
2526    /*------------------------------------------------------------------------*/
2527    while (pHandle->DLIMP_dependency_stack.size > 0)
2528    {
2529       DLIMP_Dynamic_Module *dyn_mod_ptr =
2530                       dynamic_module_ptr_pop(&pHandle->DLIMP_dependency_stack);
2532       /*---------------------------------------------------------------------*/
2533       /* Process dynamic relocations associated with this module.            */
2534       /*---------------------------------------------------------------------*/
2535       process_dynamic_module_relocations(handle, dyn_mod_ptr->fd,
2536                                          dyn_mod_ptr);
2538       /*---------------------------------------------------------------------*/
2539       /* __c_args__ points to the beginning of the .args section, if there   */
2540       /* is one.  Record this pointer in the ELF file internal data object.  */
2541       /*---------------------------------------------------------------------*/
2542       DLSYM_lookup_local_symtab("__c_args__", dyn_mod_ptr->symtab,
2543                                 dyn_mod_ptr->symnum,
2544                                 (Elf32_Addr *)&dyn_mod_ptr->c_args);
2546       /*---------------------------------------------------------------------*/
2547       /* Pick up entry point address from ELF file header.                   */
2548       /*   We currently only support a single entry point into the ELF file. */
2549       /*   To support Braveheart notion of nodes, with multiple entry points,*/
2550       /*   we'll need to get the list of entry points associated with a node,*/
2551       /*   then add capability to the "execute" command to select the entry  */
2552       /*   point that we want to start executing from.                       */
2553       /*---------------------------------------------------------------------*/
2554       dyn_mod_ptr->loaded_module->entry_point = dyn_mod_ptr->fhdr.e_entry;
2556       /*---------------------------------------------------------------------*/
2557       /* Copy command-line arguments into args section and deal with DSBT    */
2558       /* issues (copy DSBT to its run location).                             */
2559       /*---------------------------------------------------------------------*/
2560       load_object(dyn_mod_ptr->fd, dyn_mod_ptr);
2562       /*---------------------------------------------------------------------*/
2563       /* Perform initialization, if needed, for this module.                 */
2564       /*---------------------------------------------------------------------*/
2565       execute_module_initialization(handle, dyn_mod_ptr);
2567       /*---------------------------------------------------------------------*/
2568       /* Free all dependent file pointers.                                   */
2569       /*---------------------------------------------------------------------*/
2570       if (dyn_mod_ptr->fd != fd)
2571       {
2572          DLIF_fclose(dyn_mod_ptr->fd);
2573          dyn_mod_ptr->fd = NULL;
2574       }
2576       /*---------------------------------------------------------------------*/
2577       /* Detach loaded module object from the dynamic module object that     */
2578       /* created it, then throw away the dynamic module object.              */
2579       /*---------------------------------------------------------------------*/
2580       detach_loaded_module(dyn_mod_ptr);
2581       delete_DLIMP_Dynamic_Module(handle, &dyn_mod_ptr);
2582    }
2584    return local_file_handle;
2587 /*****************************************************************************/
2588 /* DLOAD_load()                                                              */
2589 /*                                                                           */
2590 /*    Dynamically load the specified file and return a file handle for the   */
2591 /*    loaded file.  If the load fails, this function will return a value of  */
2592 /*    zero (0) for the file handle.                                          */
2593 /*                                                                           */
2594 /*    The core loader must have read access to the file pointed to by fd.    */
2595 /*                                                                           */
2596 /*****************************************************************************/
2597 int32_t DLOAD_load(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd, int argc,
2598                    char** argv)
2600     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2601     DLIMP_Dynamic_Module *dyn_module = new_DLIMP_Dynamic_Module(fd);
2603     if (!dyn_module)
2604         return 0;
2606 #if LOADER_DEBUG
2607    /*------------------------------------------------------------------------*/
2608    /* Spit out some loader progress information when we begin loading an     */
2609    /* object.                                                                */
2610    /*------------------------------------------------------------------------*/
2611    if (debugging_on) DLIF_trace("Loading file...\n");
2612 #endif
2614    /*------------------------------------------------------------------------*/
2615    /* If no access to a program was provided, there is nothing to do.        */
2616    /*------------------------------------------------------------------------*/
2617    if (!fd)
2618    {
2619       DLIF_error(DLET_FILE, "Missing file specification.\n");
2620       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2621       return 0;
2622    }
2624    /*------------------------------------------------------------------------*/
2625    /* Read file headers and dynamic information into dynamic module.         */
2626    /*------------------------------------------------------------------------*/
2627    if (!dload_headers(handle, fd, dyn_module)) {
2628       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2629       return 0;
2630    }
2632    /*------------------------------------------------------------------------*/
2633    /* Find the dynamic segment, if there is one, and read dynamic            */
2634    /* information from the ELF object file into the dynamic module data      */
2635    /* structure associated with this file.                                   */
2636    /*------------------------------------------------------------------------*/
2637    if (!dload_dynamic_segment(handle, fd, dyn_module)) {
2638       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2639       return 0;
2640    }
2642    /*------------------------------------------------------------------------*/
2643    /* ??? We currently don't have a way of finding the .args section.  So    */
2644    /*    we are hard-wiring the address of the .args section.  The proposed  */
2645    /*    solution for this problem is to invent a special segment type or    */
2646    /*    dynamic tag(s) that identify the location and size of the .args     */
2647    /*    section for the dynamic loader.                                     */
2648    /*------------------------------------------------------------------------*/
2649    /*HACK ---> */dyn_module->c_args = (uint8_t*)(0x02204000); /* <--- HACK*/
2651    /*------------------------------------------------------------------------*/
2652    /* Record argc and argv pointers with the dynamic module record.          */
2653    /*------------------------------------------------------------------------*/
2654    dyn_module->argc = argc;
2655    dyn_module->argv = argv;
2656    if (dyn_module->name == NULL) {
2657       dyn_module->name = DLIF_malloc(sizeof(char));
2658       if(dyn_module->name)
2659          *dyn_module->name = '\0';
2660       else {
2661          delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2662          return 0;
2663       }
2664    }
2666    /*------------------------------------------------------------------------*/
2667    /* Perform sanity checking on the read-in ELF file.                       */
2668    /*------------------------------------------------------------------------*/
2669    if (!is_valid_elf_object_file(fd, dyn_module))
2670    {
2671       DLIF_error(DLET_FILE, "Attempt to load invalid ELF file, '%s'.\n",
2672                     dyn_module->name);
2673       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2674       return 0;
2675    }
2677 #if LOADER_DEBUG && LOADER_PROFILE
2678    /*------------------------------------------------------------------------*/
2679    /* Stop clock on initialization of ELF file information.  Start clock on  */
2680    /* initialization of ELF module.                                          */
2681    /*------------------------------------------------------------------------*/
2682    if (debugging_on || profiling_on)
2683    {
2684       DLIF_trace("Finished dload_dynamic_segment.\n");
2685       if (profiling_on)
2686       {
2687          profile_stop_clock();
2688          DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
2689       }
2690    }
2691 #endif
2693    if (!process_section_table(fd, dyn_module)) {
2694       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2695       return 0;
2696    }
2698    /*------------------------------------------------------------------------*/
2699    /* Initialize internal ELF module and segment structures.  Sets           */
2700    /* loaded_module in *dyn_module.  This also deals with assigning a file   */
2701    /* handle and bumping file handle counter.                                */
2702    /*------------------------------------------------------------------------*/
2703    initialize_loaded_module(handle, dyn_module);
2705    /*------------------------------------------------------------------------*/
2706    /* Append Module structure to loaded object list.                         */
2707    /*------------------------------------------------------------------------*/
2708    loaded_module_ptr_enqueue(&pHandle->DLIMP_loaded_objects,
2709                              dyn_module->loaded_module);
2711    /*------------------------------------------------------------------------*/
2712    /* Support static loading as special case.                                */
2713    /*------------------------------------------------------------------------*/
2714    if (!dyn_module->relocatable)
2715       return dload_static_executable(handle, fd, dyn_module);
2717    /*------------------------------------------------------------------------*/
2718    /* Get space & address for segments, and offset symbols and program       */
2719    /* header table to reflect the relocated address.  Also offset the        */
2720    /* addresses in the internal Segment structures used by the Module        */
2721    /* structure.  Note that this step needs to be performed prior and in     */
2722    /* addition to the relocation entry processing.                           */
2723    /*------------------------------------------------------------------------*/
2724    if (!allocate_dynamic_segments_and_relocate_symbols(handle, fd, dyn_module)) {
2725       loaded_module_ptr_remove(&pHandle->DLIMP_loaded_objects,
2726                                dyn_module->loaded_module);
2727       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2728       return 0;
2729    }
2730    /*------------------------------------------------------------------------*/
2731    /* Execute any user defined pre-initialization functions that may be      */
2732    /* associated with a dynamic executable module.                           */
2733    /*------------------------------------------------------------------------*/
2734    if (dyn_module->fhdr.e_type == ET_EXEC)
2735       execute_module_pre_initialization(handle, dyn_module);
2737    /*------------------------------------------------------------------------*/
2738    /* Append current ELF file to list of objects currently loading.          */
2739    /* This is used to detect circular dependencies while we are processing   */
2740    /* the dependents of this file.                                           */
2741    /*------------------------------------------------------------------------*/
2742    AL_append(&pHandle->DLIMP_module_dependency_list, &dyn_module->name);
2744    /*------------------------------------------------------------------------*/
2745    /* Push this dynamic module object onto the dependency stack.             */
2746    /* All of the modules on the stack will get relocated after all of the    */
2747    /* dependent files have been loaded and allocated.                        */
2748    /*------------------------------------------------------------------------*/
2749    dynamic_module_ptr_push(&pHandle->DLIMP_dependency_stack, dyn_module);
2751    /*------------------------------------------------------------------------*/
2752    /* If this object file uses the DSBT model, then register a DSBT index    */
2753    /* request with the client's DSBT support management.                     */
2754    /*------------------------------------------------------------------------*/
2755    if (is_dsbt_module(dyn_module) &&
2756       !DLIF_register_dsbt_index_request(handle,
2757                                         dyn_module->name,
2758                                         dyn_module->loaded_module->file_handle,
2759                                         dyn_module->dsbt_index)) {
2760       dynamic_module_ptr_pop(&pHandle->DLIMP_dependency_stack);
2761       loaded_module_ptr_remove(&pHandle->DLIMP_loaded_objects,
2762                                   dyn_module->loaded_module);
2763       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2764       return 0;
2765    }
2767    /*------------------------------------------------------------------------*/
2768    /* Load this ELF file's dependents (all files on its DT_NEEDED list).     */
2769    /* Do not process relocation entries for anyone in the dependency graph   */
2770    /* until all modules in the graph are loaded and allocated.               */
2771    /*------------------------------------------------------------------------*/
2772    if (!dload_and_allocate_dependencies(handle, dyn_module)) {
2773       dynamic_module_ptr_pop(&pHandle->DLIMP_dependency_stack);
2774       loaded_module_ptr_remove(&pHandle->DLIMP_loaded_objects,
2775                                   dyn_module->loaded_module);
2776       delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2777       return 0;
2778    }
2780    /*------------------------------------------------------------------------*/
2781    /* Remove the current ELF file from the list of files that are in the     */
2782    /* process of loading.                                                    */
2783    /*------------------------------------------------------------------------*/
2784    pHandle->DLIMP_module_dependency_list.size--;
2786    /*------------------------------------------------------------------------*/
2787    /* __c_args__ points to the beginning of the .args section, if there is   */
2788    /* one.  Record this pointer in the ELF file internal data object.        */
2789    /*------------------------------------------------------------------------*/
2790    DLSYM_lookup_local_symtab("__c_args__", dyn_module->symtab,
2791                              dyn_module->symnum,
2792                              (Elf32_Addr *)&dyn_module->c_args);
2795    return relocate_dependency_graph_modules(handle, fd, dyn_module);
2798 BOOL DLOAD_get_entry_names_info(DLOAD_HANDLE handle,
2799                                 uint32_t file_handle,
2800                                 int32_t *entry_pt_cnt,
2801                                 int32_t *entry_pt_max_name_len)
2803    /*------------------------------------------------------------------------*/
2804    /* Spin through list of loaded files until we find the file handle we     */
2805    /* are looking for.  Then build a list of entry points from that file's   */
2806    /* symbol table.                                                          */
2807    /*------------------------------------------------------------------------*/
2808    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2809    loaded_module_ptr_Queue_Node* ptr;
2810    for (ptr = pHandle->DLIMP_loaded_objects.front_ptr;
2811        ptr != NULL;
2812        ptr = ptr->next_ptr)
2813    {
2814       if (ptr->value->file_handle == file_handle)
2815       {
2816          DLIMP_Loaded_Module *module = ptr->value;
2817          struct Elf32_Sym *symtab;
2818          int i;
2820          /*------------------------------------------------------------------*/
2821          /* Any symbol in our file's symbol table is considered a valid      */
2822          /* entry point.                                                     */
2823          /*------------------------------------------------------------------*/
2824          symtab = (struct Elf32_Sym*)module->gsymtab;
2825          *entry_pt_cnt = module->gsymnum;
2826          *entry_pt_max_name_len = 0;
2827          for (i = 0; i < module->gsymnum; i++)
2828          {
2829             const char *sym_name = (const char *)symtab[i].st_name;
2831             if ((strlen(sym_name) + 1) > *entry_pt_max_name_len)
2832                *entry_pt_max_name_len = strlen(sym_name) + 1;
2833          }
2835          return TRUE;
2836       }
2837    }
2839    /*------------------------------------------------------------------------*/
2840    /* We didn't find the file we were looking for, return false.             */
2841    /*------------------------------------------------------------------------*/
2842    return FALSE;
2845 /*****************************************************************************/
2846 /* DLOAD_get_entry_names()                                                   */
2847 /*                                                                           */
2848 /*    Build a list of entry point names for a loaded object.  Currently,     */
2849 /*    any global symbol in the module is considered a valid entry point      */
2850 /*    regardless of whether it is defined in code or associated with a       */
2851 /*    data object.  We would need to process the content of the symbol       */
2852 /*    table entry or its debug information to determine whether it is a      */
2853 /*    valid entry point or not.                                              */
2854 /*                                                                           */
2855 /*****************************************************************************/
2856 BOOL DLOAD_get_entry_names(DLOAD_HANDLE handle,
2857                            uint32_t file_handle,
2858                            int32_t *entry_pt_cnt,
2859                            char ***entry_pt_names)
2861    /*------------------------------------------------------------------------*/
2862    /* Spin through list of loaded files until we find the file handle we     */
2863    /* are looking for.  Then build a list of entry points from that file's   */
2864    /* symbol table.                                                          */
2865    /*------------------------------------------------------------------------*/
2866    char **names;
2867    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2868    loaded_module_ptr_Queue_Node* ptr;
2869    for (ptr = pHandle->DLIMP_loaded_objects.front_ptr;
2870         ptr != NULL;
2871         ptr = ptr->next_ptr)
2872    {
2873       if (ptr->value->file_handle == file_handle)
2874       {
2875          DLIMP_Loaded_Module *module = ptr->value;
2876          struct Elf32_Sym *symtab;
2877          int i;
2879          /*------------------------------------------------------------------*/
2880          /* Any symbol in our file's symbol table is considered a valid      */
2881          /* entry point.                                                     */
2882          /*------------------------------------------------------------------*/
2883          symtab = (struct Elf32_Sym*)module->gsymtab;
2884          if (*entry_pt_cnt < module->gsymnum) {
2885             DLIF_error(DLET_MEMORY, "There are %d entry points, "
2886                        "only %d spaces provided.\n",
2887                        module->gsymnum,*entry_pt_cnt);
2888             return FALSE;
2889          }
2890          names = *entry_pt_names;
2891          for (i = 0; i < module->gsymnum; i++)
2892          {
2893             const char *sym_name = (const char *)symtab[i].st_name;
2894             strcpy(names[i],sym_name);
2895          }
2897          return TRUE;
2898       }
2899    }
2901    /*------------------------------------------------------------------------*/
2902    /* We didn't find the file we were looking for, return false.             */
2903    /*------------------------------------------------------------------------*/
2904    return FALSE;
2907 /*****************************************************************************/
2908 /* DLOAD_get_entry_point()                                                   */
2909 /*                                                                           */
2910 /*    Given a file handle, return the entry point associated with that       */
2911 /*    module in the *sym_val output parameter.                               */
2912 /*                                                                           */
2913 /*****************************************************************************/
2914 BOOL DLOAD_get_entry_point(DLOAD_HANDLE handle, uint32_t file_handle,
2915                            TARGET_ADDRESS *sym_val)
2917    /*------------------------------------------------------------------------*/
2918    /* Spin through list of loaded files until we find the file handle we     */
2919    /* are looking for.  Then return the entry point address associated with  */
2920    /* that module.                                                           */
2921    /*------------------------------------------------------------------------*/
2922    loaded_module_ptr_Queue_Node* ptr;
2923    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2924    for (ptr = pHandle->DLIMP_loaded_objects.front_ptr;
2925         ptr != NULL;
2926         ptr = ptr->next_ptr)
2927       if (ptr->value->file_handle == file_handle)
2928       {
2929          *sym_val = (TARGET_ADDRESS)(ptr->value->entry_point);
2930          return TRUE;
2931       }
2933    /*------------------------------------------------------------------------*/
2934    /* We didn't find the file we were looking for, return false.             */
2935    /*------------------------------------------------------------------------*/
2936    return FALSE;
2939 /*****************************************************************************/
2940 /* DLOAD_query_symbol()                                                      */
2941 /*                                                                           */
2942 /*    Query the value of a global symbol from a specific file.  The value    */
2943 /*    result will be written to *sym_val.  The function returns TRUE if the  */
2944 /*    symbol was found, and FALSE if it wasn't.                              */
2945 /*                                                                           */
2946 /*****************************************************************************/
2947 BOOL DLOAD_query_symbol(DLOAD_HANDLE handle,