]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/interp/elf/dload.c
Bug fix for automatic file format detection
[keystone-rtos/ibl.git] / src / interp / elf / 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 #include <limits.h>
44 #include <inttypes.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <time.h>
50 #include "ewrap.h"
51 #include "elf32.h"
52 #include "dload.h"
53 #include "dload_api.h"
55 /* Eat printfs. */
56 #define printf mprintf
60 #if 0
62 #include "ArrayList.h"
63 #include "Queue.h"
65 #include "symtab.h"
66 #include "dload_endian.h"
67 #include "elf32.h"
68 #include "dload.h"
69 #include "relocate.h"
70 #include "dload_api.h"
72 #ifdef ARM_TARGET
73 #include "arm_dynamic.h"
74 #endif
76 #ifdef C60_TARGET
77 #include "c60_dynamic.h"
78 #endif
80 #endif
84 /*---------------------------------------------------------------------------*/
85 /* Identify target supported by this implementation of the core loader.      */
86 /*---------------------------------------------------------------------------*/
87 int DLOAD_TARGET_MACHINE = DLOAD_DEFAULT_TARGET_MACHINE;
89 #if 0
90 /*---------------------------------------------------------------------------*/
91 /* Contains filenames (type const char*) the system is in the process of     */
92 /* loading.  Used to detect cycles in incorrectly compiled ELF binaries.     */
93 /*---------------------------------------------------------------------------*/
94 Array_List DLIMP_module_dependency_list;
96 /*---------------------------------------------------------------------------*/
97 /* Contains objects (type DLIMP_Loaded_Module) that the system has loaded into     */
98 /* target memory.                                                            */
99 /*---------------------------------------------------------------------------*/
100 TYPE_QUEUE_IMPLEMENTATION(DLIMP_Loaded_Module*, loaded_module_ptr)
101 loaded_module_ptr_Queue DLIMP_loaded_objects;
103 /*---------------------------------------------------------------------------*/
104 /* Dependency Graph Queue - FIFO queue of dynamic modules that are loaded    */
105 /* when client asks to load a dynamic executable or library. Note that       */
106 /* dependents that have already been loaded with another module will not     */
107 /* appear on this queue.                                                     */
108 /*---------------------------------------------------------------------------*/
109 TYPE_STACK_IMPLEMENTATION(DLIMP_Dynamic_Module*, dynamic_module_ptr)
110 dynamic_module_ptr_Stack DLIMP_dependency_stack;
112 #endif
114 /*---------------------------------------------------------------------------*/
115 /* Counter for generating unique IDs for file handles.                       */
116 /*   NOTE: File handle is assigned sequencially but is never reclaimed       */
117 /*         when the modules are unloaded. It is conceivable that a loader    */
118 /*         running for a long time and loading and unloading modules could   */
119 /*         wrap-around. The loader generates error in this case.             */
120 /*---------------------------------------------------------------------------*/
121 static int32_t file_handle = 1;
123 /*---------------------------------------------------------------------------*/
124 /* Support for profiling performance of dynamic loader core.                 */
125 /*---------------------------------------------------------------------------*/
126 #if LOADER_DEBUG
127 static clock_t cycle0 = 0;
128 static clock_t cycle_end = 0;
129 #define profile_start_clock() (cycle0 = clock())
130 #define profile_stop_clock()  (cycle_end = clock())
131 #define profile_cycle_count() (cycle_end - cycle0)
132 #endif
135 #if 0
136 /*****************************************************************************/
137 /* DLIMP_get_first_dyntag()                                                  */
138 /*                                                                           */
139 /*    Return value for first tag entry in the given dynamic table whose      */
140 /*    tag type matches the given key.                                        */
141 /*                                                                           */
142 /*****************************************************************************/
143 uint32_t DLIMP_get_first_dyntag(int tag, struct Elf32_Dyn* dyn_table)
145    /*------------------------------------------------------------------------*/
146    /* Spin through dynamic segment looking for a specific dynamic tag.       */
147    /* Return the value associated with the tag, if the tag is found.         */
148    /*------------------------------------------------------------------------*/
149    struct Elf32_Dyn *dtp = dyn_table;
150    while (dtp->d_tag != DT_NULL)
151    {
152       if (dtp->d_tag == tag) return dtp->d_un.d_val;
153       else dtp++;
154    }
156    /*------------------------------------------------------------------------*/
157    /* Tag wasn't found, return a known bogus value for the tag.              */
158    /*------------------------------------------------------------------------*/
159    return INT_MAX;
162 #endif
164 #if 0
165 /*****************************************************************************/
166 /* dload_and_allocate_dependencies()                                         */
167 /*                                                                           */
168 /*    If not already loaded, load each dependent file identified in the      */
169 /*    dynamic segment with a DT_NEEDED tag.  Dependent files are listed in   */
170 /*    order and should be loaded in the same order that they appear in the   */
171 /*    dynamic segment.                                                       */
172 /*                                                                           */
173 /*****************************************************************************/
174 static BOOL dload_and_allocate_dependencies(DLIMP_Dynamic_Module *dyn_module)
176    /*------------------------------------------------------------------------*/
177    /* Spin through each dynamic tag entry in the dynamic segment.            */
178    /*------------------------------------------------------------------------*/
179    struct Elf32_Dyn* dyn_nugget = dyn_module->dyntab;
181 #if LOADER_DEBUG
182    if (debugging_on) 
183       printf("Starting dload_and_allocate_dependencies() for %s ...\n", 
184              dyn_module->name);
185 #endif
187    while(dyn_nugget->d_tag != DT_NULL)
188    {
189       /*---------------------------------------------------------------------*/
190       /* For each DT_NEEDED dynamic tag that we find in the dynamic segment, */
191       /* load the dependent file identified by the so_name value attached    */
192       /* to the DT_NEEDED dynamic tag.                                       */
193       /*---------------------------------------------------------------------*/
194       if (dyn_nugget->d_tag == DT_NEEDED)
195       {
196          loaded_module_ptr_Queue_Node* ptr;
198 #if LOADER_DEBUG
199          if (debugging_on)
200             printf("Found DT_NEEDED: %s\n", 
201                    dyn_module->strtab+dyn_nugget->d_un.d_val);
202 #endif
204          /*------------------------------------------------------------------*/
205          /* Find out if the file named by the DT_NEEDED tag has already      */
206          /* been loaded.  If it has, then we only have to bump the use count */
207          /* of the named dependent file.                                     */
208          /*------------------------------------------------------------------*/
209          for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL; 
210               ptr = ptr->next_ptr)
211          {
212             if (!strcmp(ptr->value->name,
213                                    dyn_module->strtab + dyn_nugget->d_un.d_val))
214             {
215                ptr->value->use_count++;
216                AL_append(&(dyn_module->loaded_module->dependencies),
217                                                 &(ptr->value->file_handle));
218                break;
219             }
220          }
222          /*------------------------------------------------------------------*/
223          /* If the named dependent file has not been loaded, then we ask the */
224          /* client to invoke a load of the dependent file on our behalf.     */ 
225          /*------------------------------------------------------------------*/
226          if (ptr == NULL)
227          {
228             int32_t dependent_handle = DLIF_load_dependent(dyn_module->strtab + 
229                                                        dyn_nugget->d_un.d_val);
230             AL_append(&(dyn_module->loaded_module->dependencies), 
231                                                             &dependent_handle);
232             if (dependent_handle == 0) return FALSE;
233          }
234       }
236       dyn_nugget++;
237    }
239 #if LOADER_DEBUG
240    if (debugging_on) 
241       printf("Finished dload_and_allocate_dependencies() for %s\n", 
242              dyn_module->name);
243 #endif
245    return TRUE;
248 #endif
250 /*****************************************************************************/
251 /* load_object()                                                             */
252 /*                                                                           */
253 /*    Finish the process of loading an object file.                          */
254 /*                                                                           */
255 /*****************************************************************************/
256 static int load_object(LOADER_FILE_DESC *fd, DLIMP_Dynamic_Module *dyn_module)
258    /*------------------------------------------------------------------------*/
259    /* With the dynamic loader already running on the target, we are able to  */
260    /* relocate directly into target memory, so there is nothing more to be   */
261    /* done (at least in the bare-metal dynamic linking ABI model).           */
262    /*------------------------------------------------------------------------*/
263    return 1;
266 #if 1
267 /*****************************************************************************/
268 /* initialize_loaded_module()                                                */
269 /*                                                                           */
270 /*    Initialize DLIMP_Loaded_Module internal data object associated with a  */
271 /*    dynamic module.  This function will also set up a queue of             */
272 /*    DLIMP_Loaded_Segment(s) associated with the loaded module.             */
273 /*    This function is called as we are getting ready to actually load the   */
274 /*    object file contents into target memory.  Each segment will get a      */
275 /*    target memory request that it can use to ask the client for target     */
276 /*    memory space.  This function will also assign a file handle to the     */
277 /*    loaded module.                                                         */
278 /*                                                                           */
279 /*---------------------------------------------------------------------------*/
280 /*                                                                           */
281 /* In applications that use the DSBT model, this function will also need to  */
282 /* negotiate the module's DSBT index with the client.                        */
283 /*                                                                           */
284 /*****************************************************************************/
285 static void initialize_loaded_module(DLIMP_Dynamic_Module *dyn_module)
287    int i;
289    /*------------------------------------------------------------------------*/
290    /* Allocate a DLIMP_Loaded_Module data structure for the specified ELF    */
291    /* file and assign a file handle for it (bumping the file handle counter  */
292    /* as we go).                                                             */
293    /*------------------------------------------------------------------------*/
294    DLIMP_Loaded_Module *loaded_module =
295           dyn_module->loaded_module = DLIF_malloc(sizeof(DLIMP_Loaded_Module));
297 #if LOADER_DEBUG || LOADER_PROFILE
298    /*------------------------------------------------------------------------*/
299    /* Start clock on initialization of loaded module object.                 */
300    /*------------------------------------------------------------------------*/
301    if (debugging_on || profiling_on)
302    {
303       printf("Starting initialize_loaded_module() ...\n");
304       if (profiling_on) profile_start_clock();
305    }
306 #endif
308    loaded_module->name = DLIF_malloc(strlen(dyn_module->name) + 1);
309    strcpy(loaded_module->name, dyn_module->name);
311    loaded_module->file_handle = file_handle++;
312    loaded_module->direct_dependent_only = dyn_module->direct_dependent_only;
313    loaded_module->use_count = 1;
315    /*------------------------------------------------------------------------*/
316    /* In case we wrapped around the file handle, return error.               */
317    /*------------------------------------------------------------------------*/
318    if (file_handle == 0)
319       DLIF_error(DLET_MISC, "DLOAD File handle overflowed.\n");
321    /*------------------------------------------------------------------------*/
322    /* Initially the loaded module does not have access to its global         */
323    /* symbols.  These need to be copied from the dynamic module (see call    */
324    /* to DLSYM_copy_globals() below).                                        */
325    /*                                                                        */
326    /* THESE INITIALIZATIONS SHOULD BE MOVED TO AN INIT ROUTINE FOR THE       */
327    /* LOADED MODULE                                                          */
328    /*------------------------------------------------------------------------*/
329    loaded_module->gsymtab = NULL;
330    loaded_module->gstrtab = NULL;
331    loaded_module->gsymnum = loaded_module->gstrsz = 0;
333    /*------------------------------------------------------------------------*/
334    /* Initialize the Array_List of dependencies.                             */
335    /*------------------------------------------------------------------------*/
336    AL_initialize(&(loaded_module->dependencies), sizeof(int), 1);
338    if (dyn_module->symtab)
339       DLSYM_copy_globals(dyn_module);
340      
341    /*------------------------------------------------------------------------*/
342    /* Initialize the module loaded segments Array_List.                      */
343    /*------------------------------------------------------------------------*/
344    AL_initialize(&(loaded_module->loaded_segments),
345                  sizeof(DLIMP_Loaded_Segment), dyn_module->phnum);
347    /*------------------------------------------------------------------------*/
348    /* Spin thru segment headers and process each load segment encountered.   */
349    /*------------------------------------------------------------------------*/
350    for (i = 0; i < dyn_module->phnum; i++)
351       if (dyn_module->phdr[i].p_type == PT_LOAD)
352       {
353          /*------------------------------------------------------------------*/
354          /* Note that this is parallel to and does not supplant the ELF      */
355          /* phdr tables.                                                     */
356          /*------------------------------------------------------------------*/
357          DLIMP_Loaded_Segment seg;
358          seg.obj_desc = DLIF_malloc(sizeof(struct DLOAD_MEMORY_SEGMENT));
359          seg.phdr.p_vaddr = dyn_module->phdr[i].p_vaddr;
360          seg.phdr.p_offset = dyn_module->phdr[i].p_offset;
361          seg.obj_desc->target_page = 0; /*not used*/
362          seg.modified = 0;
363          seg.phdr.p_filesz = seg.obj_desc->objsz_in_bytes 
364                            = dyn_module->phdr[i].p_filesz;
365          seg.phdr.p_memsz = seg.obj_desc->memsz_in_bytes 
366                           = dyn_module->phdr[i].p_memsz;
367          seg.phdr.p_align = dyn_module->phdr[i].p_align;
368          seg.phdr.p_flags = dyn_module->phdr[i].p_flags;
369          seg.reloc_offset = 0;
370          AL_append(&(loaded_module->loaded_segments), &seg);
371       }
373    /*------------------------------------------------------------------------*/
374    /* Initialize the DSO termination information for this module.            */
375    /* It will be copied over from the enclosing dyn_module object when       */
376    /* placement is completed and dyn_module's local copy of the dynamic      */
377    /* table is updated.                                                      */
378    /*------------------------------------------------------------------------*/
379    loaded_module->fini_array = NULL;
380    loaded_module->fini_arraysz = 0;
381    loaded_module->fini = NULL;
383 #if LOADER_DEBUG || LOADER_PROFILE
384    if (debugging_on || profiling_on)
385    {
386       printf("Finished initialize_loaded_module()\n");
387       if (profiling_on)
388       {
389          profile_stop_clock();
390          printf("Took %d cycles.\n", profile_cycle_count());
391       }
392    }
393 #endif
396 #endif
398 /*****************************************************************************/
399 /* load_static_segment()                                                     */
400 /*                                                                           */
401 /*    The core dynamic loader requires that a statically linked executable   */
402 /*    be placed in target memory at the location that was determined during  */
403 /*    the static link that created the executable.  Failure to get the       */
404 /*    required target memory where the static executable is to be loaded     */
405 /*    will cause the dynamic loader to emit an error and abort the load.     */
406 /*                                                                           */
407 /*****************************************************************************/
408 static BOOL load_static_segment(LOADER_FILE_DESC *fd, 
409                                 DLIMP_Dynamic_Module *dyn_module)
411    int i;
412    DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*) 
413                               (dyn_module->loaded_module->loaded_segments.buf);
415    /*------------------------------------------------------------------------*/
416    /* For each segment in the loaded module, build up a target memory        */
417    /* request for the segment, get rights to target memory where we want     */
418    /* to load the segment from the client, then get the client to write the  */
419    /* segment contents out to target memory to the appropriate address.      */
420    /*------------------------------------------------------------------------*/
421    for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
422    {
423       struct DLOAD_MEMORY_REQUEST targ_req;
424       seg[i].obj_desc->target_page = 0;
425       targ_req.flags = 0;
427       /*---------------------------------------------------------------------*/
428       /* This is a static executable.  DLIF_allocate should give us the      */
429       /* address we ask for or fail.                                         */
430       /*---------------------------------------------------------------------*/
431       if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
433       targ_req.align = seg[i].phdr.p_align;
434       seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
435       targ_req.flags &= ~DLOAD_SF_relocatable;
436       targ_req.fp = fd;
437       targ_req.segment = seg[i].obj_desc;
438       targ_req.offset = seg[i].phdr.p_offset;
439       targ_req.flip_endian = dyn_module->wrong_endian;
441       /*---------------------------------------------------------------------*/
442       /* Ask the client side of the dynamic loader to allocate target memory */
443       /* for this segment to be loaded into.                                 */
444       /*---------------------------------------------------------------------*/
445       if (!DLIF_allocate(&targ_req)) return FALSE;
447       /*---------------------------------------------------------------------*/
448       /* If there is any initialized data in the segment, we'll first write  */
449       /* it into a host writable buffer (DLIF_copy()) and then flush it to   */
450       /* target memory.                                                      */
451       /*---------------------------------------------------------------------*/
452       if (seg[i].phdr.p_filesz)
453       {
454          DLIF_copy(&targ_req);
455          DLIF_write(&targ_req);
456       }
457    }
459    return TRUE;
462 #if 0
463 /*****************************************************************************/
464 /* relocate_target_dynamic_tag_info()                                        */
465 /*                                                                           */
466 /*    Update a target specific dynamic tag value that happens to be a        */
467 /*    virtual address of a section. Returns TRUE if the tag was updated or   */
468 /*    is not a virtual address and FALSE if it was not successfully updated  */
469 /*    or was not recognized.                                                 */
470 /*****************************************************************************/
471 static BOOL relocate_target_dynamic_tag_info(DLIMP_Dynamic_Module *dyn_module, 
472                                              int i)
474 #ifdef ARM_TARGET
475    if (is_arm_module(&dyn_module->fhdr))
476        return DLDYN_arm_relocate_dynamic_tag_info(dyn_module, i);
477 #endif
479 #ifdef C60_TARGET      
480    if (is_c60_module(&dyn_module->fhdr))
481       return DLDYN_c60_relocate_dynamic_tag_info(dyn_module, i);
482 #endif
484    return FALSE;
487 #endif
490 #if 0
491 /*****************************************************************************/
492 /* DLIMP_update_dyntag_section_address()                                     */
493 /*                                                                           */
494 /*    Given the index of a dynamic tag which we happen to know points to a   */
495 /*    section address, find the program header table entry associated with   */
496 /*    the specified address and update the tag value with the real address   */
497 /*    of the section.                                                        */
498 /*                                                                           */
499 /*****************************************************************************/
500 BOOL DLIMP_update_dyntag_section_address(DLIMP_Dynamic_Module *dyn_module, 
501                                          int32_t i)
503    int j;
504    DLIMP_Loaded_Segment *seg = (DLIMP_Loaded_Segment *)
505                               (dyn_module->loaded_module->loaded_segments.buf);
506    for (j = 0; j < dyn_module->loaded_module->loaded_segments.size; j++)
507    {
508       if ((dyn_module->dyntab[i].d_un.d_ptr >= seg[j].input_vaddr) &&
509           (dyn_module->dyntab[i].d_un.d_ptr < 
510            (seg[j].input_vaddr + seg[j].phdr.p_memsz)))
511       {
512          dyn_module->dyntab[i].d_un.d_ptr += 
513                                     (seg[j].phdr.p_vaddr - seg[j].input_vaddr);
514          return TRUE;
515       }
516    }
518    return FALSE;
521 #endif
524 #if 0
525 /*****************************************************************************/
526 /* relocate_dynamic_tag_info()                                               */
527 /*                                                                           */
528 /*    Once segment allocation has been completed, we'll need to go through   */
529 /*    the dynamic table and update any tag values that happen to be virtual  */
530 /*    addresses of segments (DT_C6000_DSBT_BASE, for example).               */
531 /*                                                                           */
532 /*****************************************************************************/
533 static BOOL relocate_dynamic_tag_info(LOADER_FILE_DESC *fd,
534                                       DLIMP_Dynamic_Module *dyn_module)
536    /*------------------------------------------------------------------------*/
537    /* Spin through dynamic table loking for tags that have a value which is  */
538    /* the virtual address of a section. After the sections are allocated,    */
539    /* we'll need to update these values with the new address of the section. */
540    /*------------------------------------------------------------------------*/
541    int i;
542    for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
543    {
544       switch (dyn_module->dyntab[i].d_tag)
545       {
546          /*------------------------------------------------------------------*/
547          /* Only tag values that are virtual addresses will be affected.     */
548          /*------------------------------------------------------------------*/
549          case DT_NEEDED: 
550          case DT_PLTRELSZ:
551          case DT_HASH:
552          case DT_STRTAB:
553          case DT_SYMTAB: 
554          case DT_RELA:
555          case DT_RELASZ:
556          case DT_RELAENT:
557          case DT_STRSZ:
558          case DT_SYMENT:
559          case DT_SONAME:
560          case DT_RPATH:
561          case DT_SYMBOLIC:
562          case DT_REL:
563          case DT_RELSZ:
564          case DT_RELENT:
565          case DT_PLTREL:
566          case DT_DEBUG:
567          case DT_TEXTREL:
568          case DT_BIND_NOW:
569          case DT_INIT_ARRAYSZ:
570          case DT_RUNPATH:
571          case DT_FLAGS:
572          case DT_PREINIT_ARRAYSZ:
573             continue;
575          /*------------------------------------------------------------------*/
576          /* NOTE!!!                                                          */
577          /* case DT_ENCODING:  -- tag type has same "id" as DT_PREINIT_ARRAY */
578          /*------------------------------------------------------------------*/
580          /*------------------------------------------------------------------*/
581          /* This is a generic dynamic tag whose value is a virtual address   */
582          /* of a section. It needs to be relocated to the section's actual   */
583          /* address in target memory.                                        */
584          /*------------------------------------------------------------------*/
585          case DT_PREINIT_ARRAY:
586          case DT_INIT:
587          case DT_INIT_ARRAY:
588             if (!DLIMP_update_dyntag_section_address(dyn_module, i))
589                return FALSE;
591             continue;
593          /*------------------------------------------------------------------*/
594          /* Once we have resolved the actual address of termination function */
595          /* sections, we need to copy their addresses over to the loaded     */
596          /* module object (dyn_module will be deleted before we get to       */
597          /* unloading the module).                                           */
598          /*------------------------------------------------------------------*/
599          case DT_FINI_ARRAY:
600          case DT_FINI:
601             if (!DLIMP_update_dyntag_section_address(dyn_module, i))
602                return FALSE;
604             if (dyn_module->dyntab[i].d_tag == DT_FINI)
605                dyn_module->loaded_module->fini = 
606                                               dyn_module->dyntab[i].d_un.d_ptr;
607             else
608                dyn_module->loaded_module->fini_array = 
609                                               dyn_module->dyntab[i].d_un.d_ptr;
611             continue;
613          case DT_FINI_ARRAYSZ:
614             dyn_module->loaded_module->fini_arraysz = 
615                                               dyn_module->dyntab[i].d_un.d_val;
616             continue;
618          /*------------------------------------------------------------------*/
619          /* Is this a virtual address???                                     */
620          /*------------------------------------------------------------------*/
621          case DT_JMPREL: /* is this a virtual address??? */
622             continue;
624          /*------------------------------------------------------------------*/
625          /* The remaining dynamic tag types should be target specific. If    */
626          /* something generic slips through to here, then the handler for    */
627          /* relocating target specific dynamic tags should fail.             */
628          /*------------------------------------------------------------------*/
629          default:
630             if (!relocate_target_dynamic_tag_info(dyn_module, i))
631                return FALSE;
632       }
633    }
635    /*------------------------------------------------------------------------*/
636    /* We've gotten through all of the dynamic table without incident.        */
637    /* All dynamic tag values that were virtual section addresses should have */
638    /* been updated with the final address of the section that they point to. */
639    /*------------------------------------------------------------------------*/
640    return TRUE;
643 #endif
646 #if 0
647 /*****************************************************************************/
648 /* allocate_dynamic_segments_and relocate_symbols()                          */
649 /*                                                                           */
650 /*    Allocate target memory for each segment in this module, getting a      */
651 /*    host-accessible space to copy the content of each segment into.  Then  */
652 /*    update the symbol table and program header table to reflect the new    */
653 /*    target address for each segment.  Processing of the dynamic relocation */
654 /*    entries will wait until all dependent files have been loaded and       */
655 /*    allocated into target memory.                                          */
656 /*                                                                           */
657 /*---------------------------------------------------------------------------*/
658 /*                                                                           */
659 /* The relocation entries in the ELF file do not handle the necessary        */
660 /* adjustments to the memory addresses in the program header or symbol       */
661 /* tables.  These must be done manually.                                     */
662 /*                                                                           */
663 /* This is harder for us than for most dynamic loaders, because we have to   */
664 /* work in environments without virtual memory and thus where the offsets    */
665 /* between segments in memory may be different than they were in the file.   */
666 /* So, even though a dynamic loader usually only has to adjust all the       */
667 /* segments by a single fixed offset, we need to offset the symbols and      */
668 /* program header addresses segment by segment.  This job is done by the     */
669 /* function below.                                                           */
670 /*                                                                           */
671 /*****************************************************************************/
672 static BOOL allocate_dynamic_segments_and_relocate_symbols
673                                              (LOADER_FILE_DESC *fd,
674                                               DLIMP_Dynamic_Module *dyn_module)
676    int i,j;
677    DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
678                              (dyn_module->loaded_module->loaded_segments.buf);
679    struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
681 #if LOADER_DEBUG || LOADER_PROFILE
682    if (debugging_on || profiling_on)
683    {
684       printf("Dynamic executable found.\n"
685              "Starting allocate_dynamic_segments_and_relocate_symbols() ...\n");
686       if (profiling_on) profile_start_clock();
687    }
688 #endif
690    /*------------------------------------------------------------------------*/
691    /* Spin through the list of loaded segments from the current module.      */
692    /*------------------------------------------------------------------------*/
693    for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
694    {
695       /*--------------------------------------------------------------------*/
696       /* Allocate target memory for segment via client-provided target      */
697       /* memory API.                                                        */
698       /*--------------------------------------------------------------------*/
699       int32_t addr_offset;
700       struct DLOAD_MEMORY_REQUEST targ_req;
701       seg[i].obj_desc->target_page = 0;
702       targ_req.flags = 0;
703       if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
704       targ_req.align = 0x20;
705       seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
706       targ_req.flags |= DLOAD_SF_relocatable;
707       targ_req.fp = fd;
708       targ_req.segment = seg[i].obj_desc;
709       targ_req.offset = seg[i].phdr.p_offset;
710       targ_req.flip_endian = dyn_module->wrong_endian;
712       if (!DLIF_allocate(&targ_req))
713       {
714          DLIF_error(DLET_MEMORY, "DLIF allocation failure.\n");
715          return FALSE;
716       }
718       /*--------------------------------------------------------------------*/
719       /* Calculate the offset we need to adjust segment header and symbol   */
720       /* table addresses.                                                   */
721       /*--------------------------------------------------------------------*/
722       addr_offset = (int32_t)(seg[i].obj_desc->target_address) -
723                                                (int32_t)(seg[i].phdr.p_vaddr);
725 #if LOADER_DEBUG
726       if (debugging_on)
727       {
728          printf("Segment %d (at 0x%x, 0x%x bytes) relocated to 0x%x\n", i, 
729                 (int32_t)(seg[i].phdr.p_vaddr), 
730                 (int32_t)(seg[i].phdr.p_memsz), 
731                 (int32_t)(seg[i].obj_desc->target_address));
732          printf( "Addr Offset is 0x%x\n", addr_offset);
733       }
734 #endif
736       /*--------------------------------------------------------------------*/
737       /* Update program entry point if needed.  Need to replace to deal     */
738       /* with full ELF initialization routine.                              */
739       /*--------------------------------------------------------------------*/
740       if (dyn_module->relocate_entry_point && 
741           fhdr->e_entry >= (Elf32_Addr)(seg[i].phdr.p_vaddr) && 
742           fhdr->e_entry <
743             (Elf32_Addr)((uint8_t*)(seg[i].phdr.p_vaddr) + 
744                                              (uint32_t)(seg[i].phdr.p_memsz)))
745       {
746 #if LOADER_DEBUG
747          if (debugging_on)
748          {
749             printf("Entry point 0x%x relocated to 0x%x\n", 
750                    fhdr->e_entry, fhdr->e_entry + addr_offset);
751          }
752 #endif
753          fhdr->e_entry += addr_offset;
755          /*------------------------------------------------------------------*/
756          /* Mark the entry point as being relocated so we will not do it     */
757          /* again.                                                           */
758          /*------------------------------------------------------------------*/
759          dyn_module->relocate_entry_point = FALSE;
760       }
762       /*---------------------------------------------------------------------*/
763       /* Fix program header entries in segment and Elf32_Phdr structs.       */
764       /*---------------------------------------------------------------------*/
765       for (j = 0; j < fhdr->e_phnum; j++)
766          if (dyn_module->phdr[j].p_vaddr == (Elf32_Addr)seg[i].phdr.p_vaddr)
767          {
768             dyn_module->phdr[j].p_vaddr += addr_offset;
769             dyn_module->phdr[i].p_paddr += addr_offset;
770             break;
771          }
773       seg[i].input_vaddr = (Elf32_Addr)(seg[i].phdr.p_vaddr);
774       seg[i].phdr.p_vaddr += addr_offset;
776       /*---------------------------------------------------------------------*/
777       /* Great, now the hard part: fix offsets in symbols.  It would be nice */
778       /* if there were an easier way to deal with this.                      */
779       /*---------------------------------------------------------------------*/
780       {
781          struct Elf32_Sym *gsymtab = 
782                     ((struct Elf32_Sym*)(dyn_module->loaded_module->gsymtab));
783          Elf32_Addr segment_start = (Elf32_Addr)seg[i].phdr.p_vaddr;
784          Elf32_Addr segment_end   = (Elf32_Addr)seg[i].phdr.p_vaddr + 
785                                                            seg[i].phdr.p_memsz;
786          Elf32_Word global_index  = dyn_module->symnum - 
787                                     dyn_module->loaded_module->gsymnum;
788       
789          for (j = 0; j < dyn_module->symnum; j++)
790          {
791             /*---------------------------------------------------------------*/
792             /* Get the relocated symbol value.                               */
793             /*---------------------------------------------------------------*/
794             Elf32_Addr symval_adj = dyn_module->symtab[j].st_value + addr_offset;
796             /*---------------------------------------------------------------*/
797             /* If the symbol is defined in this segment, update the symbol   */
798             /* value and mark the symbol so that we don't relocate it again. */
799             /*---------------------------------------------------------------*/
800             if (symval_adj >= segment_start && symval_adj <  segment_end &&
801                 dyn_module->symtab[j].st_shndx != INT16_MAX)
802             {
803                dyn_module->symtab[j].st_value = symval_adj;
805                /*------------------------------------------------------------*/
806                /* The module symbol table only has the global symbols.       */
807                /*------------------------------------------------------------*/
808                if (j >= global_index)
809                   gsymtab[j-global_index].st_value = symval_adj;
811                /*------------------------------------------------------------*/
812                /* Mark the symbol as relocated.                              */
813                /*------------------------------------------------------------*/
814                dyn_module->symtab[j].st_shndx = INT16_MAX;
815             }
816          }
817       }
818    }
820    /*------------------------------------------------------------------------*/
821    /* Update dynamic tag information. Some dynamic tags have values which    */
822    /* are virtual addresses of sections. These values need to be updated     */
823    /* once segment allocation is completed and the new segment addresses are */
824    /* known.                                                                 */
825    /*------------------------------------------------------------------------*/
826    /* We should only traverse through the dynamic table once because we want */
827    /* to avoid the possibility of updating the same tag multiple times (an   */
828    /* error, if it happens).                                                 */
829    /*------------------------------------------------------------------------*/
830    if (!relocate_dynamic_tag_info(fd, dyn_module))
831    {
832       DLIF_error(DLET_MISC, "Failed dynamic table update.\n");
833       return FALSE;
834    }
836 #if LOADER_DEBUG || LOADER_PROFILE
837    if (debugging_on || profiling_on)
838    {
839       printf("Finished allocate_dynamic_segments_and_relocate_symbols()\n");
840       if (profiling_on)
841       {
842          profile_stop_clock();
843          printf("Took %d cycles.\n", profile_cycle_count());
844       }
845    }
846 #endif
848    return TRUE;
851 #endif
854 #if 0
855 /*****************************************************************************/
856 /* delete_DLIMP_Loaded_Module()                                              */
857 /*                                                                           */
858 /*    Free host memory associated with a DLIMP_Loaded_Module data structure  */
859 /*    and all of the DLIMP_Loaded_Segment objects that are associated with   */
860 /*    it.                                                                    */
861 /*                                                                           */
862 /*****************************************************************************/
863 static void delete_DLIMP_Loaded_Module(DLIMP_Loaded_Module **pplm)
865     DLIMP_Loaded_Module *loaded_module = *pplm;
866     DLIMP_Loaded_Segment *segments = (DLIMP_Loaded_Segment*)
867                                           (loaded_module->loaded_segments.buf);
869     /*-----------------------------------------------------------------------*/
870     /* Spin through the segments attached to this loaded module, freeing up  */
871     /* any target memory that was allocated by the client for the segment.   */
872     /*-----------------------------------------------------------------------*/
873     int i;
874     for (i = 0; i < loaded_module->loaded_segments.size; i++)
875     {
876         if (!DLIF_release(segments[i].obj_desc))
877             DLIF_error(DLET_MISC, "Failed call to DLIF_release!\n");;
878         DLIF_free(segments[i].obj_desc);
879     }
881     /*----------------------------------------------------------------------*/
882     /* Hacky way of indicating that the base image is no longer available.  */
883     /* WHHHHAAAAAAATTT!?!?!?!?!?!                                           */
884     /*----------------------------------------------------------------------*/
885     if (loaded_module->file_handle == DLIMP_application_handle)
886         DLIMP_application_handle = 0;
888     /*-----------------------------------------------------------------------*/
889     /* Free host heap memory that was allocated for the internal loaded      */
890     /* module data structure members.                                        */
891     /*-----------------------------------------------------------------------*/
892     if (loaded_module->name)    DLIF_free(loaded_module->name);
893     if (loaded_module->gsymtab) DLIF_free(loaded_module->gsymtab);
894     loaded_module->gsymnum = 0;
895     if (loaded_module->gstrtab) DLIF_free(loaded_module->gstrtab);
896     loaded_module->gstrsz = 0;
897     AL_destroy(&(loaded_module->loaded_segments));
898     AL_destroy(&(loaded_module->dependencies));
900     /*-----------------------------------------------------------------------*/
901     /* Finally, free the host memory for the loaded module object, then NULL */
902     /* the pointer that was passed in.                                       */
903     /*-----------------------------------------------------------------------*/
904     DLIF_free(loaded_module);
905     *pplm = NULL;
908 #endif
910 /*****************************************************************************/
911 /* new_DLIMP_Dynamic_Module()                                                */
912 /*                                                                           */
913 /*   Allocate a dynamic module data structure from host memory and           */
914 /*   initialize its members to their default values.                         */
915 /*                                                                           */
916 /*****************************************************************************/
917 static DLIMP_Dynamic_Module *new_DLIMP_Dynamic_Module(LOADER_FILE_DESC *fd)
919     /*-----------------------------------------------------------------------*/
920     /* Allocate space for dynamic module data structure from host memory.    */
921     /*-----------------------------------------------------------------------*/
922     DLIMP_Dynamic_Module *dyn_module = 
923              (DLIMP_Dynamic_Module *)DLIF_malloc(sizeof(DLIMP_Dynamic_Module));
925     if (!dyn_module)
926         return NULL;
928     /*-----------------------------------------------------------------------*/
929     /* Initialize data members of the new dynamic module data structure.     */
930     /*-----------------------------------------------------------------------*/
931     dyn_module->name = NULL;
932     dyn_module->fd = fd;
933     dyn_module->phdr = NULL;
934     dyn_module->phnum = 0;
935     dyn_module->strtab = NULL;
936     dyn_module->strsz = 0;
937     dyn_module->dyntab = NULL;
938     dyn_module->symtab = NULL;
939     dyn_module->symnum = 0;
940     dyn_module->gsymtab_offset = 0;
941     dyn_module->gstrtab_offset = 0;
942     dyn_module->c_args = NULL;
943     dyn_module->argc = 0;
944     dyn_module->argv = NULL;
945     dyn_module->loaded_module = NULL;
946     dyn_module->wrong_endian = 0;
947     dyn_module->direct_dependent_only = TRUE;
948     dyn_module->relocatable = FALSE;
949     dyn_module->relocate_entry_point = TRUE;
951     dyn_module->dsbt_size = 0;
952     dyn_module->dsbt_index = DSBT_INDEX_INVALID;
953     dyn_module->dsbt_base_tagidx = -1;
955     dyn_module->preinit_array_idx = -1;
956     dyn_module->preinit_arraysz = 0;
957     dyn_module->init_idx = -1;
958     dyn_module->init_array_idx = -1;
959     dyn_module->init_arraysz = 0;
961     return dyn_module;
964 /*****************************************************************************/
965 /* detach_loaded_module()                                                    */
966 /*                                                                           */
967 /*    Detach loaded module data structure from given dynamic module.  When   */
968 /*    an object file has been successfully loaded, the loader core will      */
969 /*    detach the loaded module data structure from the dynamic module data   */
970 /*    structure because the loaded module must continue to persist until is  */
971 /*    is actually unloaded from target memory.  If there is a problem with   */
972 /*    the load, then the host memory associated with the loaded module will  */
973 /*    be released as part of the destruction of the dynamic module.          */
974 /*                                                                           */
975 /*****************************************************************************/
976 static DLIMP_Loaded_Module *detach_loaded_module(DLIMP_Dynamic_Module *dyn_module)
978     if (dyn_module && dyn_module->loaded_module)
979     {
980         DLIMP_Loaded_Module *loaded_module = dyn_module->loaded_module;
981         dyn_module->loaded_module = NULL;
982         return loaded_module;
983     }
985     return NULL;
989 #if 0
990 /*****************************************************************************/
991 /* delete_DLIMP_Dynamic_Module()                                             */
992 /*                                                                           */
993 /*    Remove local copies of the string table, symbol table, program header  */
994 /*    table, and dynamic table.                                              */
995 /*                                                                           */
996 /*****************************************************************************/
997 static void delete_DLIMP_Dynamic_Module(DLIMP_Dynamic_Module **ppdm)
999    DLIMP_Dynamic_Module *dyn_module = NULL;
1000    
1001    if (!ppdm || (*ppdm == NULL))
1002    {
1003       DLIF_error(DLET_MISC, 
1004                  "Internal Error: invalid argument to dynamic module "
1005                  "destructor function; aborting loader\n");
1006       exit(1);
1007    }
1008    
1009    dyn_module = *ppdm;
1010    if (dyn_module->name)     DLIF_free(dyn_module->name);
1011    if (dyn_module->strtab)   DLIF_free(dyn_module->strtab);
1012    if (dyn_module->symtab)   DLIF_free(dyn_module->symtab);
1013    if (dyn_module->phdr)     DLIF_free(dyn_module->phdr);
1014    if (dyn_module->dyntab)   DLIF_free(dyn_module->dyntab);
1016    /*------------------------------------------------------------------------*/
1017    /* If we left the loaded module attached to the dynamic module, then      */
1018    /* something must have gone wrong with the load.  Remove the loaded       */
1019    /* module from the queue of loaded modules, if it is there.  Then free    */
1020    /* the host memory allocated to the loaded module and its segments.       */
1021    /*------------------------------------------------------------------------*/
1022    if (dyn_module->loaded_module != NULL)
1023       delete_DLIMP_Loaded_Module(&(dyn_module->loaded_module));
1025    /*------------------------------------------------------------------------*/
1026    /* Finally, free the host memory for this dynamic module object and NULL  */
1027    /* the pointer to the object.                                             */
1028    /*------------------------------------------------------------------------*/
1029    DLIF_free(dyn_module);
1030    *ppdm = NULL;
1033 #endif
1035 /*****************************************************************************/
1036 /* file_header_magic_number_is_valid()                                       */
1037 /*                                                                           */
1038 /*    Given an object file header, check the magic number to ensure that it  */
1039 /*    is an object file format that we recognize.  This implementation of    */
1040 /*    the dynamic loader core will handle ELF object file format.            */
1041 /*                                                                           */
1042 /*****************************************************************************/
1043 static BOOL file_header_magic_number_is_valid(struct Elf32_Ehdr* header)
1045    /*------------------------------------------------------------------------*/
1046    /* Check for correct ELF magic numbers in file header.                    */
1047    /*------------------------------------------------------------------------*/
1048    if (!header->e_ident[EI_MAG0] == ELFMAG0 ||
1049        !header->e_ident[EI_MAG1] == ELFMAG1 ||
1050        !header->e_ident[EI_MAG2] == ELFMAG2 ||
1051        !header->e_ident[EI_MAG3] == ELFMAG3)
1052    {
1053       DLIF_error(DLET_FILE, "Invalid ELF magic number.\n");
1054       return FALSE;
1055    }
1057    return TRUE;
1060 /*****************************************************************************/
1061 /* file_header_machine_is_valid()                                            */
1062 /*                                                                           */
1063 /*    Check if the machine specified in the file header is supported by the  */
1064 /*    loader.  If the loader was compiled with support for all targets,      */
1065 /*    the machine will be initially set to EM_NONE.  Once a module has been  */
1066 /*    loaded, all remaining modules must have the same machine value.        */
1067 /*****************************************************************************/
1068 static BOOL file_header_machine_is_valid(Elf32_Half e_machine)
1070    if (DLOAD_TARGET_MACHINE == EM_NONE)
1071       DLOAD_TARGET_MACHINE = e_machine;
1073    if (e_machine != DLOAD_TARGET_MACHINE)
1074       return FALSE;
1076    return TRUE;
1079 /*****************************************************************************/
1080 /* is_valid_elf_object_file()                                                */
1081 /*                                                                           */
1082 /*    Check file size against anticipated end location of string table,      */
1083 /*    symbol table, program header tables, etc.  If we anything untoward,    */
1084 /*    then we declare that the ELF file is corrupt and the load is aborted.  */
1085 /*                                                                           */
1086 /*****************************************************************************/
1087 static BOOL is_valid_elf_object_file(LOADER_FILE_DESC *fd, 
1088                                      DLIMP_Dynamic_Module *dyn_module)
1090    uint32_t fsz;
1091    int i;
1093    /*------------------------------------------------------------------------*/
1094    /* Get file size.                                                         */
1095    /*------------------------------------------------------------------------*/
1096    DLIF_fseek(fd, 0, LOADER_SEEK_END);
1097    fsz = DLIF_ftell(fd);
1099    /*------------------------------------------------------------------------*/
1100    /* Check for invalid table sizes (string table, symbol table, and         */
1101    /* program header tables).                                                */
1102    /*------------------------------------------------------------------------*/
1103    if (!((dyn_module->strsz < fsz) &&
1104          (dyn_module->symnum < fsz) &&
1105          (dyn_module->phnum * sizeof(struct Elf32_Phdr)) < fsz))
1106    {
1107       DLIF_error(DLET_FILE, "Invalid ELF table bounds.\n");
1108       return FALSE;
1109    }
1111    /*------------------------------------------------------------------------*/
1112    /* Check for null so_name string in file with dynamic information.        */
1113    /*------------------------------------------------------------------------*/
1114    if (dyn_module->dyntab && !strcmp(dyn_module->name, ""))
1115    {
1116       DLIF_error(DLET_MISC, "Dynamic file lacks SO_NAME identifier.\n");
1117       return FALSE;
1118    }
1120    /*------------------------------------------------------------------------*/
1121    /* Check for invalid program header information.                          */
1122    /*------------------------------------------------------------------------*/
1123    for (i = 0; i < dyn_module->phnum; i++)
1124    {
1125       struct Elf32_Phdr* phdr = dyn_module->phdr + i;
1127       /*---------------------------------------------------------------------*/
1128       /* Sanity check for relative sizes of filesz and memsz.                */
1129       /*---------------------------------------------------------------------*/
1130       if (!(phdr->p_type != PT_LOAD || phdr->p_filesz <= phdr->p_memsz))
1131       {
1132          DLIF_error(DLET_MISC, 
1133                     "Invalid file or memory size for segment %d.\n", i);
1134          return FALSE;
1135       }
1137       /*---------------------------------------------------------------------*/
1138       /* Check that segment file offset doesn't go off the end of the file.  */
1139       /*---------------------------------------------------------------------*/
1140       if (!(phdr->p_offset + phdr->p_filesz < fsz))
1141       {
1142          DLIF_error(DLET_FILE,
1143                   "File location of segment %d is past the end of file.\n", i);
1144          return FALSE;
1145       }
1146    }
1148    /*------------------------------------------------------------------------*/
1149    /* Check that a ET_DYN-type file is relocatable.                          */
1150    /*------------------------------------------------------------------------*/
1151    if (dyn_module->fhdr.e_type == ET_DYN && !dyn_module->symtab) return FALSE;
1153    /*------------------------------------------------------------------------*/
1154    /* All checks passed.                                                     */
1155    /*------------------------------------------------------------------------*/
1156    return TRUE;
1159 /*****************************************************************************/
1160 /* process_eiosabi()                                                         */
1161 /*                                                                           */
1162 /*   Check the EI_OSABI field to validate it and set any parameters based on */
1163 /*   it.                                                                     */
1164 /*****************************************************************************/
1165 static BOOL process_eiosabi(DLIMP_Dynamic_Module* dyn_module)
1167 #if ARM_TARGET
1168    if (is_arm_module(&dyn_module->fhdr))
1169       return DLDYN_arm_process_eiosabi(dyn_module);
1170 #endif
1172 #if C60_TARGET
1173    if (is_c60_module(&dyn_module->fhdr))
1174       return DLDYN_c60_process_eiosabi(dyn_module);
1175 #endif
1177    return FALSE;
1179 /*****************************************************************************/
1180 /* dload_file_header()                                                       */
1181 /*                                                                           */
1182 /*    Read ELF file header.  Store critical information in the provided      */
1183 /*    DLIMP_Dynamic_Module record.  Check file header for validity.          */
1184 /*                                                                           */
1185 /*****************************************************************************/
1186 static BOOL dload_file_header(LOADER_FILE_DESC *fd, 
1187                               DLIMP_Dynamic_Module *dyn_module)
1189    /*------------------------------------------------------------------------*/
1190    /* Read ELF file header from given input file.                            */
1191    /*------------------------------------------------------------------------*/
1192    DLIF_fread(&(dyn_module->fhdr), sizeof(struct Elf32_Ehdr), 1, fd);
1194    /*------------------------------------------------------------------------*/
1195    /* Determine target vs. host endian-ness.  Does header data need to be    */
1196    /* byte swapped?                                                          */
1197    /*------------------------------------------------------------------------*/
1198    dyn_module->wrong_endian = 
1199                      (dyn_module->fhdr.e_ident[EI_DATA] != DLIMP_get_endian());
1201    /*------------------------------------------------------------------------*/
1202    /* Swap file header structures, if needed.                                */
1203    /*------------------------------------------------------------------------*/
1204    if (dyn_module->wrong_endian)
1205       DLIMP_change_ehdr_endian(&(dyn_module->fhdr));
1207    /*------------------------------------------------------------------------*/
1208    /* Write out magic ELF information for debug purposes.                    */
1209    /*------------------------------------------------------------------------*/
1210    printf("ELF: %c%c%c\n", dyn_module->fhdr.e_ident[1],
1211                            dyn_module->fhdr.e_ident[2],
1212                            dyn_module->fhdr.e_ident[3]);
1213    printf("ELF file header entry point: %x\n", dyn_module->fhdr.e_entry);
1215    /*------------------------------------------------------------------------*/
1216    /* Verify magic numbers in ELF file header.                               */
1217    /*------------------------------------------------------------------------*/
1218    if (!file_header_magic_number_is_valid(&(dyn_module->fhdr)))
1219    {
1220       DLIF_error(DLET_FILE, "Invalid ELF file header magic number.\n");
1221       return 0;
1222    }
1224    if (!file_header_machine_is_valid(dyn_module->fhdr.e_machine))
1225    {
1226        DLIF_error(DLET_FILE, "Invalid ELF file target machine.\n");
1227        return 0;
1228    }
1230    /*------------------------------------------------------------------------*/
1231    /* Verify file is an executable or dynamic shared object or library.      */
1232    /*------------------------------------------------------------------------*/
1233    if ((dyn_module->fhdr.e_type != ET_EXEC) && 
1234        (dyn_module->fhdr.e_type != ET_DYN))
1235    {
1236       DLIF_error(DLET_FILE, "Invalid ELF file type.\n");
1237       return FALSE;
1238    }
1240 #if LOADER_DEBUG || LOADER_PROFILE
1241    /*------------------------------------------------------------------------*/
1242    /* Stop profiling clock when file header information has finished         */
1243    /* loading.  Re-start clock on initialization of symbol table, and        */
1244    /* dynamic table pointers.                                                */
1245    /*------------------------------------------------------------------------*/
1246    if (debugging_on || profiling_on)
1247    {
1248       printf("done.\n");
1249       if (profiling_on)
1250       {
1251          profile_stop_clock();
1252          printf("Took %d cycles.\n", profile_cycle_count());
1253          profile_start_clock();
1254       }
1255    }
1256 #endif
1258    return TRUE;
1261 /*****************************************************************************/
1262 /* dload_program_header_table()                                              */
1263 /*                                                                           */
1264 /*    Make a local copy of the ELF object file's program header table in the */
1265 /*    dynamic module data structure.                                         */
1266 /*                                                                           */
1267 /*****************************************************************************/
1268 static void dload_program_header_table(LOADER_FILE_DESC *fd,
1269                                        DLIMP_Dynamic_Module *dyn_module)
1271    /*------------------------------------------------------------------------*/
1272    /* Read the program header tables from the object file.                   */
1273    /*------------------------------------------------------------------------*/
1274    struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
1275    dyn_module->phdr = (struct Elf32_Phdr*)
1276                               (DLIF_malloc(fhdr->e_phnum * fhdr->e_phentsize));
1277    DLIF_fseek(fd, fhdr->e_phoff, LOADER_SEEK_SET);
1278    DLIF_fread(dyn_module->phdr, fhdr->e_phentsize, fhdr->e_phnum,fd);
1279    dyn_module->phnum = fhdr->e_phnum;
1281    /*------------------------------------------------------------------------*/
1282    /* Byte swap the program header tables if the target endian-ness is not   */
1283    /* the same as the host endian-ness.                                      */
1284    /*------------------------------------------------------------------------*/
1285    if (dyn_module->wrong_endian)
1286    {
1287       int i;
1288       for (i = 0; i < dyn_module->phnum; i++)
1289          DLIMP_change_phdr_endian(dyn_module->phdr + i);
1290    }
1293 /*****************************************************************************/
1294 /* dload_headers()                                                           */
1295 /*                                                                           */
1296 /*    Read ELF object file header and program header table information into  */
1297 /*    the given dynamic module data structure.  If the object file contains  */
1298 /*    dynamic information, read in the dynamic tags, dynamic symbol table,   */
1299 /*    and global string table.  Check to make sure that we are not already   */
1300 /*    in the process of loading the module (circular dependencies), then     */
1301 /*    perform some level of sanity checking on the content of the file to    */
1302 /*    provide some assurance that the file is not corrupted.                 */
1303 /*                                                                           */
1304 /*****************************************************************************/
1305 static BOOL dload_headers(LOADER_FILE_DESC *fd,
1306                           DLIMP_Dynamic_Module *dyn_module)
1308 #if LOADER_DEBUG || LOADER_PROFILE
1309    /*------------------------------------------------------------------------*/
1310    /* More progress information.  Start timing if profiling is enabled.      */
1311    /*------------------------------------------------------------------------*/
1312    if (debugging_on || profiling_on)
1313    {
1314       printf("\nReading file headers ...\n");
1315       if (profiling_on) profile_start_clock();
1316    }
1317 #endif
1319    /*------------------------------------------------------------------------*/
1320    /* Read file header information and check vs. expected ELF object file    */
1321    /* header content.                                                        */
1322    /*------------------------------------------------------------------------*/
1323    if (!dload_file_header(fd, dyn_module))
1324       return FALSE;
1326    /*------------------------------------------------------------------------*/
1327    /* Read program header table information into the dynamic module object.  */
1328    /*------------------------------------------------------------------------*/
1329    dload_program_header_table(fd, dyn_module);
1331    return TRUE;
1334 /*****************************************************************************/
1335 /* find_dynamic_segment()                                                    */
1336 /*                                                                           */
1337 /*    Find the dynamic segment in the given ELF object file, if there is     */
1338 /*    one.  If the segment is found, then the segment ID output parameter    */
1339 /*    is set to the index of the dynamic segment in the program header       */
1340 /*    table.  If the dynamic segment is not found, the dynamic module's      */
1341 /*    relocatable flag is set to FALSE, and return FALSE.                    */
1342 /*                                                                           */
1343 /*****************************************************************************/
1344 static BOOL find_dynamic_segment(DLIMP_Dynamic_Module *dyn_module,
1345                                  Elf32_Word *dyn_seg_idx)
1347    int i;
1349    /*------------------------------------------------------------------------*/
1350    /* We should have a valid dynamic module pointer and somewhere to put the */
1351    /* dynamic segment id, if we find one.  If either of these are missing,   */
1352    /* we should get an internal error and abort the loader.                  */
1353    /*------------------------------------------------------------------------*/
1354    if ((dyn_module == NULL) || (dyn_seg_idx == NULL))
1355    {
1356       DLIF_error(DLET_MISC, "Internal error: find_dynamic_segment() needs "
1357                             "non-NULL arguments.\n");
1358       exit(1);
1359    }
1361    /*------------------------------------------------------------------------*/
1362    /* Spin through segment program headers to find the dynamic segment.      */
1363    /*------------------------------------------------------------------------*/
1364    dyn_module->relocatable = TRUE;
1365    for (i = 0; i < dyn_module->phnum; i++)
1366       if (dyn_module->phdr[i].p_type == PT_DYNAMIC)
1367          { *dyn_seg_idx = i; return TRUE; }
1369    /*------------------------------------------------------------------------*/
1370    /* No dynamic segment found, mark the object module as not relocatable    */
1371    /* and warn the user.                                                     */
1372    /*------------------------------------------------------------------------*/
1373    dyn_module->relocatable = FALSE;
1374    DLIF_warning(DLWT_MISC, "'%s' does not have a dynamic segment; assuming " 
1375                            "that it is a static executable and it cannot " 
1376                            "be relocated.\n", dyn_module->name);
1377    return FALSE;
1381 #if 0
1382 /*****************************************************************************/
1383 /* copy_dynamic_table()                                                      */
1384 /*                                                                           */
1385 /*    Make a local copy of the dynamic table read from the dynamic segment   */
1386 /*    in the ELF object file.                                                */
1387 /*                                                                           */
1388 /*****************************************************************************/
1389 static void copy_dynamic_table(LOADER_FILE_DESC *fd,
1390                                DLIMP_Dynamic_Module *dyn_module,
1391                                Elf32_Word dyn_seg_idx)
1394    /*------------------------------------------------------------------------*/
1395    /* Allocate space for the dynamic table from host memory and read its     */
1396    /* content from the ELF object file.                                      */
1397    /*------------------------------------------------------------------------*/
1398    Elf32_Word num_elem;
1399    dyn_module->dyntab = DLIF_malloc(dyn_module->phdr[dyn_seg_idx].p_filesz);
1400    num_elem = dyn_module->phdr[dyn_seg_idx].p_filesz / sizeof(struct Elf32_Dyn);
1401    DLIF_fseek(fd, dyn_module->phdr[dyn_seg_idx].p_offset, LOADER_SEEK_SET);
1402    DLIF_fread(dyn_module->dyntab, sizeof(struct Elf32_Dyn), num_elem, fd);
1404    /*------------------------------------------------------------------------*/
1405    /* If necessary, byte swap each entry in the dynamic table.               */
1406    /*------------------------------------------------------------------------*/
1407    if (dyn_module->wrong_endian)
1408    {
1409       int i;
1410       for (i = 0; i < num_elem; i++)
1411          DLIMP_change_dynent_endian(&dyn_module->dyntab[i]);
1412    }
1415 #endif
1418 #if 0
1419 /*****************************************************************************/
1420 /* process_target_dynamic_tag()                                              */
1421 /*                                                                           */
1422 /* Process a target specific dynamic tag entry.  Returns TRUE if the tag     */
1423 /* was handled and FALSE if it was not recognized.                           */
1424 /*****************************************************************************/
1425 static BOOL process_target_dynamic_tag(DLIMP_Dynamic_Module* dyn_module, int i)
1427 #ifdef ARM_TARGET
1428    if (is_arm_module(&dyn_module->fhdr))
1429        return DLDYN_arm_process_dynamic_tag(dyn_module, i);
1430 #endif
1432 #ifdef C60_TARGET      
1433    if (is_c60_module(&dyn_module->fhdr))
1434       return DLDYN_c60_process_dynamic_tag(dyn_module, i);
1435 #endif
1437    return FALSE;
1439 #endif
1441 #if 0
1442 /*****************************************************************************/
1443 /* process_dynamic_table()                                                   */
1444 /*                                                                           */
1445 /*    Process dynamic tag entries from the dynamic table.  At the conclusion */
1446 /*    of this function, we should have made a copy of the global symbols     */
1447 /*    and the global symbol names.                                           */
1448 /*                                                                           */
1449 /*****************************************************************************/
1450 static BOOL process_dynamic_table(LOADER_FILE_DESC *fd,
1451                                   DLIMP_Dynamic_Module *dyn_module)
1453    int        i;
1454    BOOL       soname_found  = FALSE;
1455    Elf32_Addr soname_offset = 0;
1456    Elf32_Addr strtab_offset = 0;
1457    Elf32_Addr hash_offset   = 0;
1458    Elf32_Addr symtab_offset = 0;
1460    /*------------------------------------------------------------------------*/
1461    /* Iterate over the dynamic table in order to process dynamic tags.       */
1462    /* See ELF TIS Specification for details on the meaning of each dynamic   */
1463    /* tag.  The C6000 ELF ABI Specification provides more details about the  */
1464    /* TI specific C6000 ELF ABI tags.                                        */
1465    /*------------------------------------------------------------------------*/
1466    for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
1467    {
1468       switch(dyn_module->dyntab[i].d_tag)
1469       {
1470          /*------------------------------------------------------------------*/
1471          /* DT_SONAME: Contains name of dynamic object, used for dependency  */
1472          /*            comparisons.  Its value is an offset from the start   */
1473          /*            of the string table.  We need to copy the string at   */
1474          /*            this offset into dmodule->name.                       */
1475          /*------------------------------------------------------------------*/
1476          case DT_SONAME:
1477 #if LOADER_DEBUG
1478             if (debugging_on) printf("Found SO_NAME.\n");
1479 #endif
1480             /*---------------------------------------------------------------*/
1481             /* We store the offset of the so_name in the dynamic string      */
1482             /* table so that it doesn't matter which dynamic tag we see      */
1483             /* first (DT_SONAME actually is generated before DT_STRTAB).     */
1484             /*---------------------------------------------------------------*/
1485             soname_found = TRUE;
1486             soname_offset = dyn_module->dyntab[i].d_un.d_ptr;
1487             break;
1489          /*------------------------------------------------------------------*/
1490          /* DT_STRSZ: Contains the size of the string table.                 */
1491          /*------------------------------------------------------------------*/
1492          case DT_STRSZ:
1493             dyn_module->strsz = dyn_module->dyntab[i].d_un.d_val;
1495 #if LOADER_DEBUG
1496         if (debugging_on)
1497            printf("Found string table Size: 0x%x\n", dyn_module->strsz);
1498 #endif
1499             break;
1501          /*------------------------------------------------------------------*/
1502          /* DT_STRTAB: Contains the file offset of the string table.  The    */
1503          /*            tag directly after this is guaranteed to be DT_STRSZ, */
1504          /*            containing the string table size.  We need to         */
1505          /*            allocate memory for the string table and copy it from */
1506          /*            the file.                                             */
1507          /*------------------------------------------------------------------*/
1508          case DT_STRTAB:
1509             strtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1510 #if LOADER_DEBUG
1511             if (debugging_on)
1512                printf("Found string table: 0x%x\n", strtab_offset);
1513 #endif
1514             break;
1516          /*------------------------------------------------------------------*/
1517          /* DT_HASH: Contains the file offset of the symbol hash table.      */
1518          /*------------------------------------------------------------------*/
1519          case DT_HASH:
1520             hash_offset = dyn_module->dyntab[i].d_un.d_ptr;
1521 #if LOADER_DEBUG
1522             if (debugging_on)
1523                printf("Found symbol hash table: 0x%x\n", hash_offset);
1524 #endif
1525             break;
1527          /*------------------------------------------------------------------*/
1528          /* DT_SYMTAB: Contains the file offset of the symbol table.         */
1529          /*------------------------------------------------------------------*/
1530          case DT_SYMTAB:
1531             symtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1532 #if LOADER_DEBUG
1533             if (debugging_on)
1534                printf("Found symbol table: 0x%x\n", symtab_offset);
1535 #endif
1536             break;
1538          /*------------------------------------------------------------------*/
1539          /* DSO Initialization / Termination Model Dynamic Tags              */
1540          /*------------------------------------------------------------------*/
1541          /* For initialization tags, we store indices and array sizes in     */
1542          /* the dyn_module. Termination works a little different, the        */
1543          /* indices into the local copy of the dynamic table are stored in   */
1544          /* dyn_module, but the DT_FINI_ARRAYSZ value is recorded with the   */
1545          /* loaded module.                                                   */
1546          /*------------------------------------------------------------------*/
1547          /* After placement is done, the DT_FINI and DT_FINI_ARRAY values    */
1548          /* need to be copied from the local dynamic table into the loaded   */
1549          /* module object.                                                   */
1550          /*------------------------------------------------------------------*/
1551          case DT_PREINIT_ARRAY:
1552             dyn_module->preinit_array_idx = i;
1553             break;
1555          case DT_PREINIT_ARRAYSZ:
1556             dyn_module->preinit_arraysz = dyn_module->dyntab[i].d_un.d_val;
1557             break;
1559          case DT_INIT:
1560             dyn_module->init_idx = i;
1561             break;
1563          case DT_INIT_ARRAY:
1564             dyn_module->init_array_idx = i;
1565             break;
1567          case DT_INIT_ARRAYSZ:
1568             dyn_module->init_arraysz = dyn_module->dyntab[i].d_un.d_val;
1569             break;
1571          /*------------------------------------------------------------------*/
1572          /* This information will be copied over to the loaded module        */
1573          /* object after placement has been completed and the information    */
1574          /* in the dynamic table has been relocated.                         */
1575          /*------------------------------------------------------------------*/
1576          case DT_FINI_ARRAY:
1577          case DT_FINI_ARRAYSZ:
1578          case DT_FINI:
1579             break;
1581          /*------------------------------------------------------------------*/
1582          /* Unrecognized tag, may not be illegal, but is not explicitly      */
1583          /* handled by this function.  Should it be?                         */
1584          /*------------------------------------------------------------------*/
1585          default:
1586          {
1587             if (!process_target_dynamic_tag(dyn_module, i))
1588             {
1589 #if LOADER_DEBUG
1590                if (debugging_on)
1591                   printf("Unrecognized dynamic tag: 0x%X\n",
1592                                dyn_module->dyntab[i].d_tag);
1593 #endif
1594             }
1595             
1596             break;
1597          }
1599       }
1600    }
1602    /*------------------------------------------------------------------------*/
1603    /* If string table offset and size were found, read string table in from  */
1604    /* the ELF object file.                                                   */
1605    /*------------------------------------------------------------------------*/
1606    if (strtab_offset && dyn_module->strsz)
1607    {
1608       DLIF_fseek(fd, strtab_offset, LOADER_SEEK_SET);
1609       dyn_module->strtab = DLIF_malloc(dyn_module->strsz);
1610       DLIF_fread(dyn_module->strtab, sizeof(uint8_t), dyn_module->strsz, fd);
1611    }
1612    else
1613    {
1614       DLIF_warning(DLWT_MISC, "Mandatory dynamic tag DT_STRTAB/DT_STRSZ not found!\n");
1615       return FALSE;
1616    }
1619    /*------------------------------------------------------------------------*/
1620    /* If symbol hash table is found read-in the hash table.                  */
1621    /*------------------------------------------------------------------------*/
1622    if (hash_offset)
1623    {
1624       /*---------------------------------------------------------------------*/
1625       /* Hash table has the following format. nchain equals the number of    */
1626       /* entries in the symbol table (symnum)                                */
1627       /*                                                                     */
1628       /*             +----------------------------+                          */
1629       /*             |          nbucket           |                          */
1630       /*             +----------------------------+                          */
1631       /*             |          nchain            |                          */
1632       /*             +----------------------------+                          */
1633       /*             |         bucket[0]          |                          */
1634       /*             |            ...             |                          */
1635       /*             |     bucket[nbucket-1]      |                          */
1636       /*             +----------------------------+                          */
1637       /*             |          chain[0]          |                          */
1638       /*             |            ...             |                          */
1639       /*             |       chain[nchain-1]      |                          */
1640       /*             +----------------------------+                          */
1641       /*---------------------------------------------------------------------*/
1642       Elf32_Word hash_nbucket;
1643       Elf32_Word hash_nchain;
1645       /*---------------------------------------------------------------------*/
1646       /* Seek to the hash offset and read first two words into nbucket and   */
1647       /* symnum.                                                             */
1648       /*---------------------------------------------------------------------*/
1649       DLIF_fseek(fd, hash_offset, LOADER_SEEK_SET);
1650       DLIF_fread(&(hash_nbucket), sizeof(Elf32_Word), 1, fd);
1651       DLIF_fread(&(hash_nchain), sizeof(Elf32_Word), 1, fd);
1652       if (dyn_module->wrong_endian)
1653       {
1654          DLIMP_change_endian32((int32_t*)(&(hash_nbucket)));
1655          DLIMP_change_endian32((int32_t*)(&(hash_nchain)));
1656       }
1658       /*---------------------------------------------------------------------*/
1659       /* The number of entires in the dynamic symbol table is not encoded    */
1660       /* anywhere in the elf file. However, the nchain is guaranteed to be   */
1661       /* the same as the number of symbols. Use nchain to set the symnum.    */
1662       /*---------------------------------------------------------------------*/
1663       dyn_module->symnum = hash_nchain;
1664 #if LOADER_DEBUG
1665       if (debugging_on) printf("symnum=%d\n", hash_nchain);
1666 #endif
1667    }
1668    else
1669    {
1670       DLIF_warning(DLWT_MISC, "Mandatory dynamic tag DT_HASH is not found!\n");
1671       return FALSE;
1672    }
1674    /*------------------------------------------------------------------------*/
1675    /* Read dynamic symbol table.                                             */
1676    /*------------------------------------------------------------------------*/
1677    if (symtab_offset)
1678    {
1679       int j = 0;
1680       DLIF_fseek(fd, symtab_offset, LOADER_SEEK_SET);
1681       dyn_module->symtab = 
1682                  DLIF_malloc(dyn_module->symnum * sizeof(struct Elf32_Sym));
1683       DLIF_fread(dyn_module->symtab, sizeof(struct Elf32_Sym), 
1684                  dyn_module->symnum, fd);
1685       if (dyn_module->wrong_endian)
1686       {
1687          for (j = 0; j < dyn_module->symnum; j++)
1688             DLIMP_change_sym_endian(dyn_module->symtab + j);
1689       }
1691       /*---------------------------------------------------------------------*/
1692       /* The st_name field of an Elf32_Sym entity is an offset into the      */
1693       /* string table. Convert it into a pointer to the string.              */
1694       /*---------------------------------------------------------------------*/
1695       if (strtab_offset)
1696          for (j = 0; j < dyn_module->symnum; j++)
1697             dyn_module->symtab[j].st_name += (Elf32_Word) dyn_module->strtab;
1698    }
1699    else
1700    {
1701       DLIF_warning(DLWT_MISC, "Mandatory dynamic tag DT_SYMTAB is not found!\n");
1702       return FALSE;
1703    }
1705    /*------------------------------------------------------------------------*/
1706    /* Read the SONAME.                                                       */
1707    /*------------------------------------------------------------------------*/
1708    if (!soname_found)
1709    {
1710       DLIF_warning(DLWT_MISC, "Dynamic tag DT_SONAME is not found!\n");
1711       dyn_module->name = DLIF_malloc(sizeof(char));
1712       *dyn_module->name = '\0';
1713    }
1714    else
1715    {
1716       dyn_module->name = 
1717                     DLIF_malloc(strlen(dyn_module->strtab + soname_offset) + 1);
1718       strcpy(dyn_module->name, dyn_module->strtab + soname_offset);
1720 #if LOADER_DEBUG
1721       if (debugging_on)
1722          printf("Name of dynamic object: %s\n", dyn_module->name);
1723 #endif
1724    }
1726    return TRUE;
1729 #endif
1732 #if 0
1734 /*****************************************************************************/
1735 /* dload_dynamic_information()                                               */
1736 /*                                                                           */
1737 /*    Given a dynamic module with a dynamic segment which is located via     */
1738 /*    given dynamic segment index, make a local copy of the dynamic table    */
1739 /*    in the dynamic module object, then process the dynamic tag entries in  */
1740 /*    the table.                                                             */
1741 /*                                                                           */
1742 /*****************************************************************************/
1743 static BOOL dload_dynamic_information(LOADER_FILE_DESC *fd,
1744                                       DLIMP_Dynamic_Module *dyn_module,
1745                                       Elf32_Word dyn_seg_idx)
1747    /*------------------------------------------------------------------------*/
1748    /* Read a copy of the dynamic table into the dynamic module object.       */
1749    /*------------------------------------------------------------------------*/
1750    copy_dynamic_table(fd, dyn_module, dyn_seg_idx);
1752    /*------------------------------------------------------------------------*/
1753    /* Process dynamic entries in the dynamic table.  If any problems are     */
1754    /* encountered, the loader should emit an error or warning and return     */
1755    /* FALSE here.                                                            */
1756    /*------------------------------------------------------------------------*/
1757    return process_dynamic_table(fd, dyn_module);
1760 #endif
1763 #if 0
1764 /*****************************************************************************/
1765 /* check_circular_dependency()                                               */
1766 /*                                                                           */
1767 /*    Determine whether a dynamic module is already in the process of being  */
1768 /*    loaded before we try to start loading it again.  If it is already      */
1769 /*    being loaded, then the dynamic loader has detected a circular          */
1770 /*    dependency.  An error will be emitted and the load will be aborted.    */
1771 /*                                                                           */
1772 /*****************************************************************************/
1773 static BOOL check_circular_dependency(const char *dyn_mod_name)
1775    /*------------------------------------------------------------------------*/
1776    /* Check the name of the given dependency module to be loaded against the */
1777    /* list of modules that are currently in the process of being loaded.     */
1778    /* Report an error if any circular dependencies are detected.             */
1779    /*------------------------------------------------------------------------*/
1780    int i;
1781    for (i = 0; i < DLIMP_module_dependency_list.size; i++)
1782       if (!strcmp(dyn_mod_name, ((char**)(DLIMP_module_dependency_list.buf))[i]))
1783       {
1784          DLIF_error(DLET_MISC, 
1785                     "Circular dependency detected, '%s' is already in the " 
1786                     "process of loading.\n", dyn_mod_name);
1787          return FALSE;
1788       }
1790    return TRUE;
1793 #endif
1796 #if 0
1797 /*****************************************************************************/
1798 /* dload_dynamic_segment()                                                   */
1799 /*                                                                           */
1800 /*    Find the dynamic segment in the given ELF module, if there is one.     */
1801 /*    If there is a dynamic segment, then make a local copy of the dynamic   */
1802 /*    table in the dynamic module object provided, then process the dynamic  */
1803 /*    tag entries in the table.                                              */
1804 /*                                                                           */
1805 /*    If there is no dynamic segment, then we return success from this       */
1806 /*    function, marking the dynamic module as "not relocatable".             */
1807 /*                                                                           */
1808 /*****************************************************************************/
1809 static BOOL dload_dynamic_segment(LOADER_FILE_DESC *fd, 
1810                                   DLIMP_Dynamic_Module *dyn_module)
1812    /*------------------------------------------------------------------------*/
1813    /* If we don't find dynamic segment, the relocatable flag will have been  */
1814    /* set to false to indicate that the module is a static executable.  We   */
1815    /* still return TRUE from this function so that we can proceed with       */
1816    /* static loading.                                                        */
1817    /*------------------------------------------------------------------------*/
1818    Elf32_Word dyn_seg_idx = 0;
1819    if (!find_dynamic_segment(dyn_module, &dyn_seg_idx))
1820       return TRUE;
1822    /*------------------------------------------------------------------------*/
1823    /* Process the OSABI now, after we know if the module is relocatable.     */
1824    /*------------------------------------------------------------------------*/
1825    if (!process_eiosabi(dyn_module))
1826    {
1827       DLIF_error(DLET_FILE, "Unsupported EI_OSABI value.\n");
1828       return FALSE;
1829    }
1831    /*------------------------------------------------------------------------*/
1832    /* Read the dynamic table from the ELF file, then process the dynamic     */
1833    /* tags in the table.                                                     */
1834    /*------------------------------------------------------------------------*/
1835    if (!dload_dynamic_information(fd, dyn_module, dyn_seg_idx))
1836       return FALSE;
1838    /*------------------------------------------------------------------------*/
1839    /* Check to make sure that this module is not already being loaded.  If   */
1840    /* is, then it will cause a circular dependency to be introduced.         */
1841    /* Loader should detect circular dependencies and emit an error.          */
1842    /*------------------------------------------------------------------------*/
1843    if (!check_circular_dependency(dyn_module->name))
1844       return FALSE;
1846    return TRUE;
1849 #endif
1851 #if 0
1852 /*****************************************************************************/
1853 /* COPY_SEGMENTS() -                                                         */
1854 /*                                                                           */
1855 /*   Copy all segments into host memory.                                     */
1856 /*****************************************************************************/
1857 static void copy_segments(LOADER_FILE_DESC* fp, 
1858                           DLIMP_Dynamic_Module* dyn_module)
1860    DLIMP_Loaded_Segment* seg =
1861       (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
1862    int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
1864    for (s=0; s<seg_size; s++)
1865    {
1866       struct DLOAD_MEMORY_REQUEST targ_req;
1867       targ_req.fp = fp;
1868       targ_req.segment = seg[s].obj_desc;
1869       targ_req.offset = seg[s].phdr.p_offset;
1870       targ_req.flags = DLOAD_SF_relocatable;
1871       if (seg[s].phdr.p_flags & PF_X)
1872          seg[s].phdr.p_flags |= DLOAD_SF_executable;
1873       targ_req.align = seg[s].phdr.p_align;
1875       /*---------------------------------------------------------------------*/
1876       /* Copy segment data from the file into host buffer where it can       */
1877       /* be relocated.                                                       */
1878       /*---------------------------------------------------------------------*/
1879       DLIF_copy(&targ_req);
1881       /*---------------------------------------------------------------------*/
1882       /* Calculate offset for relocations.                                   */
1883       /*---------------------------------------------------------------------*/
1884       seg[s].reloc_offset = (int32_t)(targ_req.host_address) - 
1885                             (int32_t)(seg[s].obj_desc->target_address);
1886    }
1889 #endif
1891 #if 0
1892 /*****************************************************************************/
1893 /* WRITE_SEGMENTS() -                                                        */
1894 /*                                                                           */
1895 /*   Write all segments to target memory.                                    */
1896 /*****************************************************************************/
1897 static void write_segments(LOADER_FILE_DESC* fp, 
1898                           DLIMP_Dynamic_Module* dyn_module)
1900    DLIMP_Loaded_Segment* seg =
1901       (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
1902    int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
1904    for (s=0; s<seg_size; s++)
1905    {
1906       struct DLOAD_MEMORY_REQUEST targ_req;
1907       targ_req.fp = fp;
1908       targ_req.segment = seg[s].obj_desc;
1909       targ_req.offset = seg[s].phdr.p_offset;
1910       targ_req.flags = DLOAD_SF_relocatable;
1911       if (seg[s].phdr.p_flags & PF_X)
1912          seg[s].phdr.p_flags |= DLOAD_SF_executable;
1913       targ_req.align = seg[s].phdr.p_align;
1915       /*---------------------------------------------------------------------*/
1916       /* Copy segment data from the file into host buffer where it can       */
1917       /* be relocated.                                                       */
1918       /*---------------------------------------------------------------------*/
1919       DLIF_write(&targ_req);
1920    }
1923 #endif
1925 #if 0
1926 /*****************************************************************************/
1927 /* DLOAD_initialize()                                                        */
1928 /*                                                                           */
1929 /*    Construct and initialize data structures internal to the dynamic       */
1930 /*    loader core.                                                           */
1931 /*                                                                           */
1932 /*---------------------------------------------------------------------------*/
1933 /*                                                                           */
1934 /*    This implementation of DLOAD_initialize() will set up the list of      */
1935 /*    dependency modules maintained by the loader core.  This list contains  */
1936 /*    the names of the files that the loader is in the process of loading.   */
1937 /*    The list is used to keep track of what objects are waiting on their    */
1938 /*    dependents to be loaded so thath circular dependencies can be detected */
1939 /*    and reported by the core loader.                                       */
1940 /*                                                                           */
1941 /*****************************************************************************/
1942 void DLOAD_initialize()
1944    /*------------------------------------------------------------------------*/
1945    /* Set up initial objects_loading queue.                                  */
1946    /*------------------------------------------------------------------------*/
1947    AL_initialize(&DLIMP_module_dependency_list, sizeof (const char*), 1);
1950 #endif
1952 /*****************************************************************************/
1953 /* dload_static_executable()                                                 */
1954 /*                                                                           */
1955 /*    Account for target memory allocated to static executable and wrap up   */
1956 /*    loading.  No relocation is necessary.                                  */
1957 /*                                                                           */
1958 /*****************************************************************************/
1959 static int32_t dload_static_executable(LOADER_FILE_DESC *fd,
1960                                        DLIMP_Dynamic_Module *dyn_module)
1962    int32_t local_file_handle = 0;
1964 #if LOADER_DEBUG
1965    if (debugging_on) printf("Starting dload_static_executable() ...\n");
1966 #endif
1968    /*------------------------------------------------------------------------*/
1969    /* Set entry point for static executable and attempt to allocate target   */
1970    /* memory for the static executable.                                      */
1971    /*------------------------------------------------------------------------*/
1972    dyn_module->loaded_module->entry_point = dyn_module->fhdr.e_entry;
1973    if (load_static_segment(fd, dyn_module) && load_object(fd, dyn_module))
1974    {
1975       /*---------------------------------------------------------------------*/
1976       /* If successful, we'll want to detach the loaded module object from   */
1977       /* the dynamic module object that created it.  Take note of the file   */
1978       /* handle.                                                             */
1979       /*---------------------------------------------------------------------*/
1980       DLIMP_Loaded_Module *loaded_module = detach_loaded_module(dyn_module);
1981       local_file_handle = loaded_module->file_handle;
1982    }
1984    /*------------------------------------------------------------------------*/
1985    /* Static load failed.  Flag an error.                                    */
1986    /*------------------------------------------------------------------------*/
1987    else
1988       DLIF_error(DLET_MEMORY, 
1989                  "Failed to allocate target memory for static executable.\n");
1991    /*------------------------------------------------------------------------*/
1992    /* Destruct dynamic module object.                                        */
1993    /*------------------------------------------------------------------------*/
1994 #if 0
1995    delete_DLIMP_Dynamic_Module(&dyn_module);
1996 #endif
1998 #if LOADER_DEBUG
1999    if (debugging_on) printf("Finished dload_static_executable()\n");
2000 #endif
2002    return local_file_handle;
2005 #if 0
2006 /*****************************************************************************/
2007 /* process_dynamic_module_relocations()                                      */
2008 /*                                                                           */
2009 /*    Make a host-accessible copy of all of the segments, process all        */
2010 /*    relocation entries associated with the given module within that        */
2011 /*    space, then write the updated segment buffers back out to target       */
2012 /*    memory.                                                                */
2013 /*                                                                           */
2014 /*****************************************************************************/
2015 static void process_dynamic_module_relocations(LOADER_FILE_DESC *fd,
2016                                                DLIMP_Dynamic_Module *dyn_module)
2018 #if LOADER_DEBUG || LOADER_PROFILE
2019    if(debugging_on || profiling_on)
2020    {
2021       printf("Running relocate()...\n");
2022       if (profiling_on) profile_start_clock();
2023    }
2024 #endif
2026    /*------------------------------------------------------------------------*/
2027    /* Copy segments from file to host memory                                 */
2028    /*------------------------------------------------------------------------*/
2029    copy_segments(fd, dyn_module);
2031    /*------------------------------------------------------------------------*/
2032    /* Process dynamic relocations.                                           */
2033    /*------------------------------------------------------------------------*/
2034    DLREL_relocate(fd, dyn_module);
2036    /*------------------------------------------------------------------------*/
2037    /* Write segments from host memory to target memory                       */
2038    /*------------------------------------------------------------------------*/
2039    write_segments(fd, dyn_module);
2041 #if LOADER_DEBUG || LOADER_PROFILE
2042    /*------------------------------------------------------------------------*/
2043    /* Report timing and progress information for relocation step.            */
2044    /*------------------------------------------------------------------------*/
2045    if (debugging_on || profiling_on)
2046    {
2047       if (profiling_on)
2048       {
2049          profile_stop_clock();
2050          printf("Took %d cycles.\n", profile_cycle_count());
2051          printf("Total reloc time: %d\n", DLREL_total_reloc_time);
2052          printf("Time per relocation: %d\n",
2053          DLREL_relocations ? DLREL_total_reloc_time / DLREL_relocations : 0);
2054       }
2056       printf("Number of relocations: %d\n", DLREL_relocations);
2057       printf("\nAbout to run load_object()...");
2058       DLREL_total_reloc_time = DLREL_relocations = 0;
2059       if (profiling_on) profile_start_clock();
2060    }
2061 #endif
2064 #endif
2067 #if 0
2068 /*****************************************************************************/
2069 /* execute_module_pre_initialization()                                       */
2070 /*                                                                           */
2071 /*    Given a dynamic module object, execute any pre-initialization          */
2072 /*    functions for the specified dynamic executable module. Such functions  */
2073 /*    must be provided by the user and their addresses written to the        */
2074 /*    .preinit_array section. These functions should be executed in the      */
2075 /*    order that they are specified in the array before the initialization   */
2076 /*    process for this dynamic executable module begins.                     */
2077 /*                                                                           */
2078 /*---------------------------------------------------------------------------*/
2079 /*                                                                           */
2080 /*    Note that dynamic shared objects (libraries) should not have a         */
2081 /*    .preinit_array (should be caught during static link-time if the user   */
2082 /*    attempts to link a .preinit_array section into a shared object.        */
2083 /*                                                                           */
2084 /*****************************************************************************/
2085 static void execute_module_pre_initialization(DLIMP_Dynamic_Module *dyn_module)
2087    /*------------------------------------------------------------------------*/
2088    /* Check for presence of DT_PREINIT_ARRAY and DT_PREINIT_ARRAYSZ          */
2089    /* dynamic tags associated with this module. The dyn_module object will   */
2090    /* hold the relevant indices into the local copy of the dynamic table.    */
2091    /* The value of the DT_INIT_ARRAY tag will have been updated after        */
2092    /* placement of the  module was completed.                                */
2093    /*------------------------------------------------------------------------*/
2094    if (dyn_module->preinit_arraysz != 0)
2095    {
2096       /*---------------------------------------------------------------------*/
2097       /* Retrieve the address of the .preinit_array section from the value   */
2098       /* of the DT_PREINIT_ARRAY tag.                                        */
2099       /*---------------------------------------------------------------------*/
2100       TARGET_ADDRESS preinit_array_loc = (TARGET_ADDRESS)
2101                 (dyn_module->dyntab[dyn_module->preinit_array_idx].d_un.d_ptr);
2103       /*---------------------------------------------------------------------*/
2104       /* Now make a loader-accessible copy of the .preinit_array section.    */
2105       /*---------------------------------------------------------------------*/
2106       int32_t i;
2107       int32_t num_preinit_fcns = dyn_module->preinit_arraysz/sizeof(TARGET_ADDRESS);
2108       TARGET_ADDRESS *preinit_array_buf = (TARGET_ADDRESS *)
2109                                       DLIF_malloc(dyn_module->preinit_arraysz);
2111       DLIF_read(preinit_array_buf, 1, dyn_module->preinit_arraysz, 
2112                                             (TARGET_ADDRESS)preinit_array_loc);
2114       /*---------------------------------------------------------------------*/
2115       /* Call each function whose address occupies an entry in the array in  */
2116       /* the order that it appears in the array. The sizeof the array is     */
2117       /* provided by the preinit_arraysz field in the dynamic module (copied */
2118       /* earlier when the dynamic table was read in). We need to divide the  */
2119       /* sizeof value down to get the number of actual entries in the array. */
2120       /*---------------------------------------------------------------------*/
2121       for (i = 0; i < num_preinit_fcns; i++)
2122          DLIF_execute((TARGET_ADDRESS)(preinit_array_buf[i]));
2124       DLIF_free(preinit_array_buf);
2125    }
2127 #endif
2130 #if 0
2131 /*****************************************************************************/
2132 /* execute_module_initialization()                                           */
2133 /*                                                                           */
2134 /*    Given a dynamic module object, execute initialization function(s) for  */
2135 /*    all global and static data objects that are defined in the module      */
2136 /*    which require construction. The user may also provide a custom         */
2137 /*    iniitialization function that needs to be executed before the compiler */
2138 /*    generated static initialization functions are executed.                */
2139 /*                                                                           */
2140 /*****************************************************************************/
2141 static void execute_module_initialization(DLIMP_Dynamic_Module *dyn_module)
2143    /*------------------------------------------------------------------------*/
2144    /* Check for presence of a DT_INIT dynamic tag associated with this       */
2145    /* module. The dynamic module will hold the index into the local copy of  */
2146    /* the dynamic table. This entry in the dynamic table will have been      */
2147    /* updated after placement of the module is completed.                    */
2148    /*------------------------------------------------------------------------*/
2149    if (dyn_module->init_idx != -1)
2150    {
2151       /*---------------------------------------------------------------------*/
2152       /* Retrieve the address of the initialization function from the value  */
2153       /* of the DT_INIT tag, and get the client to execute the function.     */
2154       /*---------------------------------------------------------------------*/
2155       TARGET_ADDRESS init_fcn = (TARGET_ADDRESS)
2156                          (dyn_module->dyntab[dyn_module->init_idx].d_un.d_ptr);
2157       DLIF_execute(init_fcn);
2158    }
2160    /*------------------------------------------------------------------------*/
2161    /* Check for presence of a DT_INIT_ARRAY and DT_INIT_ARRAYSZ dynamic tags */
2162    /* associated with this module. The dyn_module object will hold the       */
2163    /* relevant indices into the local copy of the dynamic table. The value   */
2164    /* of the DT_INIT_ARRAY tag will have been updated after placement of the */
2165    /* module was completed.                                                  */
2166    /*------------------------------------------------------------------------*/
2167    if (dyn_module->init_arraysz != 0)
2168    {
2169       /*---------------------------------------------------------------------*/
2170       /* Retrieve the address of the .init_array section from the value of   */
2171       /* DT_INIT_ARRAY tag.                                                  */
2172       /*---------------------------------------------------------------------*/
2173       TARGET_ADDRESS init_array_loc = (TARGET_ADDRESS)
2174                    (dyn_module->dyntab[dyn_module->init_array_idx].d_un.d_ptr);
2176       /*---------------------------------------------------------------------*/
2177       /* Now make a loader-accessible copy of the .init_array section.       */
2178       /*---------------------------------------------------------------------*/
2179       int32_t i;
2180       int32_t num_init_fcns = dyn_module->init_arraysz/sizeof(TARGET_ADDRESS);
2181       TARGET_ADDRESS *init_array_buf = (TARGET_ADDRESS *)
2182                                          DLIF_malloc(dyn_module->init_arraysz);
2184       DLIF_read(init_array_buf, 1, dyn_module->init_arraysz, 
2185                                                (TARGET_ADDRESS)init_array_loc);
2187       /*---------------------------------------------------------------------*/
2188       /* Call each function whose address occupies an entry in the array in  */
2189       /* the order that they appear in the array. The size of the array is   */
2190       /* provided by the init_arraysz field in the dynamic module (copied    */
2191       /* earlier when the dynamic table was read in).                        */
2192       /*---------------------------------------------------------------------*/
2193       for (i = 0; i < num_init_fcns; i++)
2194          DLIF_execute((TARGET_ADDRESS)(init_array_buf[i]));
2196       DLIF_free(init_array_buf);
2197    }
2200 #endif
2203 #if 0
2204 /*****************************************************************************/
2205 /* relocate_dependency_graph_modules()                                       */
2206 /*                                                                           */
2207 /*    For each dynamic module on the dependency stack, process dynamic       */
2208 /*    relocation entries then perform initialization for all global and      */
2209 /*    static objects that are defined in tha given module. The stack is      */
2210 /*    emptied from the top (LIFO).  Each dynamic module object is popped     */
2211 /*    off the top of the stack, the module gets relocated, its global and    */
2212 /*    static objects that need to be constructed will be constructed, and    */
2213 /*    then, after detaching the loaded module object from its dynamic        */
2214 /*    module, the dynamic module object is destructed.                       */
2215 /*                                                                           */
2216 /*****************************************************************************/
2217 static int32_t relocate_dependency_graph_modules(LOADER_FILE_DESC *fd,
2218                                                  DLIMP_Dynamic_Module *dyn_module)
2220    /*------------------------------------------------------------------------*/
2221    /* Processing of relocations will only be triggered when this function    */
2222    /* is called from the top-level object module (at the bottom of the       */
2223    /* dependency graph stack).                                               */
2224    /*------------------------------------------------------------------------*/
2225    int32_t local_file_handle = dyn_module->loaded_module->file_handle;
2226    dynamic_module_ptr_Stack_Node *ptr = DLIMP_dependency_stack.bottom_ptr;
2227    if (ptr && (ptr->value != dyn_module)) return local_file_handle;
2229    /*------------------------------------------------------------------------*/
2230    /* Assign DSBT indices.                                                   */
2231    /*------------------------------------------------------------------------*/
2232    DLIF_assign_dsbt_indices();
2234    /*------------------------------------------------------------------------*/
2235    /* Update the content of all DSBTs for any module that uses the DSBT      */
2236    /* model.                                                                 */
2237    /*------------------------------------------------------------------------*/
2238    DLIF_update_all_dsbts();
2240    /*------------------------------------------------------------------------*/
2241    /* Ok, we are ready to process relocations. The relocation tables         */
2242    /* associated with dependent files will be processed first. Consume       */
2243    /* dynamic module objects from the dependency graph stack from dependents */
2244    /* to the root of the dependency graph.                                   */
2245    /*------------------------------------------------------------------------*/
2246    while (DLIMP_dependency_stack.size > 0)
2247    {
2248       DLIMP_Dynamic_Module *dyn_mod_ptr =
2249                            dynamic_module_ptr_pop(&DLIMP_dependency_stack);
2251       /*---------------------------------------------------------------------*/
2252       /* Process dynamic relocations associated with this module.            */
2253       /*---------------------------------------------------------------------*/
2254       process_dynamic_module_relocations(dyn_mod_ptr->fd, dyn_mod_ptr);
2256       /*---------------------------------------------------------------------*/
2257       /* __c_args__ points to the beginning of the .args section, if there   */
2258       /* is one.  Record this pointer in the ELF file internal data object.  */
2259       /*---------------------------------------------------------------------*/
2260       DLSYM_lookup_local_symtab("__c_args__", dyn_mod_ptr->symtab,
2261                                 dyn_mod_ptr->symnum,
2262                                 (Elf32_Addr *)&dyn_mod_ptr->c_args);
2264       /*---------------------------------------------------------------------*/
2265       /* Pick up entry point address from ELF file header.                   */
2266       /*   We currently only support a single entry point into the ELF file. */
2267       /*   To support Braveheart notion of nodes, with multiple entry points,*/
2268       /*   we'll need to get the list of entry points associated with a node,*/
2269       /*   then add capability to the "execute" command to select the entry  */
2270       /*   point that we want to start executing from.                       */
2271       /*---------------------------------------------------------------------*/
2272       dyn_mod_ptr->loaded_module->entry_point = dyn_mod_ptr->fhdr.e_entry;
2274       /*---------------------------------------------------------------------*/
2275       /* Copy command-line arguments into args section and deal with DSBT    */
2276       /* issues (copy DSBT to its run location).                             */
2277       /*---------------------------------------------------------------------*/
2278       load_object(dyn_mod_ptr->fd, dyn_mod_ptr);
2280       /*---------------------------------------------------------------------*/
2281       /* Perform initialization, if needed, for this module.                 */
2282       /*---------------------------------------------------------------------*/
2283       execute_module_initialization(dyn_mod_ptr);
2285       /*---------------------------------------------------------------------*/
2286       /* Free all dependent file pointers.                                   */
2287       /*---------------------------------------------------------------------*/
2288       if (dyn_mod_ptr->fd != fd)
2289       {
2290          DLIF_fclose(dyn_mod_ptr->fd);
2291          dyn_mod_ptr->fd = NULL;
2292       }
2294       /*---------------------------------------------------------------------*/
2295       /* Detach loaded module object from the dynamic module object that     */
2296       /* created it, then throw away the dynamic module object.              */
2297       /*---------------------------------------------------------------------*/
2298       detach_loaded_module(dyn_mod_ptr);
2299       delete_DLIMP_Dynamic_Module(&dyn_mod_ptr);
2300    }
2302    return local_file_handle;
2305 #endif
2307 /*****************************************************************************/
2308 /* DLOAD_load()                                                              */
2309 /*                                                                           */
2310 /*    Dynamically load the specified file and return a file handle for the   */
2311 /*    loaded file.  If the load fails, this function will return a value of  */
2312 /*    zero (0) for the file handle.                                          */
2313 /*                                                                           */
2314 /*    The core loader must have read access to the file pointed to by fd.    */
2315 /*                                                                           */
2316 /*****************************************************************************/
2317 int32_t DLOAD_load(LOADER_FILE_DESC *fd, int argc, char** argv, int32_t *entry)
2319     DLIMP_Dynamic_Module *dyn_module = new_DLIMP_Dynamic_Module(fd);
2321     if (!dyn_module)
2322         return 0;
2324 #if LOADER_DEBUG
2325    /*------------------------------------------------------------------------*/
2326    /* Spit out some loader progress information when we begin loading an     */
2327    /* object.                                                                */
2328    /*------------------------------------------------------------------------*/
2329    if (debugging_on) printf("Loading file...\n");
2330 #endif
2332    /*------------------------------------------------------------------------*/
2333    /* If no access to a program was provided, there is nothing to do.        */
2334    /*------------------------------------------------------------------------*/
2335    if (!fd)
2336    {
2337       DLIF_error(DLET_FILE, "Missing file specification.\n");
2338       return 0;
2339    }
2341    /*------------------------------------------------------------------------*/
2342    /* Read file headers and dynamic information into dynamic module.         */
2343    /*------------------------------------------------------------------------*/
2344    if (!dload_headers(fd, dyn_module))
2345       return 0;
2347    /*------------------------------------------------------------------------*/
2348    /* Find the dynamic segment, if there is one, and read dynamic            */
2349    /* information from the ELF object file into the dynamic module data      */
2350    /* structure associated with this file.                                   */
2351    /*------------------------------------------------------------------------*/
2352    if (!dload_dynamic_segment(fd, dyn_module))
2353       return 0;
2355    /*------------------------------------------------------------------------*/
2356    /* ??? We currently don't have a way of finding the .args section.  So    */
2357    /*    we are hard-wiring the address of the .args section.  The proposed  */
2358    /*    solution for this problem is to invent a special segment type or    */
2359    /*    dynamic tag(s) that identify the location and size of the .args     */
2360    /*    section for the dynamic loader.                                     */
2361    /*------------------------------------------------------------------------*/
2362    /*HACK ---> */dyn_module->c_args = (uint8_t*)(0x02204000); /* <--- HACK*/
2364    /*------------------------------------------------------------------------*/
2365    /* Record argc and argv pointers with the dynamic module record.          */
2366    /*------------------------------------------------------------------------*/
2367    dyn_module->argc = argc;
2368    dyn_module->argv = argv;
2370    /*------------------------------------------------------------------------*/
2371    /* Perform sanity checking on the read-in ELF file.                       */
2372    /*------------------------------------------------------------------------*/
2373    if (!is_valid_elf_object_file(fd, dyn_module))
2374    {
2375       DLIF_error(DLET_FILE, "Attempt to load invalid ELF file, '%s'.\n",
2376                     dyn_module->name);
2377       return 0;
2378    }
2380 #if LOADER_DEBUG || LOADER_PROFILE
2381    /*------------------------------------------------------------------------*/
2382    /* Stop clock on initialization of ELF file information.  Start clock on  */
2383    /* initialization of ELF module.                                          */
2384    /*------------------------------------------------------------------------*/
2385    if (debugging_on || profiling_on)
2386    {
2387       printf("Finished dload_dynamic_segment.\n");
2388       if (profiling_on)
2389       {
2390          profile_stop_clock();
2391          printf("Took %d cycles.\n", profile_cycle_count());
2392       }
2393    }
2394 #endif
2396    /*------------------------------------------------------------------------*/
2397    /* Initialize internal ELF module and segment structures.  Sets           */
2398    /* loaded_module in *dyn_module.  This also deals with assigning a file   */
2399    /* handle and bumping file handle counter.                                */
2400    /*------------------------------------------------------------------------*/
2401    initialize_loaded_module(dyn_module);
2403    /*------------------------------------------------------------------------*/
2404    /* Append Module structure to loaded object list.                         */
2405    /*------------------------------------------------------------------------*/
2406 #if 0
2407    loaded_module_ptr_enqueue(&DLIMP_loaded_objects, dyn_module->loaded_module);
2408 #endif
2410    /*------------------------------------------------------------------------*/
2411    /* Support static loading as special case.                                */
2412    /*------------------------------------------------------------------------*/
2413    if (!dyn_module->relocatable)  {
2414       return (dload_static_executable(fd, dyn_module));
2415       *entry = dyn_module->fhdr.e_entry;
2416       return (0); 
2417    }
2419 #if 0
2421    /*------------------------------------------------------------------------*/
2422    /* Get space & address for segments, and offset symbols and program       */
2423    /* header table to reflect the relocated address.  Also offset the        */
2424    /* addresses in the internal Segment structures used by the Module        */
2425    /* structure.  Note that this step needs to be performed prior and in     */
2426    /* addition to the relocation entry processing.                           */
2427    /*------------------------------------------------------------------------*/
2428    if (!allocate_dynamic_segments_and_relocate_symbols(fd, dyn_module))
2429       return 0;
2431    /*------------------------------------------------------------------------*/
2432    /* Execute any user defined pre-initialization functions that may be      */
2433    /* associated with a dynamic executable module.                           */
2434    /*------------------------------------------------------------------------*/
2435    if (dyn_module->fhdr.e_type == ET_EXEC)
2436       execute_module_pre_initialization(dyn_module);
2438    /*------------------------------------------------------------------------*/
2439    /* Append current ELF file to list of objects currently loading.          */
2440    /* This is used to detect circular dependencies while we are processing   */
2441    /* the dependents of this file.                                           */
2442    /*------------------------------------------------------------------------*/
2443    AL_append(&DLIMP_module_dependency_list, &dyn_module->name);
2445    /*------------------------------------------------------------------------*/
2446    /* Push this dynamic module object onto the dependency stack.             */
2447    /* All of the modules on the stack will get relocated after all of the    */
2448    /* dependent files have been loaded and allocated.                        */
2449    /*------------------------------------------------------------------------*/
2450    dynamic_module_ptr_push(&DLIMP_dependency_stack, dyn_module);
2452    /*------------------------------------------------------------------------*/
2453    /* If this object file uses the DSBT model, then register a DSBT index    */
2454    /* request with the client's DSBT support management.                     */
2455    /*------------------------------------------------------------------------*/
2456    if (is_dsbt_module(dyn_module) &&
2457        !DLIF_register_dsbt_index_request(dyn_module->name,
2458                                          dyn_module->loaded_module->file_handle,
2459                                          dyn_module->dsbt_index))
2460       return 0;
2462    /*------------------------------------------------------------------------*/
2463    /* Load this ELF file's dependents (all files on its DT_NEEDED list).     */
2464    /* Do not process relocation entries for anyone in the dependency graph   */
2465    /* until all modules in the graph are loaded and allocated.               */
2466    /*------------------------------------------------------------------------*/
2467    if (!dload_and_allocate_dependencies(dyn_module))
2468       return 0;
2470    /*------------------------------------------------------------------------*/
2471    /* Remove the current ELF file from the list of files that are in the     */
2472    /* process of loading.                                                    */
2473    /*------------------------------------------------------------------------*/
2474    DLIMP_module_dependency_list.size--;
2476    /*------------------------------------------------------------------------*/
2477    /* __c_args__ points to the beginning of the .args section, if there is   */
2478    /* one.  Record this pointer in the ELF file internal data object.        */
2479    /*------------------------------------------------------------------------*/
2480    DLSYM_lookup_local_symtab("__c_args__", dyn_module->symtab, 
2481                              dyn_module->symnum, 
2482                              (Elf32_Addr *)&dyn_module->c_args);
2485    return relocate_dependency_graph_modules(fd, dyn_module);
2487 #endif
2491 #if 0
2492 /*****************************************************************************/
2493 /* DLOAD_get_entry_names()                                                   */
2494 /*                                                                           */
2495 /*    Build a list of entry point names for a loaded object.  Currently,     */
2496 /*    any global symbol in the module is considered a valid entry point      */
2497 /*    regardless of whether it is defined in code or associated with a       */
2498 /*    data object.  We would need to process the content of the symbol       */
2499 /*    table entry or its debug information to determine whether it is a      */
2500 /*    valid entry point or not.                                              */
2501 /*                                                                           */
2502 /*****************************************************************************/
2503 BOOL DLOAD_get_entry_names(uint32_t file_handle, 
2504                            int32_t *entry_pt_cnt, 
2505                            char ***entry_pt_names)
2507    /*------------------------------------------------------------------------*/
2508    /* Spin through list of loaded files until we find the file handle we     */
2509    /* are looking for.  Then build a list of entry points from that file's   */
2510    /* symbol table.                                                          */
2511    /*------------------------------------------------------------------------*/
2512    loaded_module_ptr_Queue_Node* ptr;
2513    for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL; ptr = ptr->next_ptr)
2514    {
2515       if (ptr->value->file_handle == file_handle)
2516       {
2517          DLIMP_Loaded_Module *module = ptr->value;
2518          struct Elf32_Sym *symtab;
2519          int i;
2520               
2521          /*------------------------------------------------------------------*/
2522          /* Any symbol in our file's symbol table is considered a valid      */
2523          /* entry point.                                                     */
2524          /*------------------------------------------------------------------*/
2525          symtab = (struct Elf32_Sym*)module->gsymtab;
2526          *entry_pt_cnt = module->gsymnum;
2527          *entry_pt_names = DLIF_malloc(*entry_pt_cnt * sizeof(char*));
2528          for (i = 0; i < module->gsymnum; i++)
2529          {
2530             const char *sym_name = (const char *)symtab[i].st_name;
2531             **entry_pt_names = DLIF_malloc(strlen(sym_name) + 1);
2532             strcpy(**entry_pt_names,sym_name);
2533          }
2535          return TRUE;
2536       }
2537    }
2539    /*------------------------------------------------------------------------*/
2540    /* We didn't find the file we were looking for, return false.             */
2541    /*------------------------------------------------------------------------*/
2542    return FALSE;
2545 #endif
2548 #if 0
2549 /*****************************************************************************/
2550 /* DLOAD_get_entry_point()                                                   */
2551 /*                                                                           */
2552 /*    Given a file handle, return the entry point associated with that       */
2553 /*    module in the *sym_val output parameter.                               */
2554 /*                                                                           */
2555 /*****************************************************************************/
2556 BOOL DLOAD_get_entry_point(uint32_t file_handle, TARGET_ADDRESS *sym_val)
2558    /*------------------------------------------------------------------------*/
2559    /* Spin through list of loaded files until we find the file handle we     */
2560    /* are looking for.  Then return the entry point address associated with  */
2561    /* that module.                                                           */
2562    /*------------------------------------------------------------------------*/
2563    loaded_module_ptr_Queue_Node* ptr;
2564    for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL; ptr = ptr->next_ptr)
2565       if (ptr->value->file_handle == file_handle)
2566       {
2567          *sym_val = (TARGET_ADDRESS)(ptr->value->entry_point);
2568          return TRUE;
2569       }
2571    /*------------------------------------------------------------------------*/
2572    /* We didn't find the file we were looking for, return false.             */
2573    /*------------------------------------------------------------------------*/
2574    return FALSE;
2577 #endif
2580 #if 0
2581 /*****************************************************************************/
2582 /* DLOAD_query_symbol()                                                      */
2583 /*                                                                           */
2584 /*    Query the value of a global symbol from a specific file.  The value    */
2585 /*    result will be written to *sym_val.  The function returns TRUE if the  */
2586 /*    symbol was found, and FALSE if it wasn't.                              */
2587 /*                                                                           */
2588 /*****************************************************************************/
2589 BOOL DLOAD_query_symbol(uint32_t file_handle, 
2590                         const char *sym_name, 
2591                         TARGET_ADDRESS *sym_val)
2593    /*------------------------------------------------------------------------*/
2594    /* Spin through list of loaded files until we find the file handle we     */
2595    /* are looking for.  Then return the value (target address) associated    */
2596    /* with the symbol we are looking for in that file.                       */
2597    /*------------------------------------------------------------------------*/
2598    loaded_module_ptr_Queue_Node* ptr;
2599    for (ptr = DLIMP_loaded_objects.front_ptr; ptr != NULL; ptr = ptr->next_ptr)
2600    {
2601       if (ptr->value->file_handle == file_handle)
2602       {
2603          DLIMP_Loaded_Module *module = ptr->value;
2604          struct Elf32_Sym *symtab;
2605          int i;
2606               
2607          /*------------------------------------------------------------------*/
2608          /* Search through the symbol table by name.                         */
2609          /*------------------------------------------------------------------*/
2610          symtab = (struct Elf32_Sym*)module->gsymtab;
2611          for(i=0; i < module->gsymnum; i++)
2612          {
2613             if (!strcmp(sym_name, (const char *)symtab[i].st_name))
2614             {
2615                *sym_val = (TARGET_ADDRESS) symtab[i].st_value;
2616                return TRUE;
2617             }
2618          }
2619       }
2620    }
2622    /*------------------------------------------------------------------------*/
2623    /* We didn't find the file we were looking for, return false.             */
2624    /*------------------------------------------------------------------------*/
2625    return FALSE;
2628 #endif
2632 #if 0
2633 /*****************************************************************************/
2634 /* unlink_loaded_module()                                                    */
2635 /*                                                                           */
2636 /*    Unlink a loaded module data object from the list of loaded objects,    */
2637 /*    returning a pointer to the object so that it can be deconstructed.     */
2638 /*                                                                           */
2639 /*****************************************************************************/
2640 static DLIMP_Loaded_Module *unlink_loaded_module(loaded_module_ptr_Queue_Node *back_ptr,
2641                                                  loaded_module_ptr_Queue_Node *lm_node)
2643     DLIMP_Loaded_Module *loaded_module = lm_node->value;
2644     loaded_module_ptr_remove(&DLIMP_loaded_objects, lm_node->value);
2645     DLIF_free(lm_node);
2646     return loaded_module;
2649 #endif
2651 #if 0
2653 /*****************************************************************************/
2654 /* execute_module_termination()                                              */
2655 /*                                                                           */
2656 /*    Execute termination functions associated with this loaded module.      */
2657 /*    Termination functions are called in the reverse order as their         */
2658 /*    corresponding initialization functions.                                */
2659 /*                                                                           */
2660 /*****************************************************************************/
2661 static void execute_module_termination(DLIMP_Loaded_Module *loaded_module)
2663    /*------------------------------------------------------------------------*/
2664    /* If a DT_FINI_ARRAY dynamic tag was encountered for this module, spin   */
2665    /* through the array in reverse order, calling each function address      */
2666    /* stored in the array.                                                   */
2667    /*------------------------------------------------------------------------*/
2668    if (loaded_module->fini_arraysz != 0)
2669    {
2670       /*---------------------------------------------------------------------*/
2671       /* Now make a loader-accessible copy of the .fini_array section.       */
2672       /*---------------------------------------------------------------------*/
2673       int32_t i;
2674       int32_t num_fini_fcns = loaded_module->fini_arraysz/sizeof(TARGET_ADDRESS);
2675       TARGET_ADDRESS *fini_array_buf = (TARGET_ADDRESS *)
2676                                       DLIF_malloc(loaded_module->fini_arraysz);
2678       DLIF_read(fini_array_buf, 1, loaded_module->fini_arraysz, 
2679                                     (TARGET_ADDRESS)loaded_module->fini_array);
2681       /*---------------------------------------------------------------------*/
2682       /* Now spin through the array in reverse order, executing each         */
2683       /* termination function whose address occupies an entry in the array.  */
2684       /*---------------------------------------------------------------------*/
2685       for (i = num_fini_fcns - 1; i >= 0; i--)
2686          DLIF_execute((TARGET_ADDRESS)(fini_array_buf[i]));
2688       DLIF_free(fini_array_buf);
2689    }
2691    /*------------------------------------------------------------------------*/
2692    /* If a DT_FINI dynamic tag was encountered for this module, call the     */
2693    /* function indicated by the tag's value to complete the termination      */
2694    /* process for this module.                                               */
2695    /*------------------------------------------------------------------------*/
2696    if (loaded_module->fini != NULL)
2697       DLIF_execute((TARGET_ADDRESS)loaded_module->fini);
2700 #endif
2702 #if 0
2703 /*****************************************************************************/
2704 /* remove_loaded_module()                                                    */
2705 /*                                                                           */
2706 /*    Find and unlink a loaded module data object from the list of loaded    */
2707 /*    objects, then call its destructor to free the host memory associated   */
2708 /*    with the loaded module and all of its loaded segments.                 */
2709 /*                                                                           */
2710 /*****************************************************************************/
2711 static void remove_loaded_module(loaded_module_ptr_Queue_Node *lm_node)
2713     DLIMP_Loaded_Module *lm_object = NULL;
2714     loaded_module_ptr_Queue_Node *back_ptr = NULL;
2716     if (lm_node != DLIMP_loaded_objects.front_ptr)
2717        for (back_ptr = DLIMP_loaded_objects.front_ptr;
2718             back_ptr->next_ptr != lm_node;
2719             back_ptr = back_ptr->next_ptr);
2721     lm_object = unlink_loaded_module(back_ptr, lm_node);
2723     delete_DLIMP_Loaded_Module(&lm_object);
2726 #endif
2729 #if 0
2730 /*****************************************************************************/
2731 /* DLOAD_unload()                                                            */
2732 /*                                                                           */
2733 /*    Unload specified module (identified by its file handle) from target    */
2734 /*    memory.  Free up any target memory that was allocated for the module's */
2735 /*    segments and also any host heap memory that was allocated for the      */
2736 /*    internal module and segment data structures.                           */
2737 /*                                                                           */
2738 /*    Return TRUE if program entry is actually destroyed.  This is a way of  */
2739 /*    communicating to the client when it needs to actually remove debug     */
2740 /*    information associated with this module (so that client does not have  */
2741 /*    to maintain a use count that mirrors the program entry).               */
2742 /*                                                                           */
2743 /*****************************************************************************/
2744 BOOL DLOAD_unload(uint32_t handle)
2746    loaded_module_ptr_Queue_Node* lm_node;
2748    for (lm_node = DLIMP_loaded_objects.front_ptr; lm_node != NULL;
2749         lm_node = lm_node->next_ptr)
2750    {
2751       if (lm_node->value->file_handle == handle)
2752       {
2753          --lm_node->value->use_count;
2754          if (lm_node->value->use_count == 0)
2755          {
2756             DLIMP_Loaded_Module *loaded_module = 
2757                                          (DLIMP_Loaded_Module *)lm_node->value;
2758             int j;
2759             int *dep_file_handles;
2761             /*---------------------------------------------------------------*/
2762             /* Termination functions need to be executed in the reverse      */
2763             /* order as the corresponding initialization functions, so       */
2764             /* before we go unload this module's dependents, we need to      */
2765             /* perform the user/global/static termination functions          */
2766             /* associated with this module.                                  */
2767             /*---------------------------------------------------------------*/
2768             execute_module_termination(loaded_module);
2770             /*---------------------------------------------------------------*/
2771             /* Unload dependent modules via the client. Client needs to know */
2772             /* when a dependent gets unloaded so that it can update debug    */
2773             /* information.                                                  */
2774             /*---------------------------------------------------------------*/
2775             dep_file_handles = (int*)(loaded_module->dependencies.buf);
2776             for (j = 0; j < loaded_module->dependencies.size; j++)
2777                DLIF_unload_dependent(dep_file_handles[j]);
2779             /*---------------------------------------------------------------*/
2780             /* Find the predecessor node of the value we're deleting,        */
2781             /* because its next_ptr will need to be updated.                 */
2782             /*                                                               */
2783             /* We can't keep a back pointer around because                   */
2784             /* DLIF_unload_dependent() might free that node, making our      */
2785             /* pointer invalid.  Turn the Queue template into a doubly       */
2786             /* linked list if this overhead becomes a problem.               */
2787             /*---------------------------------------------------------------*/
2788             remove_loaded_module(lm_node);
2789             
2790             /*---------------------------------------------------------------*/
2791             /* If all loaded objects have been unloaded (including the       */
2792             /* base image), then reset the machine to the default target     */
2793             /* machine.  This only has an effect when multiple targets are   */
2794             /* supported, in which case the machine is set to EM_NONE.       */
2795             /*---------------------------------------------------------------*/
2796             if (DLIMP_loaded_objects.front_ptr == NULL)
2797             {
2798                 DLOAD_TARGET_MACHINE = DLOAD_DEFAULT_TARGET_MACHINE;
2799             }
2801             return TRUE;
2802          }
2803       }
2804    }
2806    return FALSE;
2809 #endif
2812 #if 0
2813 /*****************************************************************************/
2814 /* DLOAD_load_symbols()                                                      */
2815 /*                                                                           */
2816 /*    Load the symbols from the given file and make symbols available for    */
2817 /*    global symbol linkage.                                                 */
2818 /*                                                                           */
2819 /*****************************************************************************/
2820 int32_t DLOAD_load_symbols(LOADER_FILE_DESC *fd)
2822    DLIMP_Dynamic_Module *dyn_module = new_DLIMP_Dynamic_Module(fd);
2823    DLIMP_Loaded_Module *loaded_module = NULL;
2825    /*------------------------------------------------------------------------*/
2826    /* Ensure we have a valid dynamic module object from the constructor.     */
2827    /*------------------------------------------------------------------------*/
2828    if (!dyn_module)
2829        return 0;
2831    /*------------------------------------------------------------------------*/
2832    /* If no access to a program was provided, there is nothing to do.        */
2833    /*------------------------------------------------------------------------*/
2834    if (!fd)
2835    {
2836       DLIF_error(DLET_FILE, "Missing file specification.\n");
2837       return 0;
2838    }
2840    /*------------------------------------------------------------------------*/
2841    /* Record argc and argv pointers with the dynamic module record.          */
2842    /*------------------------------------------------------------------------*/
2843    dyn_module->argc = 0;
2844    dyn_module->argv = NULL;
2846    /*------------------------------------------------------------------------*/
2847    /* Read file headers and dynamic information into dynamic module.         */
2848    /*------------------------------------------------------------------------*/
2849    if (!dload_headers(fd, dyn_module))
2850       return 0;
2852    /*------------------------------------------------------------------------*/
2853    /* Find the dynamic segment, if there is one, and read dynamic            */
2854    /* information from the ELF object file into the dynamic module data      */
2855    /* structure associated with this file.                                   */
2856    /*------------------------------------------------------------------------*/
2857    if (!dload_dynamic_segment(fd, dyn_module))
2858       return 0;
2860    /*------------------------------------------------------------------------*/
2861    /* Perform sanity checking on the read-in ELF file.                       */
2862    /*------------------------------------------------------------------------*/
2863    if (!is_valid_elf_object_file(fd, dyn_module))
2864    {
2865       DLIF_error(DLET_FILE, "Attempt to load invalid ELF file, '%s'.\n",
2866                     dyn_module->name);
2867       return 0;
2868    }
2870    /*------------------------------------------------------------------------*/
2871    /* Initialize internal ELF module and segment structures.  Sets           */
2872    /* loaded_module in *dyn_module.  This also deals with assigning a file   */
2873    /* handle and bumping file handle counter.                                */
2874    /*------------------------------------------------------------------------*/
2875    initialize_loaded_module(dyn_module);
2877    /*------------------------------------------------------------------------*/
2878    /* Add this module to the loaded module queue.                            */
2879    /* Detach the loaded module object from the dynamic module thath created  */
2880    /* it. Ownership of the host memory allocated for the loaded module       */
2881    /* object now belongs to the DLIMP_loaded_objects list.                   */
2882    /*------------------------------------------------------------------------*/
2883    loaded_module_ptr_enqueue(&DLIMP_loaded_objects, dyn_module->loaded_module);
2885    /*------------------------------------------------------------------------*/
2886    /* Register a DSBT index request for this module and update its own copy  */
2887    /* of the DSBT with the contents of the client's master DSBT.             */
2888    /*------------------------------------------------------------------------*/
2889    if (is_dsbt_module(dyn_module))
2890    {
2891       dynamic_module_ptr_push(&DLIMP_dependency_stack, dyn_module);
2892       DLIF_register_dsbt_index_request(dyn_module->name,
2893                                        dyn_module->loaded_module->file_handle,
2894                                        dyn_module->dsbt_index);
2895       DLIF_assign_dsbt_indices();
2896       DLIF_update_all_dsbts();
2897       dynamic_module_ptr_pop(&DLIMP_dependency_stack);
2898    }
2899    
2900    /*------------------------------------------------------------------------*/
2901    /* Ownership of the host memory allocated for the loaded module object is */
2902    /* transferred to the DLIMP_loaded_objects list. Free up the host memory  */
2903    /* for the dynamic module that created the loaded module object. Just     */
2904    /* call the destructor function for DLIMP_Dynamic_Module.                 */
2905    /*------------------------------------------------------------------------*/
2906    loaded_module = detach_loaded_module(dyn_module);
2907    delete_DLIMP_Dynamic_Module(&dyn_module);
2909    /*------------------------------------------------------------------------*/
2910    /* Return a file handle so that the client can match this file to an ID.  */
2911    /*------------------------------------------------------------------------*/
2912    return loaded_module->file_handle;
2915 #endif
2917 /*****************************************************************************/
2918 /* DSBT Support Functions                                                    */
2919 /*****************************************************************************/
2921 #if 0
2922 /*****************************************************************************/
2923 /* DLOAD_get_dsbt_size()                                                     */
2924 /*                                                                           */
2925 /*    Find the amount of space allocated for the specified module's DSBT.    */
2926 /*    It must be big enough to hold a copy of the master DSBT or the client  */
2927 /*    will flag an error. Those modules whose DSBT size is zero are assumed  */
2928 /*    to not be using the DSBT model.                                        */
2929 /*                                                                           */
2930 /*****************************************************************************/
2931 uint32_t DLOAD_get_dsbt_size(int32_t file_handle)
2933    dynamic_module_ptr_Stack_Node *ptr;
2934    for (ptr = DLIMP_dependency_stack.top_ptr; ptr != NULL; ptr = ptr->next_ptr)
2935    {
2936       DLIMP_Dynamic_Module *dmp = ptr->value;
2937       if (dmp->loaded_module->file_handle == file_handle)
2938          return dmp->dsbt_size;
2939    }
2941    return 0;
2944 #endif
2946 #if 0
2947 /*****************************************************************************/
2948 /* DLOAD_get_static_base()                                                   */
2949 /*                                                                           */
2950 /*    Look up static base symbol associated with the specified module.       */
2951 /*                                                                           */
2952 /*****************************************************************************/
2953 BOOL DLOAD_get_static_base(int32_t file_handle, TARGET_ADDRESS *static_base)
2955    dynamic_module_ptr_Stack_Node *ptr;
2956    for (ptr = DLIMP_dependency_stack.top_ptr; ptr != NULL; ptr = ptr->next_ptr)
2957    {
2958       DLIMP_Dynamic_Module *dmp = ptr->value;
2959       if (dmp->loaded_module->file_handle == file_handle)
2960       {
2961          BOOL stat = DLSYM_lookup_local_symtab("__TI_STATIC_BASE", 
2962                                                dmp->symtab, dmp->symnum, 
2963                                                (Elf32_Addr *)static_base);
2964          return stat;
2965       }
2966    }
2968    return FALSE;
2971 #endif
2974 #if 0
2975 /*****************************************************************************/
2976 /* DLOAD_get_dsbt_base()                                                     */
2977 /*                                                                           */
2978 /*    Look up address of DSBT for the specified module.                      */
2979 /*                                                                           */
2980 /*****************************************************************************/
2981 BOOL DLOAD_get_dsbt_base(int32_t file_handle, TARGET_ADDRESS *dsbt_base)
2983    dynamic_module_ptr_Stack_Node *ptr;
2984    for (ptr = DLIMP_dependency_stack.top_ptr; ptr != NULL; ptr = ptr->next_ptr)
2985    {
2986       DLIMP_Dynamic_Module *dmp = ptr->value;
2987       if (dmp->loaded_module->file_handle == file_handle)
2988       {
2989          *dsbt_base = (TARGET_ADDRESS)dmp->dyntab[dmp->dsbt_base_tagidx].d_un.d_ptr;
2990          return TRUE;
2991       }
2992    }
2994    return FALSE;
2997 #endif