Utils: Remove the v1 firmware generator code
[gstreamer-omap:sysbios-rpmsg.git] / src / utils.mmap / elfload / dload.c
1 /*
2  *  Syslink-IPC for TI OMAP Processors
3  *
4  *  Copyright (c) 2008-2010, Texas Instruments Incorporated
5  *  All rights reserved.
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *
11  *  *  Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *
14  *  *  Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *
18  *  *  Neither the name of Texas Instruments Incorporated nor the names of
19  *     its contributors may be used to endorse or promote products derived
20  *     from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
26  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 /*****************************************************************************/
35 /* dload.c                                                                   */
36 /*                                                                           */
37 /* Core Dynamic Loader reference implementation.                             */
38 /*                                                                           */
39 /* This implementation of the core dynamic loader is platform independent,   */
40 /* but it is object file format dependent.  In particular, this              */
41 /* implementation supports ELF object file format.                           */
42 /*****************************************************************************/
43
44 #include <limits.h>
45 #include <inttypes.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <time.h>
50
51 #include "ArrayList.h"
52 #include "Queue.h"
53
54 #include "symtab.h"
55 #include "dload_endian.h"
56 #include "elf32.h"
57 #include "dload.h"
58 #include "relocate.h"
59 #include "dload_api.h"
60
61 #ifdef ARM_TARGET
62 #include "arm_dynamic.h"
63 #endif
64
65 #ifdef C60_TARGET
66 #include "c60_dynamic.h"
67 #endif
68
69 /*---------------------------------------------------------------------------*/
70 /* Contains objects (type DLIMP_Loaded_Module) that the system has loaded    */
71 /* into target memory.                                                       */
72 /*---------------------------------------------------------------------------*/
73 TYPE_QUEUE_IMPLEMENTATION(DLIMP_Loaded_Module*, loaded_module_ptr)
74
75 /*---------------------------------------------------------------------------*/
76 /* Global flag to control debug output.                                      */
77 /*---------------------------------------------------------------------------*/
78 #if LOADER_DEBUG
79 Bool debugging_on = 1;
80 #endif
81
82
83 /*---------------------------------------------------------------------------*/
84 /* Global flag to enable profiling.                                          */
85 /*---------------------------------------------------------------------------*/
86 #if LOADER_DEBUG || LOADER_PROFILE
87 Bool profiling_on = 0;
88 #endif
89
90 #if LOADER_DEBUG || LOADER_PROFILE
91 int DLREL_relocations;
92 time_t DLREL_total_reloc_time;
93 #endif
94
95
96 /*---------------------------------------------------------------------------*/
97 /* Dependency Graph Queue - FIFO queue of dynamic modules that are loaded    */
98 /* when client asks to load a dynamic executable or library. Note that       */
99 /* dependents that have already been loaded with another module will not     */
100 /* appear on this queue.                                                     */
101 /*---------------------------------------------------------------------------*/
102 TYPE_STACK_IMPLEMENTATION(DLIMP_Dynamic_Module*, dynamic_module_ptr)
103
104 /*---------------------------------------------------------------------------*/
105 /* Support for profiling performance of dynamic loader core.                 */
106 /*---------------------------------------------------------------------------*/
107 #if LOADER_PROFILE || LOADER_DEBUG
108 static clock_t cycle0 = 0;
109 static clock_t cycle_end = 0;
110 #define profile_start_clock() (cycle0 = clock())
111 #define profile_stop_clock()  (cycle_end = clock())
112 #define profile_cycle_count() (cycle_end - cycle0)
113 #endif
114
115 /*---------------------------------------------------------------------------*/
116 /* DLOAD_create()                                                            */
117 /*                                                                           */
118 /*    Create an instance of the dynamic loader core.                         */
119 /*                                                                           */
120 /*    client_handle:  Private client token to be returned during select DLIF */
121 /*                   function calls.                                         */
122 /*                                                                           */
123 /*    returns: an opaque DLOAD core loader handle, identifying this instance.*/
124 /*                                                                           */
125 /*---------------------------------------------------------------------------*/
126 DLOAD_HANDLE  DLOAD_create(void * client_handle)
127 {
128     LOADER_OBJECT     * pLoaderObject;
129
130     pLoaderObject = DLIF_malloc(sizeof(LOADER_OBJECT));
131
132     /* Fill out the Loader Object: */
133     if (pLoaderObject != NULL) {
134         /*-------------------------------------------------------------------*/
135         /* Set up initial objects_loading queue.                             */
136         /*-------------------------------------------------------------------*/
137         AL_initialize(&(pLoaderObject->DLIMP_module_dependency_list),
138                       sizeof (const char*), 1);
139
140         /* Initialize Loaded Module Ptr Queue */
141         loaded_module_ptr_initialize_queue(&pLoaderObject->DLIMP_loaded_objects);
142
143         /* Initialize Dynamic Module Ptr Stack */
144         dynamic_module_ptr_initialize_stack(&pLoaderObject->DLIMP_dependency_stack);
145
146         pLoaderObject->file_handle = 1;
147
148         pLoaderObject->DLOAD_TARGET_MACHINE = DLOAD_DEFAULT_TARGET_MACHINE;
149
150         /* Store client token, so it can be handed back during DLIF calls */
151         pLoaderObject->client_handle = client_handle;
152     }
153
154     return((DLOAD_HANDLE)pLoaderObject);
155 }
156
157 /*---------------------------------------------------------------------------*/
158 /* DLOAD_destroy()                                                           */
159 /*                                                                           */
160 /*    Remove an instance of the dynamic loader core, and free all resources  */
161 /*    allocated during DLOAD_create().                                       */
162 /*                                                                           */
163 /*    client_handle:  Private client token to be returned during select DLIF */
164 /*                   function calls.                                         */
165 /*    Preconditions: 1) handle must be valid.                                */
166 /*                   2) Loader instance must be in "UNLOADED" state.         */
167 /*                                                                           */
168 /*---------------------------------------------------------------------------*/
169 void  DLOAD_destroy(DLOAD_HANDLE handle)
170 {
171     LOADER_OBJECT     * pLoaderObject;
172
173     pLoaderObject = (LOADER_OBJECT *)handle;
174
175     AL_destroy(&(pLoaderObject->DLIMP_module_dependency_list));
176
177     /* Free the instance object */
178     DLIF_free (pLoaderObject);
179 }
180
181 /*****************************************************************************/
182 /* DLIMP_get_first_dyntag()                                                  */
183 /*                                                                           */
184 /*    Return value for first tag entry in the given dynamic table whose      */
185 /*    tag type matches the given key.                                        */
186 /*                                                                           */
187 /*****************************************************************************/
188 uint32_t DLIMP_get_first_dyntag(int tag, struct Elf32_Dyn* dyn_table)
189 {
190     /*-----------------------------------------------------------------------*/
191     /* Spin through dynamic segment looking for a specific dynamic tag.      */
192     /* Return the value associated with the tag, if the tag is found.        */
193     /*-----------------------------------------------------------------------*/
194     struct Elf32_Dyn *dtp = dyn_table;
195     while (dtp->d_tag != DT_NULL)
196     {
197         if (dtp->d_tag == tag) return dtp->d_un.d_val;
198         else dtp++;
199     }
200
201     /*-----------------------------------------------------------------------*/
202     /* Tag wasn't found, return a known bogus value for the tag.             */
203     /*-----------------------------------------------------------------------*/
204     return INT_MAX;
205 }
206
207 /*****************************************************************************/
208 /* dload_and_allocate_dependencies()                                         */
209 /*                                                                           */
210 /*    If not already loaded, load each dependent file identified in the      */
211 /*    dynamic segment with a DT_NEEDED tag.  Dependent files are listed in   */
212 /*    order and should be loaded in the same order that they appear in the   */
213 /*    dynamic segment.                                                       */
214 /*                                                                           */
215 /*****************************************************************************/
216 static BOOL dload_and_allocate_dependencies(DLOAD_HANDLE handle,
217                                             DLIMP_Dynamic_Module *dyn_module)
218 {
219     /*-----------------------------------------------------------------------*/
220     /* Spin through each dynamic tag entry in the dynamic segment.           */
221     /*-----------------------------------------------------------------------*/
222     struct Elf32_Dyn* dyn_nugget = dyn_module->dyntab;
223     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
224
225 #if LOADER_DEBUG
226     if (debugging_on)
227         DLIF_trace("Starting dload_and_allocate_dependencies() for %s ...\n",
228                    dyn_module->name);
229 #endif
230
231     while(dyn_nugget->d_tag != DT_NULL)
232     {
233         /*-------------------------------------------------------------------*/
234         /* For each DT_NEEDED dynamic tag that we find in the dynamic        */
235         /* segment, load the dependent file identified by the so_name value  */
236         /* attached to the DT_NEEDED dynamic tag.                            */
237         /*-------------------------------------------------------------------*/
238         if (dyn_nugget->d_tag == DT_NEEDED)
239         {
240             loaded_module_ptr_Queue_Node* ptr;
241
242 #if LOADER_DEBUG
243             if (debugging_on)
244                 DLIF_trace("Found DT_NEEDED: %s\n",
245                            dyn_module->strtab+dyn_nugget->d_un.d_val);
246 #endif
247
248             /*---------------------------------------------------------------*/
249             /* Find out if the file named by the DT_NEEDED tag has already   */
250             /* been loaded.  If it has, then we only have to bump the use    */
251             /* count of the named dependent file.                            */
252             /*---------------------------------------------------------------*/
253             for (ptr = pHandle->DLIMP_loaded_objects.front_ptr; ptr != NULL;
254                  ptr = ptr->next_ptr)
255             {
256                 if (!strcmp(ptr->value->name,
257                             dyn_module->strtab + dyn_nugget->d_un.d_val))
258                 {
259                     ptr->value->use_count++;
260                     AL_append(&(dyn_module->loaded_module->dependencies),
261                               &(ptr->value->file_handle));
262                     break;
263                 }
264             }
265
266             /*---------------------------------------------------------------*/
267             /* If the named dependent file has not been loaded, then we ask  */
268             /* the client to invoke a load of the dependent file on our      */
269             /* behalf.                                                       */
270             /*---------------------------------------------------------------*/
271             if (ptr == NULL)
272             {
273                 int32_t dependent_handle = DLIF_load_dependent(
274                                                        pHandle->client_handle,
275                                                        dyn_module->strtab +
276                                                        dyn_nugget->d_un.d_val);
277                 AL_append(&(dyn_module->loaded_module->dependencies),
278                           &dependent_handle);
279                 if (dependent_handle == 0) return FALSE;
280             }
281         }
282
283         dyn_nugget++;
284     }
285
286 #if LOADER_DEBUG
287     if (debugging_on)
288         DLIF_trace("Finished dload_and_allocate_dependencies() for %s\n",
289                    dyn_module->name);
290 #endif
291
292    return TRUE;
293 }
294
295 /*****************************************************************************/
296 /* load_object()                                                             */
297 /*                                                                           */
298 /*    Finish the process of loading an object file.                          */
299 /*                                                                           */
300 /*****************************************************************************/
301 static int load_object(LOADER_FILE_DESC *fd, DLIMP_Dynamic_Module *dyn_module)
302 {
303     /*-----------------------------------------------------------------------*/
304     /* With the dynamic loader already running on the target, we are able to */
305     /* relocate directly into target memory, so there is nothing more to be  */
306     /* done (at least in the bare-metal dynamic linking ABI model).          */
307     /*-----------------------------------------------------------------------*/
308     return 1;
309 }
310
311 /*****************************************************************************/
312 /* initialize_loaded_module()                                                */
313 /*                                                                           */
314 /*    Initialize DLIMP_Loaded_Module internal data object associated with a  */
315 /*    dynamic module.  This function will also set up a queue of             */
316 /*    DLIMP_Loaded_Segment(s) associated with the loaded module.             */
317 /*    This function is called as we are getting ready to actually load the   */
318 /*    object file contents into target memory.  Each segment will get a      */
319 /*    target memory request that it can use to ask the client for target     */
320 /*    memory space.  This function will also assign a file handle to the     */
321 /*    loaded module.                                                         */
322 /*                                                                           */
323 /*---------------------------------------------------------------------------*/
324 /*                                                                           */
325 /* In applications that use the DSBT model, this function will also need to  */
326 /* negotiate the module's DSBT index with the client.                        */
327 /*                                                                           */
328 /*****************************************************************************/
329 static void initialize_loaded_module(DLOAD_HANDLE handle,
330                                      DLIMP_Dynamic_Module *dyn_module)
331 {
332     int i;
333     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
334
335     /*-----------------------------------------------------------------------*/
336     /* Allocate a DLIMP_Loaded_Module data structure for the specified ELF   */
337     /* file and assign a file handle for it (bumping the file handle counter */
338     /* as we go).                                                            */
339     /*-----------------------------------------------------------------------*/
340     DLIMP_Loaded_Module *loaded_module =
341           dyn_module->loaded_module = DLIF_malloc(sizeof(DLIMP_Loaded_Module));
342
343    if(loaded_module == NULL) {
344 #if LOADER_DEBUG || LOADER_PROFILE
345       if(debugging_on)
346          DLIF_error(DLET_MISC, "Error allocating memory %d...\n",__LINE__);
347 #endif
348       exit(1);
349    }
350 #if LOADER_DEBUG || LOADER_PROFILE
351     /*-----------------------------------------------------------------------*/
352     /* Start clock on initialization of loaded module object.                */
353     /*-----------------------------------------------------------------------*/
354     if (debugging_on || profiling_on)
355     {
356         DLIF_trace("Starting initialize_loaded_module() ...\n");
357         if (profiling_on) profile_start_clock();
358     }
359 #endif
360
361     loaded_module->name = DLIF_malloc(strlen(dyn_module->name) + 1);
362     if (NULL == loaded_module->name) {
363         DLIF_error(DLET_MISC, "Error allocating memory %d...\n",__LINE__);
364         exit(1);
365     }
366     strcpy(loaded_module->name, dyn_module->name);
367
368     loaded_module->file_handle = pHandle->file_handle++;
369     loaded_module->direct_dependent_only = dyn_module->direct_dependent_only;
370     loaded_module->use_count = 1;
371
372     /*-----------------------------------------------------------------------*/
373     /* In case we wrapped around the file handle, return error.              */
374     /*-----------------------------------------------------------------------*/
375     if (pHandle->file_handle == 0)
376         DLIF_error(DLET_MISC, "DLOAD File handle overflowed.\n");
377
378     /*-----------------------------------------------------------------------*/
379     /* Initially the loaded module does not have access to its global        */
380     /* symbols.  These need to be copied from the dynamic module (see call   */
381     /* to DLSYM_copy_globals() below).                                       */
382     /*                                                                       */
383     /* THESE INITIALIZATIONS SHOULD BE MOVED TO AN INIT ROUTINE FOR THE      */
384     /* LOADED MODULE                                                         */
385     /*-----------------------------------------------------------------------*/
386     loaded_module->gsymtab = NULL;
387     loaded_module->gstrtab = NULL;
388     loaded_module->gsymnum = loaded_module->gstrsz = 0;
389
390     /*-----------------------------------------------------------------------*/
391     /* Initialize the Array_List of dependencies.                            */
392     /*-----------------------------------------------------------------------*/
393     AL_initialize(&(loaded_module->dependencies), sizeof(int), 1);
394
395     if (dyn_module->symtab)
396         DLSYM_copy_globals(dyn_module);
397
398     /*-----------------------------------------------------------------------*/
399     /* Initialize the module loaded segments Array_List.                     */
400     /*-----------------------------------------------------------------------*/
401     AL_initialize(&(loaded_module->loaded_segments),
402                   sizeof(DLIMP_Loaded_Segment), dyn_module->phnum);
403
404     /*-----------------------------------------------------------------------*/
405     /* Spin thru segment headers and process each load segment encountered.  */
406     /*-----------------------------------------------------------------------*/
407     for (i = 0; i < dyn_module->phnum; i++)
408         if (dyn_module->phdr[i].p_type == PT_LOAD)
409         {
410             /*---------------------------------------------------------------*/
411             /* Note that this is parallel to and does not supplant the ELF   */
412             /* phdr tables.                                                  */
413             /*---------------------------------------------------------------*/
414             DLIMP_Loaded_Segment seg;
415             seg.obj_desc = DLIF_malloc(sizeof(struct DLOAD_MEMORY_SEGMENT));
416             seg.phdr.p_vaddr = dyn_module->phdr[i].p_vaddr;
417             seg.phdr.p_offset = dyn_module->phdr[i].p_offset;
418             seg.modified = 0;
419             if(seg.obj_desc) {
420                 seg.obj_desc->target_page = 0; /*not used*/
421                 seg.phdr.p_filesz = seg.obj_desc->objsz_in_bytes
422                                   = dyn_module->phdr[i].p_filesz;
423                 seg.phdr.p_memsz = seg.obj_desc->memsz_in_bytes
424                                  = dyn_module->phdr[i].p_memsz;
425             }
426             seg.phdr.p_align = dyn_module->phdr[i].p_align;
427             seg.phdr.p_flags = dyn_module->phdr[i].p_flags;
428             seg.input_vaddr = 0;
429             seg.phdr.p_paddr = 0;
430             seg.phdr.p_type = PT_LOAD;
431             seg.reloc_offset = 0;
432             AL_append(&(loaded_module->loaded_segments), &seg);
433 #if LOADER_DEBUG
434             if (debugging_on)
435                 DLIF_trace("%s:seg.phdr.p_vaddr 0x%x\n",__func__,
436                            seg.phdr.p_vaddr);
437 #endif
438         }
439
440     /*-----------------------------------------------------------------------*/
441     /* Initialize the DSO termination information for this module.           */
442     /* It will be copied over from the enclosing dyn_module object when      */
443     /* placement is completed and dyn_module's local copy of the dynamic     */
444     /* table is updated.                                                     */
445     /*-----------------------------------------------------------------------*/
446     loaded_module->fini_array = (Elf32_Addr)NULL;
447     loaded_module->fini_arraysz = 0;
448     loaded_module->fini = (Elf32_Addr) NULL;
449
450 #if LOADER_DEBUG || LOADER_PROFILE
451     if (debugging_on || profiling_on)
452     {
453         DLIF_trace("Finished initialize_loaded_module()\n");
454         if (profiling_on)
455         {
456             profile_stop_clock();
457             DLIF_trace("Took %d cycles.\n", (int32_t)profile_cycle_count());
458         }
459     }
460 #endif
461
462 }
463
464 /*****************************************************************************/
465 /* load_static_segment()                                                     */
466 /*                                                                           */
467 /*    The core dynamic loader requires that a statically linked executable   */
468 /*    be placed in target memory at the location that was determined during  */
469 /*    the static link that created the executable.  Failure to get the       */
470 /*    required target memory where the static executable is to be loaded     */
471 /*    will cause the dynamic loader to emit an error and abort the load.     */
472 /*                                                                           */
473 /*****************************************************************************/
474 static BOOL load_static_segment(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd,
475                                 DLIMP_Dynamic_Module *dyn_module)
476 {
477     int i;
478     DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
479                                (dyn_module->loaded_module->loaded_segments.buf);
480     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
481
482 #if LOADER_DEBUG
483     if (debugging_on) {
484         DLIF_trace("dynmodule is 0x%x\n",(UInt32) dyn_module);
485         DLIF_trace("loaded_module is 0x%x\n",(UInt32)dyn_module->loaded_module);
486         DLIF_trace("loaded_segments is 0x%x\n",
487                    (UInt32)&dyn_module->loaded_module->loaded_segments);
488         DLIF_trace("seg is 0x%x\n",
489                    (UInt32)dyn_module->loaded_module->loaded_segments.buf);
490     }
491 #endif
492
493     /*-----------------------------------------------------------------------*/
494     /* For each segment in the loaded module, build up a target memory       */
495     /* request for the segment, get rights to target memory where we want    */
496     /* to load the segment from the client, then get the client to write the */
497     /* segment contents out to target memory to the appropriate address.     */
498     /*-----------------------------------------------------------------------*/
499
500     for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
501     {
502         struct DLOAD_MEMORY_REQUEST targ_req;
503         seg[i].obj_desc->target_page = 0;
504         targ_req.flags = 0;
505
506         /*-------------------------------------------------------------------*/
507         /* This is a static executable.  DLIF_allocate should give us the    */
508         /* address we ask for or fail.                                       */
509         /*-------------------------------------------------------------------*/
510         if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
511
512         targ_req.align = seg[i].phdr.p_align;
513         seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
514         targ_req.flags &= ~DLOAD_SF_relocatable;
515         targ_req.fp = fd;
516         targ_req.segment = seg[i].obj_desc;
517         targ_req.offset = seg[i].phdr.p_offset;
518         targ_req.flip_endian = dyn_module->wrong_endian;
519 #if LOADER_DEBUG
520         if (debugging_on) {
521             DLIF_trace("============================================\n");
522             DLIF_trace("targ_req.align %d\n", targ_req.align);
523             DLIF_trace("targ_req.segment 0x%x\n", (UInt32) targ_req.segment);
524             DLIF_trace("targ_req.offset 0x%x\n", targ_req.offset);
525             DLIF_trace("targ_req.flags 0x%x\n", targ_req.flags);
526         }
527 #endif
528         /*-------------------------------------------------------------------*/
529         /* Ask the client side of the dynamic loader to allocate target      */
530         /* memory for this segment to be loaded into.                        */
531         /*-------------------------------------------------------------------*/
532         if (!DLIF_allocate(pHandle->client_handle, &targ_req)) return FALSE;
533
534         /*-------------------------------------------------------------------*/
535         /* If there is any initialized data in the segment, we'll first write*/
536         /* it into a host writable buffer (DLIF_copy()) and then flush it to */
537         /* target memory.                                                    */
538         /*-------------------------------------------------------------------*/
539         if (seg[i].phdr.p_filesz)
540         {
541             DLIF_copy(pHandle->client_handle, &targ_req);
542             DLIF_write(pHandle->client_handle, &targ_req);
543         }
544     }
545
546     return TRUE;
547 }
548
549 /*****************************************************************************/
550 /* relocate_target_dynamic_tag_info()                                        */
551 /*                                                                           */
552 /*    Update a target specific dynamic tag value that happens to be a        */
553 /*    virtual address of a section. Returns TRUE if the tag was updated or   */
554 /*    is not a virtual address and FALSE if it was not successfully updated  */
555 /*    or was not recognized.                                                 */
556 /*****************************************************************************/
557 static BOOL relocate_target_dynamic_tag_info(DLIMP_Dynamic_Module *dyn_module,
558                                              int i)
559 {
560 #ifdef ARM_TARGET
561     if (is_arm_module(&dyn_module->fhdr))
562         return DLDYN_arm_relocate_dynamic_tag_info(dyn_module, i);
563 #endif
564
565 #ifdef C60_TARGET
566     if (is_c60_module(&dyn_module->fhdr))
567         return DLDYN_c60_relocate_dynamic_tag_info(dyn_module, i);
568 #endif
569
570    return FALSE;
571 }
572
573 /*****************************************************************************/
574 /* DLIMP_update_dyntag_section_address()                                     */
575 /*                                                                           */
576 /*    Given the index of a dynamic tag which we happen to know points to a   */
577 /*    section address, find the program header table entry associated with   */
578 /*    the specified address and update the tag value with the real address   */
579 /*    of the section.                                                        */
580 /*                                                                           */
581 /*****************************************************************************/
582 BOOL DLIMP_update_dyntag_section_address(DLIMP_Dynamic_Module *dyn_module,
583                                          int32_t i)
584 {
585     int j;
586     DLIMP_Loaded_Segment *seg = (DLIMP_Loaded_Segment *)
587                               (dyn_module->loaded_module->loaded_segments.buf);
588     for (j = 0; j < dyn_module->loaded_module->loaded_segments.size; j++)
589     {
590         if ((dyn_module->dyntab[i].d_un.d_ptr >= seg[j].input_vaddr) &&
591             (dyn_module->dyntab[i].d_un.d_ptr <
592              (seg[j].input_vaddr + seg[j].phdr.p_memsz)))
593         {
594             dyn_module->dyntab[i].d_un.d_ptr +=
595                                     (seg[j].phdr.p_vaddr - seg[j].input_vaddr);
596             return TRUE;
597         }
598     }
599
600     return FALSE;
601 }
602
603 /*****************************************************************************/
604 /* relocate_dynamic_tag_info()                                               */
605 /*                                                                           */
606 /*    Once segment allocation has been completed, we'll need to go through   */
607 /*    the dynamic table and update any tag values that happen to be virtual  */
608 /*    addresses of segments (DT_C6000_DSBT_BASE, for example).               */
609 /*                                                                           */
610 /*****************************************************************************/
611 static BOOL relocate_dynamic_tag_info(LOADER_FILE_DESC *fd,
612                                       DLIMP_Dynamic_Module *dyn_module)
613 {
614     /*-----------------------------------------------------------------------*/
615     /* Spin through dynamic table loking for tags that have a value which is */
616     /* the virtual address of a section. After the sections are allocated,   */
617     /* we'll need to update these values with the new address of the section.*/
618     /*-----------------------------------------------------------------------*/
619     int i;
620     for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
621     {
622         switch (dyn_module->dyntab[i].d_tag)
623         {
624             /*---------------------------------------------------------------*/
625             /* Only tag values that are virtual addresses will be affected.  */
626             /*---------------------------------------------------------------*/
627             case DT_NEEDED:
628             case DT_PLTRELSZ:
629             case DT_HASH:
630             case DT_STRTAB:
631             case DT_SYMTAB:
632             case DT_RELA:
633             case DT_RELASZ:
634             case DT_RELAENT:
635             case DT_STRSZ:
636             case DT_SYMENT:
637             case DT_SONAME:
638             case DT_RPATH:
639             case DT_SYMBOLIC:
640             case DT_REL:
641             case DT_RELSZ:
642             case DT_RELENT:
643             case DT_PLTREL:
644             case DT_DEBUG:
645             case DT_TEXTREL:
646             case DT_BIND_NOW:
647             case DT_INIT_ARRAYSZ:
648             case DT_RUNPATH:
649             case DT_FLAGS:
650             case DT_PREINIT_ARRAYSZ:
651                continue;
652
653             /*---------------------------------------------------------------*/
654             /* NOTE!!!                                                       */
655             /* case DT_ENCODING:  -- tag type has same "id" as               */
656             /* DT_PREINIT_ARRAY                                              */
657             /*---------------------------------------------------------------*/
658
659             /*---------------------------------------------------------------*/
660             /* This is a generic dynamic tag whose value is a virtual address*/
661             /* of a section. It needs to be relocated to the section's actual*/
662             /* address in target memory.                                     */
663             /*---------------------------------------------------------------*/
664             case DT_PREINIT_ARRAY:
665             case DT_INIT:
666             case DT_INIT_ARRAY:
667                 if (!DLIMP_update_dyntag_section_address(dyn_module, i))
668                     return FALSE;
669
670                 continue;
671
672             /*---------------------------------------------------------------*/
673             /* Once we have resolved the actual address of termination       */
674             /* function sections, we need to copy their addresses over to    */
675             /* the loaded module object (dyn_module will be deleted before   */
676             /* we get to unloading the module).                              */
677             /*---------------------------------------------------------------*/
678             case DT_FINI_ARRAY:
679             case DT_FINI:
680                 if (!DLIMP_update_dyntag_section_address(dyn_module, i))
681                     return FALSE;
682
683                 if (dyn_module->dyntab[i].d_tag == DT_FINI)
684                     dyn_module->loaded_module->fini =
685                                              dyn_module->dyntab[i].d_un.d_ptr;
686                 else
687                     dyn_module->loaded_module->fini_array =
688                                              dyn_module->dyntab[i].d_un.d_ptr;
689
690                 continue;
691
692             case DT_FINI_ARRAYSZ:
693                 dyn_module->loaded_module->fini_arraysz =
694                                              dyn_module->dyntab[i].d_un.d_val;
695                 continue;
696
697             /*---------------------------------------------------------------*/
698             /* Is this a virtual address???                                  */
699             /*---------------------------------------------------------------*/
700             case DT_JMPREL: /* is this a virtual address??? */
701                 continue;
702
703             /*---------------------------------------------------------------*/
704             /* The remaining dynamic tag types should be target specific. If */
705             /* something generic slips through to here, then the handler for */
706             /* relocating target specific dynamic tags should fail.          */
707             /*---------------------------------------------------------------*/
708             default:
709                 if (!relocate_target_dynamic_tag_info(dyn_module, i))
710                     return FALSE;
711         }
712     }
713
714     /*-----------------------------------------------------------------------*/
715     /* We've gotten through all of the dynamic table without incident.       */
716     /* All dynamic tag values that were virtual section addresses should have*/
717     /* been updated with the final address of the section that they point to.*/
718     /*-----------------------------------------------------------------------*/
719     return TRUE;
720 }
721
722 /*****************************************************************************/
723 /* allocate_dynamic_segments_and relocate_symbols()                          */
724 /*                                                                           */
725 /*    Allocate target memory for each segment in this module, getting a      */
726 /*    host-accessible space to copy the content of each segment into.  Then  */
727 /*    update the symbol table and program header table to reflect the new    */
728 /*    target address for each segment.  Processing of the dynamic relocation */
729 /*    entries will wait until all dependent files have been loaded and       */
730 /*    allocated into target memory.                                          */
731 /*                                                                           */
732 /*---------------------------------------------------------------------------*/
733 /*                                                                           */
734 /* The relocation entries in the ELF file do not handle the necessary        */
735 /* adjustments to the memory addresses in the program header or symbol       */
736 /* tables.  These must be done manually.                                     */
737 /*                                                                           */
738 /* This is harder for us than for most dynamic loaders, because we have to   */
739 /* work in environments without virtual memory and thus where the offsets    */
740 /* between segments in memory may be different than they were in the file.   */
741 /* So, even though a dynamic loader usually only has to adjust all the       */
742 /* segments by a single fixed offset, we need to offset the symbols and      */
743 /* program header addresses segment by segment.  This job is done by the     */
744 /* function below.                                                           */
745 /*                                                                           */
746 /*****************************************************************************/
747 static BOOL allocate_dynamic_segments_and_relocate_symbols
748                                              (DLOAD_HANDLE handle,
749                                               LOADER_FILE_DESC *fd,
750                                               DLIMP_Dynamic_Module *dyn_module)
751 {
752     int i,j;
753     DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
754                              (dyn_module->loaded_module->loaded_segments.buf);
755     struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
756     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
757
758 #if LOADER_DEBUG || LOADER_PROFILE
759     if (debugging_on || profiling_on)
760     {
761         DLIF_trace("Dynamic executable found.\n"
762            "Starting allocate_dynamic_segments_and_relocate_symbols() ...\n");
763         if (profiling_on) profile_start_clock();
764     }
765 #endif
766
767     /*-----------------------------------------------------------------------*/
768     /* Spin through the list of loaded segments from the current module.     */
769     /*-----------------------------------------------------------------------*/
770     for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
771     {
772         /*-------------------------------------------------------------------*/
773         /* Allocate target memory for segment via client-provided target     */
774         /* memory API.                                                       */
775         /*-------------------------------------------------------------------*/
776         int32_t addr_offset;
777         struct DLOAD_MEMORY_REQUEST targ_req;
778         seg[i].obj_desc->target_page = 0;
779         targ_req.flags = 0;
780         if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
781         targ_req.align = 0x20;
782         seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
783         targ_req.flags |= DLOAD_SF_relocatable;
784
785         targ_req.fp = fd;
786         targ_req.segment = seg[i].obj_desc;
787         targ_req.offset = seg[i].phdr.p_offset;
788         targ_req.flip_endian = dyn_module->wrong_endian;
789
790 #if LOADER_DEBUG
791         if (debugging_on)
792             DLIF_trace("Segment %d flags 0x%x\n", i, targ_req.flags);
793 #endif
794         if (!DLIF_allocate(pHandle->client_handle, &targ_req))
795         {
796             DLIF_error(DLET_MEMORY, "DLIF allocation failure.\n");
797             return FALSE;
798         }
799
800         /*-------------------------------------------------------------------*/
801         /* Calculate the offset we need to adjust segment header and symbol  */
802         /* table addresses.                                                  */
803         /*-------------------------------------------------------------------*/
804         addr_offset = (int32_t)(seg[i].obj_desc->target_address) -
805                                                (int32_t)(seg[i].phdr.p_vaddr);
806
807 #if LOADER_DEBUG
808         if (debugging_on)
809         {
810             DLIF_trace("Segment %d (at 0x%x, 0x%x bytes) relocated to 0x%x\n",
811                        i,
812                        (int32_t)(seg[i].phdr.p_vaddr),
813                        (int32_t)(seg[i].phdr.p_memsz),
814                        (int32_t)(seg[i].obj_desc->target_address));
815             DLIF_trace( "Addr Offset is 0x%x\n", addr_offset);
816         }
817 #endif
818
819         /*-------------------------------------------------------------------*/
820         /* Update program entry point if needed.  Need to replace to deal    */
821         /* with full ELF initialization routine.                             */
822         /*-------------------------------------------------------------------*/
823         if (dyn_module->relocate_entry_point &&
824             fhdr->e_entry >= (Elf32_Addr)(seg[i].phdr.p_vaddr) &&
825             fhdr->e_entry < (Elf32_Addr)((uint8_t*)(seg[i].phdr.p_vaddr) +
826                                          (uint32_t)(seg[i].phdr.p_memsz)))
827         {
828 #if LOADER_DEBUG
829             if (debugging_on)
830             {
831                 DLIF_trace("Entry point 0x%x relocated to 0x%x\n",
832                            fhdr->e_entry, fhdr->e_entry + addr_offset);
833             }
834 #endif
835             fhdr->e_entry += addr_offset;
836
837             /*---------------------------------------------------------------*/
838             /* Mark the entry point as being relocated so we will not do it  */
839             /* again.                                                        */
840             /*---------------------------------------------------------------*/
841             dyn_module->relocate_entry_point = FALSE;
842         }
843
844         /*-------------------------------------------------------------------*/
845         /* Fix program header entries in segment and Elf32_Phdr structs.     */
846         /*-------------------------------------------------------------------*/
847         for (j = 0; j < fhdr->e_phnum; j++)
848             if (dyn_module->phdr[j].p_vaddr == (Elf32_Addr)seg[i].phdr.p_vaddr)
849             {
850                 dyn_module->phdr[j].p_vaddr += addr_offset;
851                 dyn_module->phdr[i].p_paddr += addr_offset;
852                 break;
853             }
854
855         seg[i].input_vaddr = (Elf32_Addr)(seg[i].phdr.p_vaddr);
856         seg[i].phdr.p_vaddr += addr_offset;
857
858         /*-------------------------------------------------------------------*/
859         /* Great, now the hard part: fix offsets in symbols.  It would be    */
860         /* nice if there were an easier way to deal with this.               */
861         /*-------------------------------------------------------------------*/
862         {
863             struct Elf32_Sym *gsymtab =
864                     ((struct Elf32_Sym*)(dyn_module->loaded_module->gsymtab));
865             Elf32_Addr segment_start = (Elf32_Addr)seg[i].phdr.p_vaddr;
866             Elf32_Addr segment_end   = (Elf32_Addr)seg[i].phdr.p_vaddr +
867                                        seg[i].phdr.p_memsz;
868             Elf32_Word global_index  = dyn_module->symnum -
869                                        dyn_module->loaded_module->gsymnum;
870
871             for (j = 0; j < dyn_module->symnum; j++)
872             {
873                 /*-----------------------------------------------------------*/
874                 /* Get the relocated symbol value.                           */
875                 /*-----------------------------------------------------------*/
876                 Elf32_Addr symval_adj = dyn_module->symtab[j].st_value +
877                                         addr_offset;
878
879                 /*-----------------------------------------------------------*/
880                 /* If the symbol is defined in this segment, update the      */
881                 /* symbol value and mark the symbol so that we don't         */
882                 /* relocate it again.                                        */
883                 /*-----------------------------------------------------------*/
884                 if (symval_adj >= segment_start && symval_adj <  segment_end &&
885                     dyn_module->symtab[j].st_shndx != INT16_MAX)
886                 {
887                     dyn_module->symtab[j].st_value = symval_adj;
888
889                     /*-------------------------------------------------------*/
890                     /* The module symbol table only has the global symbols.  */
891                     /*-------------------------------------------------------*/
892                     if (j >= global_index)
893                        gsymtab[j-global_index].st_value = symval_adj;
894
895                     /*-------------------------------------------------------*/
896                     /* Mark the symbol as relocated.                         */
897                     /*-------------------------------------------------------*/
898                     dyn_module->symtab[j].st_shndx = INT16_MAX;
899                 }
900             }
901         }
902     }
903
904     /*-----------------------------------------------------------------------*/
905     /* Update dynamic tag information. Some dynamic tags have values which   */
906     /* are virtual addresses of sections. These values need to be updated    */
907     /* once segment allocation is completed and the new segment addresses are*/
908     /* known.                                                                */
909     /*-----------------------------------------------------------------------*/
910     /* We should only traverse through the dynamic table once because we want*/
911     /* to avoid the possibility of updating the same tag multiple times (an  */
912     /* error, if it happens).                                                */
913     /*-----------------------------------------------------------------------*/
914     if (!relocate_dynamic_tag_info(fd, dyn_module))
915     {
916         DLIF_error(DLET_MISC, "Failed dynamic table update.\n");
917         return FALSE;
918     }
919
920 #if LOADER_DEBUG || LOADER_PROFILE
921     if (debugging_on || profiling_on)
922     {
923         DLIF_trace("allocate_dynamic_segments_and_relocate_symbols() Done\n");
924         if (profiling_on)
925         {
926             profile_stop_clock();
927             DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
928         }
929     }
930 #endif
931
932     return TRUE;
933 }
934
935 /*****************************************************************************/
936 /* delete_DLIMP_Loaded_Module()                                              */
937 /*                                                                           */
938 /*    Free host memory associated with a DLIMP_Loaded_Module data structure  */
939 /*    and all of the DLIMP_Loaded_Segment objects that are associated with   */
940 /*    it.                                                                    */
941 /*                                                                           */
942 /*****************************************************************************/
943 static void delete_DLIMP_Loaded_Module(DLOAD_HANDLE handle,
944                                        DLIMP_Loaded_Module **pplm)
945 {
946     DLIMP_Loaded_Module *loaded_module = *pplm;
947     DLIMP_Loaded_Segment *segments = (DLIMP_Loaded_Segment*)
948                                           (loaded_module->loaded_segments.buf);
949     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
950
951     /*-----------------------------------------------------------------------*/
952     /* Spin through the segments attached to this loaded module, freeing up  */
953     /* any target memory that was allocated by the client for the segment.   */
954     /*-----------------------------------------------------------------------*/
955     int i;
956     for (i = 0; i < loaded_module->loaded_segments.size; i++)
957     {
958         if (!DLIF_release(pHandle->client_handle, segments[i].obj_desc))
959             DLIF_error(DLET_MISC, "Failed call to DLIF_release!\n");;
960         DLIF_free(segments[i].obj_desc);
961     }
962
963     /*-----------------------------------------------------------------------*/
964     /* Hacky way of indicating that the base image is no longer available.   */
965     /* WHHHHAAAAAAATTT!?!?!?!?!?!                                            */
966     /*-----------------------------------------------------------------------*/
967     if (loaded_module->file_handle == DLIMP_application_handle)
968         DLIMP_application_handle = 0;
969
970     /*-----------------------------------------------------------------------*/
971     /* Free host heap memory that was allocated for the internal loaded      */
972     /* module data structure members.                                        */
973     /*-----------------------------------------------------------------------*/
974     if (loaded_module->name)    DLIF_free(loaded_module->name);
975     if (loaded_module->gsymtab) DLIF_free(loaded_module->gsymtab);
976     loaded_module->gsymnum = 0;
977     if (loaded_module->gstrtab) DLIF_free(loaded_module->gstrtab);
978     loaded_module->gstrsz = 0;
979     AL_destroy(&(loaded_module->loaded_segments));
980     AL_destroy(&(loaded_module->dependencies));
981
982     /*-----------------------------------------------------------------------*/
983     /* Finally, free the host memory for the loaded module object, then NULL */
984     /* the pointer that was passed in.                                       */
985     /*-----------------------------------------------------------------------*/
986     DLIF_free(loaded_module);
987     *pplm = NULL;
988 }
989
990 /*****************************************************************************/
991 /* new_DLIMP_Dynamic_Module()                                                */
992 /*                                                                           */
993 /*   Allocate a dynamic module data structure from host memory and           */
994 /*   initialize its members to their default values.                         */
995 /*                                                                           */
996 /*****************************************************************************/
997 static DLIMP_Dynamic_Module *new_DLIMP_Dynamic_Module(LOADER_FILE_DESC *fd)
998 {
999     /*-----------------------------------------------------------------------*/
1000     /* Allocate space for dynamic module data structure from host memory.    */
1001     /*-----------------------------------------------------------------------*/
1002     DLIMP_Dynamic_Module *dyn_module =
1003              (DLIMP_Dynamic_Module *)DLIF_malloc(sizeof(DLIMP_Dynamic_Module));
1004
1005     if (!dyn_module)
1006         return NULL;
1007
1008     /*-----------------------------------------------------------------------*/
1009     /* Initialize data members of the new dynamic module data structure.     */
1010     /*-----------------------------------------------------------------------*/
1011     dyn_module->name = NULL;
1012     dyn_module->fd = fd;
1013     dyn_module->phdr = NULL;
1014     dyn_module->phnum = 0;
1015     dyn_module->strtab = NULL;
1016     dyn_module->strsz = 0;
1017     dyn_module->dyntab = NULL;
1018     dyn_module->symtab = NULL;
1019     dyn_module->symnum = 0;
1020     dyn_module->gsymtab_offset = 0;
1021     dyn_module->gstrtab_offset = 0;
1022     dyn_module->c_args = NULL;
1023     dyn_module->argc = 0;
1024     dyn_module->argv = NULL;
1025     dyn_module->loaded_module = NULL;
1026     dyn_module->wrong_endian = 0;
1027     dyn_module->direct_dependent_only = TRUE;
1028     dyn_module->relocatable = FALSE;
1029     dyn_module->relocate_entry_point = TRUE;
1030
1031     dyn_module->dsbt_size = 0;
1032     dyn_module->dsbt_index = DSBT_INDEX_INVALID;
1033     dyn_module->dsbt_base_tagidx = -1;
1034
1035     dyn_module->preinit_array_idx = -1;
1036     dyn_module->preinit_arraysz = 0;
1037     dyn_module->init_idx = -1;
1038     dyn_module->init_array_idx = -1;
1039     dyn_module->init_arraysz = 0;
1040
1041     return dyn_module;
1042 }
1043
1044 /*****************************************************************************/
1045 /* detach_loaded_module()                                                    */
1046 /*                                                                           */
1047 /*    Detach loaded module data structure from given dynamic module.  When   */
1048 /*    an object file has been successfully loaded, the loader core will      */
1049 /*    detach the loaded module data structure from the dynamic module data   */
1050 /*    structure because the loaded module must continue to persist until is  */
1051 /*    is actually unloaded from target memory.  If there is a problem with   */
1052 /*    the load, then the host memory associated with the loaded module will  */
1053 /*    be released as part of the destruction of the dynamic module.          */
1054 /*                                                                           */
1055 /*****************************************************************************/
1056 static DLIMP_Loaded_Module *detach_loaded_module(DLIMP_Dynamic_Module *dyn_module)
1057 {
1058     if (dyn_module && dyn_module->loaded_module)
1059     {
1060         DLIMP_Loaded_Module *loaded_module = dyn_module->loaded_module;
1061         dyn_module->loaded_module = NULL;
1062         return loaded_module;
1063     }
1064
1065     return NULL;
1066 }
1067 /*****************************************************************************/
1068 /* delete_DLIMP_Dynamic_Module()                                             */
1069 /*                                                                           */
1070 /*    Remove local copies of the string table, symbol table, program header  */
1071 /*    table, and dynamic table.                                              */
1072 /*                                                                           */
1073 /*****************************************************************************/
1074 static void delete_DLIMP_Dynamic_Module(DLOAD_HANDLE handle,
1075                                         DLIMP_Dynamic_Module **ppdm)
1076 {
1077     DLIMP_Dynamic_Module *dyn_module = NULL;
1078
1079     if (!ppdm || (*ppdm == NULL))
1080     {
1081         DLIF_error(DLET_MISC,
1082                    "Internal Error: invalid argument to dynamic module "
1083                    "destructor function; aborting loader\n");
1084         exit(1);
1085     }
1086
1087     dyn_module = *ppdm;
1088     if (dyn_module->name)     DLIF_free(dyn_module->name);
1089     if (dyn_module->strtab)   DLIF_free(dyn_module->strtab);
1090     if (dyn_module->symtab)   DLIF_free(dyn_module->symtab);
1091     if (dyn_module->phdr)     DLIF_free(dyn_module->phdr);
1092     if (dyn_module->dyntab)   DLIF_free(dyn_module->dyntab);
1093
1094     /*-----------------------------------------------------------------------*/
1095     /* If we left the loaded module attached to the dynamic module, then     */
1096     /* something must have gone wrong with the load.  Remove the loaded      */
1097     /* module from the queue of loaded modules, if it is there.  Then free   */
1098     /* the host memory allocated to the loaded module and its segments.      */
1099     /*-----------------------------------------------------------------------*/
1100     if (dyn_module->loaded_module != NULL)
1101         delete_DLIMP_Loaded_Module(handle, &(dyn_module->loaded_module));
1102
1103     /*-----------------------------------------------------------------------*/
1104     /* Finally, free the host memory for this dynamic module object and NULL */
1105     /* the pointer to the object.                                            */
1106     /*-----------------------------------------------------------------------*/
1107     DLIF_free(dyn_module);
1108     *ppdm = NULL;
1109 }
1110
1111 /*****************************************************************************/
1112 /* file_header_magic_number_is_valid()                                       */
1113 /*                                                                           */
1114 /*    Given an object file header, check the magic number to ensure that it  */
1115 /*    is an object file format that we recognize.  This implementation of    */
1116 /*    the dynamic loader core will handle ELF object file format.            */
1117 /*                                                                           */
1118 /*****************************************************************************/
1119 static BOOL file_header_magic_number_is_valid(struct Elf32_Ehdr* header)
1120 {
1121     /*-----------------------------------------------------------------------*/
1122     /* Check for correct ELF magic numbers in file header.                   */
1123     /*-----------------------------------------------------------------------*/
1124     if (!header->e_ident[EI_MAG0] == ELFMAG0 ||
1125         !header->e_ident[EI_MAG1] == ELFMAG1 ||
1126         !header->e_ident[EI_MAG2] == ELFMAG2 ||
1127         !header->e_ident[EI_MAG3] == ELFMAG3)
1128     {
1129         DLIF_error(DLET_FILE, "Invalid ELF magic number.\n");
1130         return FALSE;
1131     }
1132
1133     return TRUE;
1134 }
1135
1136 /*****************************************************************************/
1137 /* file_header_machine_is_valid()                                            */
1138 /*                                                                           */
1139 /*    Check if the machine specified in the file header is supported by the  */
1140 /*    loader.  If the loader was compiled with support for all targets,      */
1141 /*    the machine will be initially set to EM_NONE.  Once a module has been  */
1142 /*    loaded, all remaining modules must have the same machine value.        */
1143 /*****************************************************************************/
1144 static BOOL file_header_machine_is_valid(DLOAD_HANDLE handle, Elf32_Half e_machine)
1145 {
1146     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
1147
1148     if (pHandle->DLOAD_TARGET_MACHINE == EM_NONE)
1149         pHandle->DLOAD_TARGET_MACHINE = e_machine;
1150
1151     if (e_machine != pHandle->DLOAD_TARGET_MACHINE)
1152         return FALSE;
1153
1154     return TRUE;
1155 }
1156
1157 /*****************************************************************************/
1158 /* is_valid_elf_object_file()                                                */
1159 /*                                                                           */
1160 /*    Check file size against anticipated end location of string table,      */
1161 /*    symbol table, program header tables, etc.  If we anything untoward,    */
1162 /*    then we declare that the ELF file is corrupt and the load is aborted.  */
1163 /*                                                                           */
1164 /*****************************************************************************/
1165 static BOOL is_valid_elf_object_file(LOADER_FILE_DESC *fd,
1166                                      DLIMP_Dynamic_Module *dyn_module)
1167 {
1168     uint32_t fsz;
1169     int i;
1170
1171     /*-----------------------------------------------------------------------*/
1172     /* Get file size.                                                        */
1173     /*-----------------------------------------------------------------------*/
1174     DLIF_fseek(fd, 0, LOADER_SEEK_END);
1175     fsz = DLIF_ftell(fd);
1176
1177     /*-----------------------------------------------------------------------*/
1178     /* Check for invalid table sizes (string table, symbol table, and        */
1179     /* program header tables).                                               */
1180     /*-----------------------------------------------------------------------*/
1181     if (!((dyn_module->strsz < fsz) &&
1182           (dyn_module->symnum < fsz) &&
1183           (dyn_module->phnum * sizeof(struct Elf32_Phdr)) < fsz))
1184     {
1185         DLIF_error(DLET_FILE, "Invalid ELF table bounds.\n");
1186         return FALSE;
1187     }
1188
1189     /*-----------------------------------------------------------------------*/
1190     /* Check for null so_name string in file with dynamic information.       */
1191     /*-----------------------------------------------------------------------*/
1192     if (dyn_module->dyntab && !strcmp(dyn_module->name, ""))
1193     {
1194         DLIF_error(DLET_MISC, "Dynamic file lacks SO_NAME identifier.\n");
1195         return FALSE;
1196     }
1197
1198     /*-----------------------------------------------------------------------*/
1199     /* Check for invalid program header information.                         */
1200     /*-----------------------------------------------------------------------*/
1201     for (i = 0; i < dyn_module->phnum; i++)
1202     {
1203         struct Elf32_Phdr* phdr = dyn_module->phdr + i;
1204
1205         /*-------------------------------------------------------------------*/
1206         /* Sanity check for relative sizes of filesz and memsz.              */
1207         /*-------------------------------------------------------------------*/
1208         if (!(phdr->p_type != PT_LOAD || phdr->p_filesz <= phdr->p_memsz))
1209         {
1210              DLIF_error(DLET_MISC,
1211                         "Invalid file or memory size for segment %d.\n", i);
1212              return FALSE;
1213         }
1214
1215         /*-------------------------------------------------------------------*/
1216         /* Check that segment file offset doesn't go off the end of the file.*/
1217         /*-------------------------------------------------------------------*/
1218         if (!(phdr->p_offset + phdr->p_filesz < fsz))
1219         {
1220              DLIF_error(DLET_FILE,
1221                  "File location of segment %d is past the end of file.\n", i);
1222              return FALSE;
1223         }
1224     }
1225
1226     /*-----------------------------------------------------------------------*/
1227     /* Check that a ET_DYN-type file is relocatable.                         */
1228     /*-----------------------------------------------------------------------*/
1229     if (dyn_module->fhdr.e_type == ET_DYN && !dyn_module->symtab) return FALSE;
1230
1231     /*-----------------------------------------------------------------------*/
1232     /* All checks passed.                                                    */
1233     /*-----------------------------------------------------------------------*/
1234     return TRUE;
1235 }
1236
1237 /*****************************************************************************/
1238 /* process_eiosabi()                                                         */
1239 /*                                                                           */
1240 /*   Check the EI_OSABI field to validate it and set any parameters based on */
1241 /*   it.                                                                     */
1242 /*****************************************************************************/
1243 static BOOL process_eiosabi(DLIMP_Dynamic_Module* dyn_module)
1244 {
1245 #if ARM_TARGET
1246     if (is_arm_module(&dyn_module->fhdr))
1247         return DLDYN_arm_process_eiosabi(dyn_module);
1248 #endif
1249
1250 #if C60_TARGET
1251     if (is_c60_module(&dyn_module->fhdr))
1252         return DLDYN_c60_process_eiosabi(dyn_module);
1253 #endif
1254
1255    return FALSE;
1256 }
1257 /*****************************************************************************/
1258 /* dload_file_header()                                                       */
1259 /*                                                                           */
1260 /*    Read ELF file header.  Store critical information in the provided      */
1261 /*    DLIMP_Dynamic_Module record.  Check file header for validity.          */
1262 /*                                                                           */
1263 /*****************************************************************************/
1264 static BOOL dload_file_header(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd,
1265                               DLIMP_Dynamic_Module *dyn_module)
1266 {
1267     /*-----------------------------------------------------------------------*/
1268     /* Read ELF file header from given input file.                           */
1269     /*-----------------------------------------------------------------------*/
1270     DLIF_fread(&(dyn_module->fhdr), sizeof(struct Elf32_Ehdr), 1, fd);
1271
1272     /*-----------------------------------------------------------------------*/
1273     /* Determine target vs. host endian-ness.  Does header data need to be   */
1274     /* byte swapped?                                                         */
1275     /*-----------------------------------------------------------------------*/
1276     dyn_module->wrong_endian =
1277                      (dyn_module->fhdr.e_ident[EI_DATA] != DLIMP_get_endian());
1278
1279     /*-----------------------------------------------------------------------*/
1280     /* Swap file header structures, if needed.                               */
1281     /*-----------------------------------------------------------------------*/
1282     if (dyn_module->wrong_endian)
1283         DLIMP_change_ehdr_endian(&(dyn_module->fhdr));
1284
1285 #if LOADER_DEBUG
1286     if (debugging_on) {
1287         /*-------------------------------------------------------------------*/
1288         /* Write out magic ELF information for debug purposes.               */
1289         /*-------------------------------------------------------------------*/
1290         DLIF_trace("ELF: %c%c%c\n", dyn_module->fhdr.e_ident[1],
1291                                 dyn_module->fhdr.e_ident[2],
1292                                 dyn_module->fhdr.e_ident[3]);
1293         DLIF_trace("ELF file header entry point: %x\n",
1294                    dyn_module->fhdr.e_entry);
1295     }
1296 #endif
1297
1298     /*-----------------------------------------------------------------------*/
1299     /* Verify magic numbers in ELF file header.                              */
1300     /*-----------------------------------------------------------------------*/
1301     if (!file_header_magic_number_is_valid(&(dyn_module->fhdr)))
1302     {
1303         DLIF_error(DLET_FILE, "Invalid ELF file header magic number.\n");
1304         return FALSE;
1305     }
1306
1307     if (!file_header_machine_is_valid(handle, dyn_module->fhdr.e_machine))
1308     {
1309         DLIF_error(DLET_FILE, "Invalid ELF file target machine.\n");
1310         DLIF_trace("dyn_module->fhdr.e_machine = 0x%x\n",
1311                    dyn_module->fhdr.e_machine);
1312         return FALSE;
1313     }
1314
1315     /*-----------------------------------------------------------------------*/
1316     /* Verify file is an executable or dynamic shared object or library.     */
1317     /*-----------------------------------------------------------------------*/
1318     if ((dyn_module->fhdr.e_type != ET_EXEC) &&
1319         (dyn_module->fhdr.e_type != ET_DYN))
1320     {
1321         DLIF_error(DLET_FILE, "Invalid ELF file type.\n");
1322         return FALSE;
1323     }
1324
1325 #if LOADER_DEBUG || LOADER_PROFILE
1326     /*-----------------------------------------------------------------------*/
1327     /* Stop profiling clock when file header information has finished        */
1328     /* loading.  Re-start clock on initialization of symbol table, and       */
1329     /* dynamic table pointers.                                               */
1330     /*-----------------------------------------------------------------------*/
1331     if (debugging_on || profiling_on)
1332     {
1333         DLIF_trace("done.\n");
1334         if (profiling_on)
1335         {
1336             profile_stop_clock();
1337             DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
1338             profile_start_clock();
1339         }
1340     }
1341 #endif
1342
1343     return TRUE;
1344 }
1345
1346 /*****************************************************************************/
1347 /* dload_program_header_table()                                              */
1348 /*                                                                           */
1349 /*    Make a local copy of the ELF object file's program header table in the */
1350 /*    dynamic module data structure.                                         */
1351 /*                                                                           */
1352 /*****************************************************************************/
1353 static void dload_program_header_table(LOADER_FILE_DESC *fd,
1354                                        DLIMP_Dynamic_Module *dyn_module)
1355 {
1356     /*-----------------------------------------------------------------------*/
1357     /* Read the program header tables from the object file.                  */
1358     /*-----------------------------------------------------------------------*/
1359     struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
1360     dyn_module->phdr = (struct Elf32_Phdr*)
1361                               (DLIF_malloc(fhdr->e_phnum * fhdr->e_phentsize));
1362     DLIF_fseek(fd, fhdr->e_phoff, LOADER_SEEK_SET);
1363     if(dyn_module->phdr) {
1364         DLIF_fread(dyn_module->phdr, fhdr->e_phentsize, fhdr->e_phnum,fd);
1365         dyn_module->phnum = fhdr->e_phnum;
1366
1367         /*-------------------------------------------------------------------*/
1368         /* Byte swap the program header tables if the target endian-ness is  */
1369         /* not the same as the host endian-ness.                             */
1370         /*-------------------------------------------------------------------*/
1371         if (dyn_module->wrong_endian)
1372         {
1373             int i;
1374             for (i = 0; i < dyn_module->phnum; i++)
1375                 DLIMP_change_phdr_endian(dyn_module->phdr + i);
1376         }
1377     }
1378 }
1379
1380 /*****************************************************************************/
1381 /* dload_headers()                                                           */
1382 /*                                                                           */
1383 /*    Read ELF object file header and program header table information into  */
1384 /*    the given dynamic module data structure.  If the object file contains  */
1385 /*    dynamic information, read in the dynamic tags, dynamic symbol table,   */
1386 /*    and global string table.  Check to make sure that we are not already   */
1387 /*    in the process of loading the module (circular dependencies), then     */
1388 /*    perform some level of sanity checking on the content of the file to    */
1389 /*    provide some assurance that the file is not corrupted.                 */
1390 /*                                                                           */
1391 /*****************************************************************************/
1392 static BOOL dload_headers(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd,
1393                           DLIMP_Dynamic_Module *dyn_module)
1394 {
1395 #if LOADER_DEBUG || LOADER_PROFILE
1396     /*-----------------------------------------------------------------------*/
1397     /* More progress information.  Start timing if profiling is enabled.     */
1398     /*-----------------------------------------------------------------------*/
1399     if (debugging_on || profiling_on)
1400     {
1401         DLIF_trace("\nReading file headers ...\n");
1402         if (profiling_on) profile_start_clock();
1403     }
1404 #endif
1405
1406     /*-----------------------------------------------------------------------*/
1407     /* Read file header information and check vs. expected ELF object file   */
1408     /* header content.                                                       */
1409     /*-----------------------------------------------------------------------*/
1410     if (!dload_file_header(handle, fd, dyn_module))
1411         return FALSE;
1412
1413     /*-----------------------------------------------------------------------*/
1414     /* Read program header table information into the dynamic module object. */
1415     /*-----------------------------------------------------------------------*/
1416     dload_program_header_table(fd, dyn_module);
1417
1418     return TRUE;
1419 }
1420
1421 /*****************************************************************************/
1422 /* find_dynamic_segment()                                                    */
1423 /*                                                                           */
1424 /*    Find the dynamic segment in the given ELF object file, if there is     */
1425 /*    one.  If the segment is found, then the segment ID output parameter    */
1426 /*    is set to the index of the dynamic segment in the program header       */
1427 /*    table.  If the dynamic segment is not found, the dynamic module's      */
1428 /*    relocatable flag is set to FALSE, and return FALSE.                    */
1429 /*                                                                           */
1430 /*****************************************************************************/
1431 static BOOL find_dynamic_segment(DLIMP_Dynamic_Module *dyn_module,
1432                                  Elf32_Word *dyn_seg_idx)
1433 {
1434     int i;
1435
1436     /*-----------------------------------------------------------------------*/
1437     /* We should have a valid dynamic module pointer and somewhere to put the*/
1438     /* dynamic segment id, if we find one.  If either of these are missing,  */
1439     /* we should get an internal error and abort the loader.                 */
1440     /*-----------------------------------------------------------------------*/
1441     if ((dyn_module == NULL) || (dyn_seg_idx == NULL))
1442     {
1443         DLIF_error(DLET_MISC, "Internal error: find_dynamic_segment() needs "
1444                               "non-NULL arguments.\n");
1445         exit(1);
1446     }
1447
1448     /*-----------------------------------------------------------------------*/
1449     /* Spin through segment program headers to find the dynamic segment.     */
1450     /*-----------------------------------------------------------------------*/
1451     dyn_module->relocatable = TRUE;
1452     for (i = 0; i < dyn_module->phnum; i++)
1453         if (dyn_module->phdr[i].p_type == PT_DYNAMIC)
1454             { *dyn_seg_idx = i; return TRUE; }
1455
1456     /*-----------------------------------------------------------------------*/
1457     /* No dynamic segment found, mark the object module as not relocatable   */
1458     /* and warn the user.                                                    */
1459     /*-----------------------------------------------------------------------*/
1460     dyn_module->relocatable = FALSE;
1461 #if LOADER_DEBUG
1462     DLIF_warning(DLWT_MISC, "'%s' does not have a dynamic segment; assuming "
1463                             "that it is a static executable and it cannot "
1464                             "be relocated.\n", dyn_module->name);
1465 #endif
1466     return FALSE;
1467 }
1468
1469 /*****************************************************************************/
1470 /* copy_dynamic_table()                                                      */
1471 /*                                                                           */
1472 /*    Make a local copy of the dynamic table read from the dynamic segment   */
1473 /*    in the ELF object file.                                                */
1474 /*                                                                           */
1475 /*****************************************************************************/
1476 static void copy_dynamic_table(LOADER_FILE_DESC *fd,
1477                                DLIMP_Dynamic_Module *dyn_module,
1478                                Elf32_Word dyn_seg_idx)
1479 {
1480     /*-----------------------------------------------------------------------*/
1481     /* Allocate space for the dynamic table from host memory and read its    */
1482     /* content from the ELF object file.                                     */
1483     /*-----------------------------------------------------------------------*/
1484     Elf32_Word num_elem;
1485     dyn_module->dyntab = DLIF_malloc(dyn_module->phdr[dyn_seg_idx].p_filesz);
1486     num_elem =
1487         dyn_module->phdr[dyn_seg_idx].p_filesz / sizeof(struct Elf32_Dyn);
1488     DLIF_fseek(fd, dyn_module->phdr[dyn_seg_idx].p_offset, LOADER_SEEK_SET);
1489     if(dyn_module->dyntab) {
1490         DLIF_fread(dyn_module->dyntab, sizeof(struct Elf32_Dyn), num_elem, fd);
1491
1492         /*-------------------------------------------------------------------*/
1493         /* If necessary, byte swap each entry in the dynamic table.          */
1494         /*-------------------------------------------------------------------*/
1495         if (dyn_module->wrong_endian)
1496         {
1497             int i;
1498             for (i = 0; i < num_elem; i++)
1499                 DLIMP_change_dynent_endian(&dyn_module->dyntab[i]);
1500         }
1501     }
1502 }
1503
1504 /*****************************************************************************/
1505 /* process_target_dynamic_tag()                                              */
1506 /*                                                                           */
1507 /* Process a target specific dynamic tag entry.  Returns TRUE if the tag     */
1508 /* was handled and FALSE if it was not recognized.                           */
1509 /*****************************************************************************/
1510 static BOOL process_target_dynamic_tag(DLIMP_Dynamic_Module* dyn_module, int i)
1511 {
1512 #ifdef ARM_TARGET
1513     if (is_arm_module(&dyn_module->fhdr))
1514         return DLDYN_arm_process_dynamic_tag(dyn_module, i);
1515 #endif
1516
1517 #ifdef C60_TARGET
1518     if (is_c60_module(&dyn_module->fhdr))
1519         return DLDYN_c60_process_dynamic_tag(dyn_module, i);
1520 #endif
1521
1522     return FALSE;
1523 }
1524
1525 /*****************************************************************************/
1526 /* process_dynamic_table()                                                   */
1527 /*                                                                           */
1528 /*    Process dynamic tag entries from the dynamic table.  At the conclusion */
1529 /*    of this function, we should have made a copy of the global symbols     */
1530 /*    and the global symbol names.                                           */
1531 /*                                                                           */
1532 /*****************************************************************************/
1533 static BOOL process_dynamic_table(LOADER_FILE_DESC *fd,
1534                                   DLIMP_Dynamic_Module *dyn_module)
1535 {
1536     int        i;
1537     BOOL       soname_found  = FALSE;
1538     Elf32_Addr soname_offset = 0;
1539     Elf32_Addr strtab_offset = 0;
1540     Elf32_Addr hash_offset   = 0;
1541     Elf32_Addr symtab_offset = 0;
1542
1543     /*-----------------------------------------------------------------------*/
1544     /* Iterate over the dynamic table in order to process dynamic tags.      */
1545     /* See ELF TIS Specification for details on the meaning of each dynamic  */
1546     /* tag.  The C6000 ELF ABI Specification provides more details about the */
1547     /* TI specific C6000 ELF ABI tags.                                       */
1548     /*-----------------------------------------------------------------------*/
1549     for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
1550     {
1551         switch(dyn_module->dyntab[i].d_tag)
1552         {
1553             /*---------------------------------------------------------------*/
1554             /* DT_SONAME: Contains name of dynamic object, used for          */
1555             /*            dependency comparisons.  Its value is an offset    */
1556             /*            from the start of the string table.  We need to    */
1557             /*            copy the string at this offset into dmodule->name. */
1558             /*------------------------------------------------------------- -*/
1559             case DT_SONAME:
1560 #if LOADER_DEBUG
1561                 if (debugging_on) DLIF_trace("Found SO_NAME.\n");
1562 #endif
1563                 /*-----------------------------------------------------------*/
1564                 /* We store the offset of the so_name in the dynamic string  */
1565                 /* table so that it doesn't matter which dynamic tag we see  */
1566                 /* first (DT_SONAME actually is generated before DT_STRTAB). */
1567                 /*-----------------------------------------------------------*/
1568                 soname_found = TRUE;
1569                 soname_offset = dyn_module->dyntab[i].d_un.d_ptr;
1570                 break;
1571
1572             /*---------------------------------------------------------------*/
1573             /* DT_STRSZ: Contains the size of the string table.              */
1574             /*---------------------------------------------------------------*/
1575             case DT_STRSZ:
1576                 dyn_module->strsz = dyn_module->dyntab[i].d_un.d_val;
1577
1578 #if LOADER_DEBUG
1579                 if (debugging_on)
1580                     DLIF_trace("Found string table Size: 0x%x\n",
1581                                dyn_module->strsz);
1582 #endif
1583                 break;
1584
1585             /*---------------------------------------------------------------*/
1586             /* DT_STRTAB: Contains the file offset of the string table.  The */
1587             /*            tag directly after this is guaranteed to be        */
1588             /*            DT_STRSZ, containing the string table size.  We    */
1589             /*            need to allocate memory for the string table and   */
1590             /*            copy it from the file.                             */
1591             /*---------------------------------------------------------------*/
1592             case DT_STRTAB:
1593                 strtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1594 #if LOADER_DEBUG
1595                 if (debugging_on)
1596                     DLIF_trace("Found string table: 0x%x\n", strtab_offset);
1597 #endif
1598                 break;
1599
1600             /*---------------------------------------------------------------*/
1601             /* DT_HASH: Contains the file offset of the symbol hash table.   */
1602             /*---------------------------------------------------------------*/
1603             case DT_HASH:
1604                 hash_offset = dyn_module->dyntab[i].d_un.d_ptr;
1605 #if LOADER_DEBUG
1606                 if (debugging_on)
1607                     DLIF_trace("Found symbol hash table: 0x%x\n", hash_offset);
1608 #endif
1609                 break;
1610
1611             /*---------------------------------------------------------------*/
1612             /* DT_SYMTAB: Contains the file offset of the symbol table.      */
1613             /*---------------------------------------------------------------*/
1614             case DT_SYMTAB:
1615                 symtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1616 #if LOADER_DEBUG
1617                 if (debugging_on)
1618                     DLIF_trace("Found symbol table: 0x%x\n", symtab_offset);
1619 #endif
1620                 break;
1621
1622             /*---------------------------------------------------------------*/
1623             /* DSO Initialization / Termination Model Dynamic Tags           */
1624             /*---------------------------------------------------------------*/
1625             /* For initialization tags, we store indices and array sizes in  */
1626             /* the dyn_module. Termination works a little different, the     */
1627             /* indices into the local copy of the dynamic table are stored   */
1628             /* in dyn_module, but the DT_FINI_ARRAYSZ value is recorded with */
1629             /* the loaded module.                                            */
1630             /*---------------------------------------------------------------*/
1631             /* After placement is done, the DT_FINI and DT_FINI_ARRAY values */
1632             /* need to be copied from the local dynamic table into the       */
1633             /* loaded module object.                                         */
1634             /*---------------------------------------------------------------*/
1635             case DT_PREINIT_ARRAY:
1636                 dyn_module->preinit_array_idx = i;
1637                 break;
1638
1639             case DT_PREINIT_ARRAYSZ:
1640                 dyn_module->preinit_arraysz = dyn_module->dyntab[i].d_un.d_val;
1641                 break;
1642
1643             case DT_INIT:
1644                 dyn_module->init_idx = i;
1645                 break;
1646
1647             case DT_INIT_ARRAY:
1648                 dyn_module->init_array_idx = i;
1649                 break;
1650
1651             case DT_INIT_ARRAYSZ:
1652                 dyn_module->init_arraysz = dyn_module->dyntab[i].d_un.d_val;
1653                 break;
1654
1655             /*---------------------------------------------------------------*/
1656             /* This information will be copied over to the loaded module     */
1657             /* object after placement has been completed and the information */
1658             /* in the dynamic table has been relocated.                      */
1659             /*---------------------------------------------------------------*/
1660             case DT_FINI_ARRAY:
1661             case DT_FINI_ARRAYSZ:
1662             case DT_FINI:
1663                 break;
1664
1665             /*---------------------------------------------------------------*/
1666             /* Unrecognized tag, may not be illegal, but is not explicitly   */
1667             /* handled by this function.  Should it be?                      */
1668             /*---------------------------------------------------------------*/
1669             default:
1670             {
1671                 if (!process_target_dynamic_tag(dyn_module, i))
1672                 {
1673 #if LOADER_DEBUG
1674                     if (debugging_on)
1675                         DLIF_trace("Unrecognized dynamic tag: 0x%X\n",
1676                                    dyn_module->dyntab[i].d_tag);
1677 #endif
1678                 }
1679
1680                 break;
1681             }
1682
1683         }
1684     }
1685
1686     /*-----------------------------------------------------------------------*/
1687     /* If string table offset and size were found, read string table in from */
1688     /* the ELF object file.                                                  */
1689     /*-----------------------------------------------------------------------*/
1690     if (strtab_offset && dyn_module->strsz)
1691     {
1692         DLIF_fseek(fd, strtab_offset, LOADER_SEEK_SET);
1693         dyn_module->strtab = DLIF_malloc(dyn_module->strsz);
1694         if(dyn_module->strtab)
1695             DLIF_fread(dyn_module->strtab, sizeof(uint8_t), dyn_module->strsz,
1696                         fd);
1697         else
1698             return FALSE;
1699     }
1700     else
1701     {
1702         DLIF_warning(DLWT_MISC,
1703                      "Mandatory dynamic tag DT_STRTAB/DT_STRSZ not found!\n");
1704         return FALSE;
1705     }
1706
1707
1708     /*-----------------------------------------------------------------------*/
1709     /* If symbol hash table is found read-in the hash table.                 */
1710     /*-----------------------------------------------------------------------*/
1711     if (hash_offset)
1712     {
1713         /*-------------------------------------------------------------------*/
1714         /* Hash table has the following format. nchain equals the number of  */
1715         /* entries in the symbol table (symnum)                              */
1716         /*                                                                   */
1717         /*             +----------------------------+                        */
1718         /*             |          nbucket           |                        */
1719         /*             +----------------------------+                        */
1720         /*             |          nchain            |                        */
1721         /*             +----------------------------+                        */
1722         /*             |         bucket[0]          |                        */
1723         /*             |            ...             |                        */
1724         /*             |     bucket[nbucket-1]      |                        */
1725         /*             +----------------------------+                        */
1726         /*             |          chain[0]          |                        */
1727         /*             |            ...             |                        */
1728         /*             |       chain[nchain-1]      |                        */
1729         /*             +----------------------------+                        */
1730         /*-------------------------------------------------------------------*/
1731         Elf32_Word hash_nbucket;
1732         Elf32_Word hash_nchain;
1733
1734         /*-------------------------------------------------------------------*/
1735         /* Seek to the hash offset and read first two words into nbucket and */
1736         /* symnum.                                                           */
1737         /*-------------------------------------------------------------------*/
1738         DLIF_fseek(fd, hash_offset, LOADER_SEEK_SET);
1739         DLIF_fread(&(hash_nbucket), sizeof(Elf32_Word), 1, fd);
1740         DLIF_fread(&(hash_nchain), sizeof(Elf32_Word), 1, fd);
1741         if (dyn_module->wrong_endian)
1742         {
1743          DLIMP_change_endian32((int32_t*)(&(hash_nbucket)));
1744          DLIMP_change_endian32((int32_t*)(&(hash_nchain)));
1745         }
1746
1747         /*-------------------------------------------------------------------*/
1748         /* The number of entires in the dynamic symbol table is not encoded  */
1749         /* anywhere in the elf file. However, the nchain is guaranteed to be */
1750         /* the same as the number of symbols. Use nchain to set the symnum.  */
1751         /*-------------------------------------------------------------------*/
1752         dyn_module->symnum = hash_nchain;
1753 #if LOADER_DEBUG
1754         if (debugging_on) DLIF_trace("symnum=%d\n", hash_nchain);
1755 #endif
1756     }
1757     else
1758     {
1759         DLIF_warning(DLWT_MISC,
1760                      "Mandatory dynamic tag DT_HASH is not found!\n");
1761         return FALSE;
1762     }
1763
1764     /*-----------------------------------------------------------------------*/
1765     /* Read dynamic symbol table.                                            */
1766     /*-----------------------------------------------------------------------*/
1767     if (symtab_offset)
1768     {
1769         int j = 0;
1770         DLIF_fseek(fd, symtab_offset, LOADER_SEEK_SET);
1771         dyn_module->symtab =
1772                    DLIF_malloc(dyn_module->symnum * sizeof(struct Elf32_Sym));
1773         if(dyn_module->symtab == NULL)
1774             return FALSE;
1775         DLIF_fread(dyn_module->symtab, sizeof(struct Elf32_Sym),
1776                    dyn_module->symnum, fd);
1777         if (dyn_module->wrong_endian)
1778         {
1779             for (j = 0; j < dyn_module->symnum; j++)
1780                 DLIMP_change_sym_endian(dyn_module->symtab + j);
1781         }
1782
1783         /*-------------------------------------------------------------------*/
1784         /* The st_name field of an Elf32_Sym entity is an offset into the    */
1785         /* string table. Convert it into a pointer to the string.            */
1786         /*-------------------------------------------------------------------*/
1787         if (strtab_offset)
1788             for (j = 0; j < dyn_module->symnum; j++) {
1789                 dyn_module->symtab[j].st_name +=
1790                         (Elf32_Word) dyn_module->strtab;
1791 #if LOADER_DEBUG
1792             if (debugging_on)
1793                 DLIF_trace("Name of dynamic entry: %s\n",
1794                            dyn_module->symtab[j].st_name);
1795 #endif
1796             }
1797     }
1798     else
1799     {
1800         DLIF_warning(DLWT_MISC,
1801                      "Mandatory dynamic tag DT_SYMTAB is not found!\n");
1802         return FALSE;
1803     }
1804
1805     /*-----------------------------------------------------------------------*/
1806     /* Read the SONAME.                                                      */
1807     /*-----------------------------------------------------------------------*/
1808     if (!soname_found)
1809     {
1810         DLIF_warning(DLWT_MISC, "Dynamic tag DT_SONAME is not found!\n");
1811         dyn_module->name = DLIF_malloc(sizeof(char));
1812         if(dyn_module->name)
1813             *dyn_module->name = '\0';
1814         else
1815             return FALSE;
1816     }
1817     else
1818     {
1819         dyn_module->name =
1820                   DLIF_malloc(strlen(dyn_module->strtab + soname_offset) + 1);
1821         if(dyn_module->name) {
1822             strcpy(dyn_module->name, dyn_module->strtab + soname_offset);
1823 #if LOADER_DEBUG
1824             if (debugging_on)
1825                 DLIF_trace("Name of dynamic object: %s\n", dyn_module->name);
1826 #endif
1827         }
1828         else {
1829             DLIF_error(DLET_MISC, "Error allocating memory %d.\n",__LINE__);
1830             return FALSE;
1831         }
1832     }
1833
1834     return TRUE;
1835 }
1836
1837
1838 /*****************************************************************************/
1839 /* dload_dynamic_information()                                               */
1840 /*                                                                           */
1841 /*    Given a dynamic module with a dynamic segment which is located via     */
1842 /*    given dynamic segment index, make a local copy of the dynamic table    */
1843 /*    in the dynamic module object, then process the dynamic tag entries in  */
1844 /*    the table.                                                             */
1845 /*                                                                           */
1846 /*****************************************************************************/
1847 static BOOL dload_dynamic_information(LOADER_FILE_DESC *fd,
1848                                       DLIMP_Dynamic_Module *dyn_module,
1849                                       Elf32_Word dyn_seg_idx)
1850 {
1851     /*-----------------------------------------------------------------------*/
1852     /* Read a copy of the dynamic table into the dynamic module object.      */
1853     /*-----------------------------------------------------------------------*/
1854     copy_dynamic_table(fd, dyn_module, dyn_seg_idx);
1855
1856     /*-----------------------------------------------------------------------*/
1857     /* Process dynamic entries in the dynamic table.  If any problems are    */
1858     /* encountered, the loader should emit an error or warning and return    */
1859     /* FALSE here.                                                           */
1860     /*-----------------------------------------------------------------------*/
1861     return process_dynamic_table(fd, dyn_module);
1862 }
1863
1864 /*****************************************************************************/
1865 /* check_circular_dependency()                                               */
1866 /*                                                                           */
1867 /*    Determine whether a dynamic module is already in the process of being  */
1868 /*    loaded before we try to start loading it again.  If it is already      */
1869 /*    being loaded, then the dynamic loader has detected a circular          */
1870 /*    dependency.  An error will be emitted and the load will be aborted.    */
1871 /*                                                                           */
1872 /*****************************************************************************/
1873 static BOOL check_circular_dependency(DLOAD_HANDLE handle,
1874                                       const char *dyn_mod_name)
1875 {
1876     /*-----------------------------------------------------------------------*/
1877     /* Check the name of the given dependency module to be loaded against    */
1878     /* the list of modules that are currently in the process of being        */
1879     /* loaded.  Report an error if any circular dependencies are detected.   */
1880     /*-----------------------------------------------------------------------*/
1881     int i;
1882     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
1883
1884     for (i = 0; i < pHandle->DLIMP_module_dependency_list.size; i++)
1885         if (!strcmp(dyn_mod_name,
1886             ((char**)(pHandle->DLIMP_module_dependency_list.buf))[i]))
1887         {
1888             DLIF_error(DLET_MISC,
1889                        "Circular dependency detected, '%s' is already in the "
1890                        "process of loading.\n", dyn_mod_name);
1891             return FALSE;
1892         }
1893
1894     return TRUE;
1895 }
1896
1897 /*****************************************************************************/
1898 /* dload_dynamic_segment()                                                   */
1899 /*                                                                           */
1900 /*    Find the dynamic segment in the given ELF module, if there is one.     */
1901 /*    If there is a dynamic segment, then make a local copy of the dynamic   */
1902 /*    table in the dynamic module object provided, then process the dynamic  */
1903 /*    tag entries in the table.                                              */
1904 /*                                                                           */
1905 /*    If there is no dynamic segment, then we return success from this       */
1906 /*    function, marking the dynamic module as "not relocatable".             */
1907 /*                                                                           */
1908 /*****************************************************************************/
1909 static BOOL dload_dynamic_segment(DLOAD_HANDLE handle,
1910                                   LOADER_FILE_DESC *fd,
1911                                   DLIMP_Dynamic_Module *dyn_module)
1912 {
1913     /*-----------------------------------------------------------------------*/
1914     /* If we don't find dynamic segment, the relocatable flag will have been */
1915     /* set to false to indicate that the module is a static executable.  We  */
1916     /* still return TRUE from this function so that we can proceed with      */
1917     /* static loading.                                                       */
1918     /*-----------------------------------------------------------------------*/
1919     Elf32_Word dyn_seg_idx = 0;
1920     if (!find_dynamic_segment(dyn_module, &dyn_seg_idx))
1921         return TRUE;
1922
1923     /*-----------------------------------------------------------------------*/
1924     /* Process the OSABI now, after we know if the module is relocatable.    */
1925     /*-----------------------------------------------------------------------*/
1926     if (!process_eiosabi(dyn_module))
1927     {
1928         DLIF_error(DLET_FILE, "Unsupported EI_OSABI value.\n");
1929         return FALSE;
1930     }
1931
1932     /*-----------------------------------------------------------------------*/
1933     /* Read the dynamic table from the ELF file, then process the dynamic    */
1934     /* tags in the table.                                                    */
1935     /*-----------------------------------------------------------------------*/
1936     if (!dload_dynamic_information(fd, dyn_module, dyn_seg_idx))
1937         return FALSE;
1938
1939     /*-----------------------------------------------------------------------*/
1940     /* Check to make sure that this module is not already being loaded.  If  */
1941     /* is, then it will cause a circular dependency to be introduced.        */
1942     /* Loader should detect circular dependencies and emit an error.         */
1943     /*-----------------------------------------------------------------------*/
1944     if (!check_circular_dependency(handle, dyn_module->name))
1945         return FALSE;
1946
1947     return TRUE;
1948 }
1949
1950 /*****************************************************************************/
1951 /* COPY_SEGMENTS() -                                                         */
1952 /*                                                                           */
1953 /*   Copy all segments into host memory.                                     */
1954 /*****************************************************************************/
1955 static void copy_segments(DLOAD_HANDLE handle, LOADER_FILE_DESC* fp,
1956                           DLIMP_Dynamic_Module* dyn_module, int* data)
1957 {
1958     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
1959     DLIMP_Loaded_Segment* seg =
1960        (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
1961     int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
1962     void **va = DLIF_malloc(seg_size * sizeof(void*));
1963
1964     if (!va) {
1965         DLIF_error(DLET_MISC, "Failed to allocate va in copy_segments.\n");
1966         return;
1967     }
1968     else
1969         *data = (int)va;
1970
1971     for (s=0; s<seg_size; s++)
1972     {
1973         struct DLOAD_MEMORY_REQUEST targ_req;
1974         targ_req.fp = fp;
1975         targ_req.segment = seg[s].obj_desc;
1976         targ_req.offset = seg[s].phdr.p_offset;
1977         targ_req.flags = DLOAD_SF_relocatable;
1978         if (seg[s].phdr.p_flags & PF_X)
1979             seg[s].phdr.p_flags |= DLOAD_SF_executable;
1980         targ_req.align = seg[s].phdr.p_align;
1981
1982         /*-------------------------------------------------------------------*/
1983         /* Copy segment data from the file into host buffer where it can     */
1984         /* be relocated.                                                     */
1985         /*-------------------------------------------------------------------*/
1986         DLIF_copy(pHandle->client_handle, &targ_req);
1987
1988         va[s] = targ_req.host_address;
1989
1990         /*-------------------------------------------------------------------*/
1991         /* Calculate offset for relocations.                                 */
1992         /*-------------------------------------------------------------------*/
1993         seg[s].reloc_offset = (int32_t)(targ_req.host_address) -
1994                               (int32_t)(seg[s].obj_desc->target_address);
1995     }
1996 }
1997
1998 /*****************************************************************************/
1999 /* WRITE_SEGMENTS() -                                                        */
2000 /*                                                                           */
2001 /*   Write all segments to target memory.                                    */
2002 /*****************************************************************************/
2003 static void write_segments(DLOAD_HANDLE handle, LOADER_FILE_DESC* fp,
2004                           DLIMP_Dynamic_Module* dyn_module, int* data)
2005 {
2006     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2007     DLIMP_Loaded_Segment* seg =
2008         (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
2009     int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
2010     void **va = (void *)*data;
2011
2012     if (!va) {
2013         DLIF_error(DLET_MISC, "Invalid host virtual address array passed into"
2014                    "write_segments.\n");
2015         return;
2016     }
2017
2018     for (s=0; s<seg_size; s++)
2019     {
2020         struct DLOAD_MEMORY_REQUEST targ_req;
2021         targ_req.fp = fp;
2022         targ_req.segment = seg[s].obj_desc;
2023         targ_req.offset = seg[s].phdr.p_offset;
2024         targ_req.flags = DLOAD_SF_relocatable;
2025         if (seg[s].phdr.p_flags & PF_X)
2026             seg[s].phdr.p_flags |= DLOAD_SF_executable;
2027         targ_req.align = seg[s].phdr.p_align;
2028         targ_req.host_address = va[s];
2029
2030         /*-------------------------------------------------------------------*/
2031         /* Copy segment data from the file into host buffer where it can     */
2032         /* be relocated.                                                     */
2033         /*-------------------------------------------------------------------*/
2034         DLIF_write(pHandle->client_handle, &targ_req);
2035     }
2036
2037     DLIF_free(va);
2038 }
2039
2040 /*****************************************************************************/
2041 /* DLOAD_initialize()                                                        */
2042 /*                                                                           */
2043 /*    Construct and initialize data structures internal to the dynamic       */
2044 /*    loader core.                                                           */
2045 /*                                                                           */
2046 /*---------------------------------------------------------------------------*/
2047 /*                                                                           */
2048 /*    This implementation of DLOAD_initialize() will set up the list of      */
2049 /*    dependency modules maintained by the loader core.  This list contains  */
2050 /*    the names of the files that the loader is in the process of loading.   */
2051 /*    The list is used to keep track of what objects are waiting on their    */
2052 /*    dependents to be loaded so thath circular dependencies can be detected */
2053 /*    and reported by the core loader.                                       */
2054 /*                                                                           */
2055 /*****************************************************************************/
2056 void DLOAD_initialize(DLOAD_HANDLE handle)
2057 {
2058      LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2059
2060     /*-----------------------------------------------------------------------*/
2061     /* Set up initial objects_loading queue.                                 */
2062     /*-----------------------------------------------------------------------*/
2063     AL_initialize(&pHandle->DLIMP_module_dependency_list,
2064                   sizeof (const char*), 1);
2065 }
2066
2067
2068 /*****************************************************************************/
2069 /* DLOAD_finalize()                                                          */
2070 /*                                                                           */
2071 /*    Destroy and finalize data structures internal to the dynamic           */
2072 /*    loader core.                                                           */
2073 /*                                                                           */
2074 /*---------------------------------------------------------------------------*/
2075 /*                                                                           */
2076 /*    This implementation of DLOAD_finalize() will destroy the list of       */
2077 /*    dependency modules maintained by the loader core that is created       */
2078 /*    during DLOAD_initialize().                                             */
2079 /*                                                                           */
2080 /*****************************************************************************/
2081 void DLOAD_finalize(DLOAD_HANDLE handle)
2082 {
2083     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2084
2085     /*-----------------------------------------------------------------------*/
2086     /* Destroy initial objects_loading queue.                                */
2087     /*-----------------------------------------------------------------------*/
2088     AL_destroy(&pHandle->DLIMP_module_dependency_list);
2089 }
2090
2091
2092 /*****************************************************************************/
2093 /* dload_static_executable()                                                 */
2094 /*                                                                           */
2095 /*    Account for target memory allocated to static executable and wrap up   */
2096 /*    loading.  No relocation is necessary.                                  */
2097 /*                                                                           */
2098 /*****************************************************************************/
2099 static int32_t dload_static_executable(DLOAD_HANDLE handle,
2100                                        LOADER_FILE_DESC *fd,
2101                                        DLIMP_Dynamic_Module *dyn_module)
2102 {
2103     int32_t local_file_handle = 0;
2104
2105 #if LOADER_DEBUG
2106     if (debugging_on) DLIF_trace("Starting dload_static_executable() ...\n");
2107 #endif
2108
2109     /*-----------------------------------------------------------------------*/
2110     /*-----------------------------------------------------------------------*/
2111     /* Set entry point for static executable and attempt to allocate target  */
2112     /* memory for the static executable.                                     */
2113     /*-----------------------------------------------------------------------*/
2114     dyn_module->loaded_module->entry_point = dyn_module->fhdr.e_entry;
2115     if (load_static_segment(handle, fd, dyn_module) &&
2116         load_object(fd, dyn_module))
2117     {
2118         /*-------------------------------------------------------------------*/
2119         /* If successful, we'll want to detach the loaded module object from */
2120         /* the dynamic module object that created it.  Take note of the file */
2121         /* handle.                                                           */
2122         /*-------------------------------------------------------------------*/
2123         DLIMP_Loaded_Module *loaded_module = detach_loaded_module(dyn_module);
2124         if (loaded_module)
2125             local_file_handle = loaded_module->file_handle;
2126         else {
2127             DLIF_error(DLET_MISC, "Failed to detach module.\n");
2128             delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2129             return local_file_handle;
2130         }
2131    }
2132
2133     /*-----------------------------------------------------------------------*/
2134     /* Static load failed.  Flag an error.                                   */
2135     /*-----------------------------------------------------------------------*/
2136     else
2137     {
2138         DLIF_trace("%s:%d EMEMORY\n",__func__,__LINE__);
2139         DLIF_error(DLET_MEMORY,
2140                    "Failed to allocate target memory for static executable.\n");
2141     }
2142
2143     /*-----------------------------------------------------------------------*/
2144     /* Destruct dynamic module object.                                       */
2145     /*-----------------------------------------------------------------------*/
2146     delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2147
2148 #if LOADER_DEBUG
2149     if (debugging_on) DLIF_trace("Finished dload_static_executable()\n");
2150 #endif
2151
2152     return local_file_handle;
2153 }
2154
2155 /*****************************************************************************/
2156 /* process_dynamic_module_relocations()                                      */
2157 /*                                                                           */
2158 /*    Make a host-accessible copy of all of the segments, process all        */
2159 /*    relocation entries associated with the given module within that        */
2160 /*    space, then write the updated segment buffers back out to target       */
2161 /*    memory.                                                                */
2162 /*                                                                           */
2163 /*****************************************************************************/
2164 static void process_dynamic_module_relocations(DLOAD_HANDLE handle,
2165                                                LOADER_FILE_DESC *fd,
2166                                                DLIMP_Dynamic_Module *dyn_module)
2167 {
2168     int data = 0;
2169
2170 #if LOADER_DEBUG || LOADER_PROFILE
2171     if(debugging_on || profiling_on)
2172     {
2173         DLIF_trace("Running relocate()...\n");
2174         if (profiling_on) profile_start_clock();
2175     }
2176 #endif
2177
2178     /*-----------------------------------------------------------------------*/
2179     /* Copy segments from file to host memory                                */
2180     /*-----------------------------------------------------------------------*/
2181     copy_segments(handle, fd, dyn_module, &data);
2182
2183    /*------------------------------------------------------------------------*/
2184    /* Process dynamic relocations.                                           */
2185    /*------------------------------------------------------------------------*/
2186 #if ARM_TARGET
2187    if (is_arm_module(&dyn_module->fhdr))
2188       DLREL_relocate(handle, fd, dyn_module);
2189 #endif
2190
2191 #if C60_TARGET
2192    if (is_c60_module(&dyn_module->fhdr))
2193       DLREL_relocate_c60(handle, fd, dyn_module);
2194 #endif
2195
2196     /*-----------------------------------------------------------------------*/
2197     /* Write segments from host memory to target memory                      */
2198     /*-----------------------------------------------------------------------*/
2199     write_segments(handle, fd, dyn_module, &data);
2200
2201 #if LOADER_DEBUG || LOADER_PROFILE
2202     /*-----------------------------------------------------------------------*/
2203     /* Report timing and progress information for relocation step.           */
2204     /*-----------------------------------------------------------------------*/
2205     if (debugging_on || profiling_on)
2206     {
2207         if (profiling_on)
2208         {
2209             profile_stop_clock();
2210             DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
2211             DLIF_trace("Total reloc time: %d\n", (int)DLREL_total_reloc_time);
2212             DLIF_trace("Time per relocation: %d\n",
2213                        (DLREL_relocations ?
2214                         (int)(DLREL_total_reloc_time / DLREL_relocations) : 0));
2215         }
2216
2217         DLIF_trace("Number of relocations: %d\n", DLREL_relocations);
2218         DLIF_trace("\nAbout to run load_object()...");
2219         DLREL_total_reloc_time = DLREL_relocations = 0;
2220         if (profiling_on) profile_start_clock();
2221     }
2222 #endif
2223 }
2224
2225 /*****************************************************************************/
2226 /* execute_module_pre_initialization()                                       */
2227 /*                                                                           */
2228 /*    Given a dynamic module object, execute any pre-initialization          */
2229 /*    functions for the specified dynamic executable module. Such functions  */
2230 /*    must be provided by the user and their addresses written to the        */
2231 /*    .preinit_array section. These functions should be executed in the      */
2232 /*    order that they are specified in the array before the initialization   */
2233 /*    process for this dynamic executable module begins.                     */
2234 /*                                                                           */
2235 /*---------------------------------------------------------------------------*/
2236 /*                                                                           */
2237 /*    Note that dynamic shared objects (libraries) should not have a         */
2238 /*    .preinit_array (should be caught during static link-time if the user   */
2239 /*    attempts to link a .preinit_array section into a shared object.        */
2240 /*                                                                           */
2241 /*****************************************************************************/
2242 static void execute_module_pre_initialization(DLOAD_HANDLE handle, DLIMP_Dynamic_Module *dyn_module)
2243 {
2244     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2245
2246     /*-----------------------------------------------------------------------*/
2247     /* Check for presence of DT_PREINIT_ARRAY and DT_PREINIT_ARRAYSZ         */
2248     /* dynamic tags associated with this module. The dyn_module object will  */
2249     /* hold the relevant indices into the local copy of the dynamic table.   */
2250     /* The value of the DT_INIT_ARRAY tag will have been updated after       */
2251     /* placement of the  module was completed.                               */
2252     /*-----------------------------------------------------------------------*/
2253     if (dyn_module->preinit_arraysz != 0)
2254     {
2255         /*-------------------------------------------------------------------*/
2256         /* Retrieve the address of the .preinit_array section from the value */
2257         /* of the DT_PREINIT_ARRAY tag.                                      */
2258         /*-------------------------------------------------------------------*/
2259         TARGET_ADDRESS preinit_array_loc = (TARGET_ADDRESS)
2260                 (dyn_module->dyntab[dyn_module->preinit_array_idx].d_un.d_ptr);
2261
2262         /*-------------------------------------------------------------------*/
2263         /* Now make a loader-accessible copy of the .preinit_array section.  */
2264         /*-------------------------------------------------------------------*/
2265         int32_t i;
2266         int32_t num_preinit_fcns =
2267                             dyn_module->preinit_arraysz/sizeof(TARGET_ADDRESS);
2268         TARGET_ADDRESS *preinit_array_buf = (TARGET_ADDRESS *)
2269                                       DLIF_malloc(dyn_module->preinit_arraysz);
2270         if(preinit_array_buf) {
2271             DLIF_read(pHandle->client_handle, preinit_array_buf, 1,
2272                       dyn_module->preinit_arraysz,
2273                       (TARGET_ADDRESS)preinit_array_loc);
2274
2275             /*---------------------------------------------------------------*/
2276             /* Call each function whose address occupies an entry in the     */
2277             /* array in the order that it appears in the array. The sizeof   */
2278             /* the array is provided by the preinit_arraysz field in the     */
2279             /* dynamic module (copied earlier when the dynamic table was     */
2280             /* read in). We need to divide the sizeof value down to get the  */
2281             /* number of actual entries in the array.                        */
2282             /*---------------------------------------------------------------*/
2283             for (i = 0; i < num_preinit_fcns; i++)
2284                 DLIF_execute(pHandle->client_handle,
2285                              (TARGET_ADDRESS)(preinit_array_buf[i]));
2286
2287             DLIF_free(preinit_array_buf);
2288         }
2289     }
2290 }
2291
2292 /*****************************************************************************/
2293 /* execute_module_initialization()                                           */
2294 /*                                                                           */
2295 /*    Given a dynamic module object, execute initialization function(s) for  */
2296 /*    all global and static data objects that are defined in the module      */
2297 /*    which require construction. The user may also provide a custom         */
2298 /*    iniitialization function that needs to be executed before the compiler */
2299 /*    generated static initialization functions are executed.                */
2300 /*                                                                           */
2301 /*****************************************************************************/
2302 static void execute_module_initialization(DLOAD_HANDLE handle,
2303                                           DLIMP_Dynamic_Module *dyn_module)
2304 {
2305     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2306
2307     /*-----------------------------------------------------------------------*/
2308     /* Check for presence of a DT_INIT dynamic tag associated with this      */
2309     /* module. The dynamic module will hold the index into the local copy of */
2310     /* the dynamic table. This entry in the dynamic table will have been     */
2311     /* updated after placement of the module is completed.                   */
2312     /*-----------------------------------------------------------------------*/
2313     if (dyn_module->init_idx != -1)
2314     {
2315         /*-------------------------------------------------------------------*/
2316         /* Retrieve the address of the initialization function from the      */
2317         /* value of the DT_INIT tag, and get the client to execute the       */
2318         /* function.                                                         */
2319         /*-------------------------------------------------------------------*/
2320         TARGET_ADDRESS init_fcn = (TARGET_ADDRESS)
2321                          (dyn_module->dyntab[dyn_module->init_idx].d_un.d_ptr);
2322         DLIF_execute(pHandle->client_handle, init_fcn);
2323     }
2324
2325     /*-----------------------------------------------------------------------*/
2326     /* Check for presence of a DT_INIT_ARRAY and DT_INIT_ARRAYSZ dynamic     */
2327     /* tags associated with this module. The dyn_module object will hold the */
2328     /* relevant indices into the local copy of the dynamic table. The value  */
2329     /* of the DT_INIT_ARRAY tag will have been updated after placement of    */
2330     /* the module was completed.                                             */
2331     /*-----------------------------------------------------------------------*/
2332     if (dyn_module->init_arraysz != 0)
2333     {
2334         /*-------------------------------------------------------------------*/
2335         /* Retrieve the address of the .init_array section from the value of */
2336         /* DT_INIT_ARRAY tag.                                                */
2337         /*-------------------------------------------------------------------*/
2338         TARGET_ADDRESS init_array_loc = (TARGET_ADDRESS)
2339                    (dyn_module->dyntab[dyn_module->init_array_idx].d_un.d_ptr);
2340
2341         /*-------------------------------------------------------------------*/
2342         /* Now make a loader-accessible copy of the .init_array section.     */
2343         /*-------------------------------------------------------------------*/
2344         int32_t i;
2345         int32_t num_init_fcns = dyn_module->init_arraysz/sizeof(TARGET_ADDRESS);
2346         TARGET_ADDRESS *init_array_buf = (TARGET_ADDRESS *)
2347                                          DLIF_malloc(dyn_module->init_arraysz);
2348         if(init_array_buf) {
2349             DLIF_read(pHandle->client_handle, init_array_buf, 1,
2350                       dyn_module->init_arraysz, (TARGET_ADDRESS)init_array_loc);
2351
2352             /*---------------------------------------------------------------*/
2353             /* Call each function whose address occupies an entry in the     */
2354             /* array in the order that they appear in the array. The size of */
2355             /* the array is provided by the init_arraysz field in the        */
2356             /* dynamic module (copied earlier when the dynamic table was     */
2357             /* read in).                                                     */
2358             /*---------------------------------------------------------------*/
2359             for (i = 0; i < num_init_fcns; i++)
2360                 DLIF_execute(pHandle->client_handle,
2361                              (TARGET_ADDRESS)(init_array_buf[i]));
2362