QNX: Loader: Fix Compilation Warnings
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / procMgr / hlos / knl / loaders / Elf / Qnx / DLOAD / DLOAD / dload.c
1 /*
2 * dload.c
3 *
4 * Core Dynamic Loader Reference Implementation
5 *
6 * This implementation of the core dynamic loader is platform independent,
7 * but it is object file format dependent.  In particular, this
8 * implementation supports ELF object file format.
9 *
10 * Copyright (C) 2009-2015 Texas Instruments Incorporated - http://www.ti.com/
11 *
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the
23 * distribution.
24 *
25 * Neither the name of Texas Instruments Incorporated nor the names of
26 * its contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 */
43 #include <limits.h>
44 #include <inttypes.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <time.h>
50 #include "ArrayList.h"
51 #include "Queue.h"
52 #include "Stack.h"
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"
61 #ifdef ARM_TARGET
62 #include "arm_dynamic.h"
63 #endif
65 #ifdef C60_TARGET
66 #include "c60_dynamic.h"
67 #endif
69 #include "virtual_targets.h"
71 /* #undef LOADER_DEBUG
72 #define LOADER_DEBUG 0*/
73 /*---------------------------------------------------------------------------*/
74 /* These globals are used only to test the reference client implementation.  */
75 /*---------------------------------------------------------------------------*/
76 int global_argc;
77 char **global_argv;
79 /*---------------------------------------------------------------------------*/
80 /* Contains filenames (type const char*) the system is in the process of     */
81 /* loading.  Used to detect cycles in incorrectly compiled ELF binaries.     */
82 /*---------------------------------------------------------------------------*/
83 Array_List DLIMP_module_dependency_list;
85 /*---------------------------------------------------------------------------*/
86 /* Contains objects (type DLIMP_Loaded_Module) that the system has loaded into     */
87 /* target memory.                                                            */
88 /*---------------------------------------------------------------------------*/
89 TYPE_QUEUE_IMPLEMENTATION(DLIMP_Loaded_Module*, loaded_module_ptr)
90 loaded_module_ptr_Queue DLIMP_loaded_objects = TYPE_QUEUE_INITIALIZER;
92 /*---------------------------------------------------------------------------*/
93 /* Dependency Graph Queue - FIFO queue of dynamic modules that are loaded    */
94 /* when client asks to load a dynamic executable or library. Note that       */
95 /* dependents that have already been loaded with another module will not     */
96 /* appear on this queue.                                                     */
97 /*---------------------------------------------------------------------------*/
98 TYPE_STACK_IMPLEMENTATION(DLIMP_Dynamic_Module*, dynamic_module_ptr)
99 dynamic_module_ptr_Stack DLIMP_dependency_stack = TYPE_STACK_INITIALIZER;
101 /*---------------------------------------------------------------------------*/
102 /* Current virtual target set after reading the file headers. This is used   */
103 /* to access target specific functions.                                      */
104 /*---------------------------------------------------------------------------*/
105 VIRTUAL_TARGET *cur_target = NULL;
107 /*---------------------------------------------------------------------------*/
108 /* Support for profiling performance of dynamic loader core.                 */
109 /*---------------------------------------------------------------------------*/
110 #if LOADER_DEBUG && LOADER_PROFILE
111 static clock_t cycle0 = 0;
112 static clock_t cycle_end = 0;
113 #define profile_start_clock() (cycle0 = clock())
114 #define profile_stop_clock()  (cycle_end = clock())
115 #define profile_cycle_count() (cycle_end - cycle0)
116 #endif
118 /*---------------------------------------------------------------------------*/
119 /* The dynamic loader will now create a table TI_init_table to store         */
120 /* pre-init and init data. This is done because pre-init and                 */
121 /* init functions could reference as-yet unrelocated symbols from other      */
122 /* modules. As such it is safer to store relevant function addresses and     */
123 /* execute them only after all modules are relocated.                        */
124 /*---------------------------------------------------------------------------*/
125 TYPE_QUEUE_IMPLEMENTATION(IF_single_record*, IF_table)
126 IF_table_Queue TI_init_table = TYPE_QUEUE_INITIALIZER;
128 static VIRTUAL_TARGET *get_vt_obj(int given_id);
129 static void read_args_from_section(DLIMP_Loaded_Module* ep_module);
130 static BOOL seg_has_space_for_write(DLIMP_Loaded_Module* lmodule, int sz);
131 static BOOL write_arguments_to_args_section(DLOAD_HANDLE handle,
132                                             int argc, char** argv,
133                         DLIMP_Loaded_Module *ep_module);
135 /*****************************************************************************/
136 /* DLOAD_create()                                                            */
137 /*                                                                           */
138 /*    Create an instance of the dynamic loader core.                         */
139 /*                                                                           */
140 /*    client_handle:  Private client token to be returned during select DLIF */
141 /*                   function calls.                                         */
142 /*                                                                           */
143 /*    returns: an opaque DLOAD core loader handle, identifying this instance.*/
144 /*                                                                           */
145 /*****************************************************************************/
146 DLOAD_HANDLE DLOAD_create(void *client_handle)
148     LOADER_OBJECT     * pLoaderObject;
150     pLoaderObject = DLIF_malloc(sizeof(LOADER_OBJECT));
152     /* Fill out the Loader Object: */
153     if (pLoaderObject != NULL) {
154         /*-------------------------------------------------------------------*/
155         /* Set up initial objects_loading queue.                             */
156         /*-------------------------------------------------------------------*/
157         AL_initialize(&(pLoaderObject->DLIMP_module_dependency_list),
158                       sizeof (const char*), 1);
160         /* Initialize Loaded Module Ptr Queue */
161         loaded_module_ptr_initialize_queue(&pLoaderObject->DLIMP_loaded_objects);
163         /* Initialize Dynamic Module Ptr Stack */
164         dynamic_module_ptr_initialize_stack(&pLoaderObject->DLIMP_dependency_stack);
166         pLoaderObject->file_handle = 1;
168         /* Store client token, so it can be handed back during DLIF calls */
169         pLoaderObject->client_handle = client_handle;
170     }
172     return((DLOAD_HANDLE)pLoaderObject);
175 /*****************************************************************************/
176 /* DLOAD_destroy()                                                           */
177 /*                                                                           */
178 /*    Remove an instance of the dynamic loader core, and free all resources  */
179 /*    allocated during DLOAD_create().                                       */
180 /*                                                                           */
181 /*    client_handle:  Private client token to be returned during select DLIF */
182 /*                   function calls.                                         */
183 /*    Preconditions: 1) handle must be valid.                                */
184 /*                   2) Loader instance must be in "UNLOADED" state.         */
185 /*                                                                           */
186 /*****************************************************************************/
187 void  DLOAD_destroy(DLOAD_HANDLE handle)
189     LOADER_OBJECT     * pLoaderObject;
191     pLoaderObject = (LOADER_OBJECT *)handle;
193     AL_destroy(&(pLoaderObject->DLIMP_module_dependency_list));
195     /*--------------------------*/
196     /* Free the instance object */
197     /*--------------------------*/
198     DLIF_free (pLoaderObject);
201 /*****************************************************************************/
202 /* DLIMP_get_first_dyntag()                                                  */
203 /*                                                                           */
204 /*    Return value for first tag entry in the given dynamic table whose      */
205 /*    tag type matches the given key.                                        */
206 /*                                                                           */
207 /*****************************************************************************/
208 uint32_t DLIMP_get_first_dyntag(int tag, struct Elf32_Dyn* dyn_table)
210    /*------------------------------------------------------------------------*/
211    /* Spin through dynamic segment looking for a specific dynamic tag.       */
212    /* Return the value associated with the tag, if the tag is found.         */
213    /*------------------------------------------------------------------------*/
214    struct Elf32_Dyn *dtp = dyn_table;
215    while (dtp->d_tag != DT_NULL)
216    {
217       if (dtp->d_tag == tag) return dtp->d_un.d_val;
218       else dtp++;
219    }
221    /*------------------------------------------------------------------------*/
222    /* Tag wasn't found, return a known bogus value for the tag.              */
223    /*------------------------------------------------------------------------*/
224    return INT_MAX;
227 /*****************************************************************************/
228 /* dload_and_allocate_dependencies()                                         */
229 /*                                                                           */
230 /*    If not already loaded, load each dependent file identified in the      */
231 /*    dynamic segment with a DT_NEEDED tag.  Dependent files are listed in   */
232 /*    order and should be loaded in the same order that they appear in the   */
233 /*    dynamic segment.                                                       */
234 /*                                                                           */
235 /*****************************************************************************/
236 static BOOL dload_and_allocate_dependencies(DLOAD_HANDLE handle,
237                                             DLIMP_Dynamic_Module *dyn_module)
239    /*------------------------------------------------------------------------*/
240    /* Spin through each dynamic tag entry in the dynamic segment.            */
241    /*------------------------------------------------------------------------*/
242    struct Elf32_Dyn* dyn_nugget = dyn_module->dyntab;
243     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
245 #if LOADER_DEBUG
246    if (debugging_on)
247       DLIF_trace("Starting dload_and_allocate_dependencies() for %s ...\n",
248              dyn_module->name);
249 #endif
251    while(dyn_nugget->d_tag != DT_NULL)
252    {
253       /*---------------------------------------------------------------------*/
254       /* For each DT_NEEDED dynamic tag that we find in the dynamic segment, */
255       /* load the dependent file identified by the so_name value attached    */
256       /* to the DT_NEEDED dynamic tag.                                       */
257       /*---------------------------------------------------------------------*/
258       if (dyn_nugget->d_tag == DT_NEEDED)
259       {
260          loaded_module_ptr_Queue_Node* ptr;
262 #if LOADER_DEBUG
263          if (debugging_on)
264             DLIF_trace("Found DT_NEEDED: %s\n",
265                    dyn_module->strtab+dyn_nugget->d_un.d_val);
266 #endif
268          /*------------------------------------------------------------------*/
269          /* Find out if the file named by the DT_NEEDED tag has already      */
270          /* been loaded.  If it has, then we only have to bump the use count */
271          /* of the named dependent file.                                     */
272          /*------------------------------------------------------------------*/
273             for (ptr = pHandle->DLIMP_loaded_objects.front_ptr; ptr != NULL;
274               ptr = ptr->next_ptr)
275          {
276             if (!strcmp(ptr->value->name,
277                                    dyn_module->strtab + dyn_nugget->d_un.d_val))
278             {
279                ptr->value->use_count++;
280                AL_append(&(dyn_module->loaded_module->dependencies),
281                                                 &(ptr->value->file_handle));
282                break;
283             }
284          }
286          /*------------------------------------------------------------------*/
287          /* If the named dependent file has not been loaded, then we ask the */
288          /* client to invoke a load of the dependent file on our behalf.     */
289          /*------------------------------------------------------------------*/
290          if (ptr == NULL)
291          {
292             int32_t dependent_handle = DLIF_load_dependent(
293                                                        pHandle->client_handle,
294                                                        dyn_module->strtab +
295                                                        dyn_nugget->d_un.d_val);
296             AL_append(&(dyn_module->loaded_module->dependencies),
297                                                         &dependent_handle);
298             if (dependent_handle == 0) return FALSE;
299          }
300       }
302       dyn_nugget++;
303    }
305 #if LOADER_DEBUG
306    if (debugging_on)
307       DLIF_trace("Finished dload_and_allocate_dependencies() for %s\n",
308              dyn_module->name);
309 #endif
311    return TRUE;
314 /*****************************************************************************/
315 /* load_object()                                                             */
316 /*                                                                           */
317 /*    Finish the process of loading an object file.                          */
318 /*                                                                           */
319 /*****************************************************************************/
320 static int load_object(LOADER_FILE_DESC *fd, DLIMP_Dynamic_Module *dyn_module)
322    /*------------------------------------------------------------------------*/
323    /* With the dynamic loader already running on the target, we are able to  */
324    /* relocate directly into target memory, so there is nothing more to be   */
325    /* done (at least in the bare-metal dynamic linking ABI model).           */
326    /*------------------------------------------------------------------------*/
327    return 1;
330 /*****************************************************************************/
331 /* write_arguments_to_args_section()                                         */
332 /*                                                                           */
333 /*    Write argv and argc to .args section.                                  */
334 /*                                                                           */
335 /*****************************************************************************/
336 static BOOL write_arguments_to_args_section(DLOAD_HANDLE handle,
337                                             int argc, char** argv,
338                                             DLIMP_Loaded_Module *ep_module)
340    int mem_inc   = MEM_INC;
341    int ptr_sz    = PTR_SZ;
342    int p_size    = ptr_sz / mem_inc;
343    int i_size    = T_INTSZ / mem_inc;
344    int c_size    = T_CHARSZ /mem_inc;
345    int argv_offset = 0;
346    int str_offset  = 0;
347    int size        = 0;
348    int arg;
349    int *targ_argv_pointers = NULL;
350    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
352    uint8_t *c_args = NULL;
354 #if LOADER_DEBUG
355    if (debugging_on)
356       DLIF_trace("Write_arguments_to_args_section:\n");
357 #endif
359    /*-----------------------------------------------------------------------*/
360    /* IF NO ARGUMENTS, ABORT QUIETLY, WITH a SUCCESSFUL CODE.               */
361    /*-----------------------------------------------------------------------*/
362    if (argc == 0) return TRUE;
364    /*-----------------------------------------------------------------------*/
365    /* __c_args__ points to the beginning of the .args section, if there     */
366    /* is one.  This is stored in the Loaded Module, and must have a         */
367    /* legitimate address. If not, abort with Warning.                       */
368    /*-----------------------------------------------------------------------*/
369    c_args = ep_module->c_args;
370    if (!c_args || c_args == (uint8_t *)0xFFFFFFFF)
371    {
372       DLIF_warning(DLWT_MISC, "__c_args__ does not have valid value.\n");
373       return FALSE;
374    }
376    /*-----------------------------------------------------------------------*/
377    /* WE OUGHT TO WORRY ABOUT ALIGNMENT: IF SECTION ISN'T PROPERLY ALIGNED, */
378    /* ABORT THE PROCESSING OF ARGUMENTS WITH A NICE ERROR MESSAGE.          */
379    /*-----------------------------------------------------------------------*/
380    if (c_args && ((Elf32_Addr)c_args & (MAX(p_size, i_size) - 1)))
381    {
382       DLIF_warning(DLWT_MISC, ".args section not properly aligned\n");
383       return FALSE;
384    }
386    /*-----------------------------------------------------------------------*/
387    /* CALCULATE OFFSET IN TABLE WHERE ARGV AND THE STRINGS WILL BE STORED.  */
388    /* NOTE THAT argv MAY NEED MORE ALIGNMENT THAN AN INTEGER, SO ITS OFFSET */
389    /* IS REALLY THE MAXIMUM OF A POINTER SIZE AND INTEGER SIZE.  ALSO NOTE  */
390    /* WE NEED TO ALLOCATE AN EXTRA POINTER FOR argv[argc].                  */
391    /*-----------------------------------------------------------------------*/
392    argv_offset = MAX(p_size, i_size);
393    str_offset  = argv_offset + (argc * p_size) + p_size ;
395    /*-----------------------------------------------------------------------*/
396    /* CALCULATE SPACE REQUIRED FOR WRITING OUT .args SECTION. CHECK IF THE  */
397    /* SEGMENT HAS ENOUGH SPACE AVAILABLE. IF NOT, RETURN WITH ERROR CODE.   */
398    /*-----------------------------------------------------------------------*/
399    size = str_offset;
401    for (arg = 0; arg < argc; arg++)
402         size += (c_size * (strlen(argv[arg]) + 1));
404    if (!seg_has_space_for_write(ep_module, size))
405    {
406       DLIF_warning(DLWT_MISC,
407                  "Segment has insufficient space for .args contents\n");
408       return FALSE;
409    }
411    /*-----------------------------------------------------------------------*/
412    /* OVERALL, WE NEED TO CREATE A TARGET IMAGE THAT CORRESPONDS TO:        */
413    /*     int argc;                                                         */
414    /*     char *argv[argc];                                                 */
415    /*     <strings pointed to by argv>                                      */
416    /* So say, for C6x, for "-v -d", we would need 22 bytes:                 */
417    /*     4 bytes // argc                                                   */
418    /*     4 bytes // argv[0] pointer value                                  */
419    /*     4 bytes // argv[1] pointer value                                  */
420    /*     4 bytes // argv[argc] end of pointer value array, normally 0      */
421    /*     3 bytes // "-v"                                                   */
422    /*     3 bytes // "-d"                                                   */
423    /*-----------------------------------------------------------------------*/
425    /*-----------------------------------------------------------------------*/
426    /* FIRST WRITE OUT ARGC.                                                 */
427    /*-----------------------------------------------------------------------*/
428 #if LOADER_DEBUG
429    if (debugging_on)
430       DLIF_trace ("-- Copy %d bytes from 0x%x to 0x%x\n",
431                   i_size, (uint32_t) &argc, (uint32_t) c_args);
432 #endif
434    DLIF_memcpy(pHandle->client_handle, c_args, &argc, i_size);
436    /*-----------------------------------------------------------------------*/
437    /* CREATE AN INTERNAL ARRAY OF ARGV POINTER VALUES, THEN WRITE THEM OUT  */
438    /*-----------------------------------------------------------------------*/
439    targ_argv_pointers = (int *)DLIF_malloc((argc + 1) * sizeof(int));
440    for (arg = 0; arg < argc ; arg++)
441    {
442        targ_argv_pointers[arg] = (int)(str_offset + c_args);
443        str_offset += (strlen(argv[arg]) + 1) * c_size;
445 #if LOADER_DEBUG
446    if (debugging_on)
447        DLIF_trace ("\t\ttarg_argv_pointers[%d] : 0x%x\n",
448                    arg, targ_argv_pointers[arg]);
449 #endif
450    }
452    targ_argv_pointers[argc] = 0;
454    /*-----------------------------------------------------------------------*/
455    /* WRITE OUT THIS INTERNAL ARRAY OF ARGV POINTER VALUES                  */
456    /*-----------------------------------------------------------------------*/
457    for (arg = 0; arg <= argc; arg++)
458    {
459 #if LOADER_DEBUG
460    if (debugging_on)
461        DLIF_trace ("-- Copy %d bytes from 0x%x to 0x%x\n",
462                    p_size, (uint32_t) &targ_argv_pointers[arg],
463                    (uint32_t) (c_args + argv_offset));
464 #endif
465        DLIF_memcpy(pHandle->client_handle,
466                    (void *)(c_args + argv_offset),
467                    &targ_argv_pointers[arg],
468            p_size);
469        argv_offset += p_size;
470    }
472 #if LOADER_DEBUG
473 if (debugging_on)
475    DLIF_trace ("\t\targv being copied : 0x%x\n",(uint32_t)argv);
476    for (arg = 0; arg < argc; arg++)
477    {
478        DLIF_trace ("\t\t---\n\t\t&argv[%d] being copied : 0x%x\n", arg,
479                    (uint32_t)&argv[arg]);
480        DLIF_trace ("\t\targv[%d] being copied : 0x%x\n",arg,
481                    (uint32_t)argv[arg]);
482        DLIF_trace ("\t\targv[%d] being copied : %s\n",arg, (char *)argv[arg]);
483    }
485 #endif
487    /*-----------------------------------------------------------------------*/
488    /* LASTLY WRITE OUT ALL THE STRINGS.                                     */
489    /*-----------------------------------------------------------------------*/
490    for (arg = 0; arg < argc; arg++)
491    {
492 #if LOADER_DEBUG
493    if (debugging_on)
494       DLIF_trace ("-- Copy %d bytes from 0x%x to 0x%x\n",
495                   (uint32_t)strlen(argv[arg]) + 1,
496                   (uint32_t)&argv[arg],
497                   (uint32_t)(targ_argv_pointers[arg]));
498 #endif
499       DLIF_memcpy(pHandle->client_handle,
500                   (void *)(targ_argv_pointers[arg]),
501                   argv[arg],
502                   strlen(argv[arg]) + 1);
503    }
505   return TRUE;
509 /*****************************************************************************/
510 /* initialize_loaded_module()                                                */
511 /*                                                                           */
512 /*    Initialize DLIMP_Loaded_Module internal data object associated with a  */
513 /*    dynamic module.  This function will also set up a queue of             */
514 /*    DLIMP_Loaded_Segment(s) associated with the loaded module.             */
515 /*    This function is called as we are getting ready to actually load the   */
516 /*    object file contents into target memory.  Each segment will get a      */
517 /*    target memory request that it can use to ask the client for target     */
518 /*    memory space.  This function will also assign a file handle to the     */
519 /*    loaded module.                                                         */
520 /*                                                                           */
521 /*---------------------------------------------------------------------------*/
522 /*                                                                           */
523 /* In applications that use the DSBT model, this function will also need to  */
524 /* negotiate the module's DSBT index with the client.                        */
525 /*                                                                           */
526 /*****************************************************************************/
527 static void initialize_loaded_module(DLOAD_HANDLE handle,
528                                      DLIMP_Dynamic_Module *dyn_module)
530    int i;
531     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
533    /*------------------------------------------------------------------------*/
534    /* Allocate a DLIMP_Loaded_Module data structure for the specified ELF    */
535    /* file and assign a file handle for it (bumping the file handle counter  */
536    /* as we go).                                                             */
537    /*------------------------------------------------------------------------*/
538    DLIMP_Loaded_Module *loaded_module =
539           dyn_module->loaded_module = DLIF_malloc(sizeof(DLIMP_Loaded_Module));
541    if(loaded_module == NULL) {
542 #if LOADER_DEBUG && LOADER_PROFILE
543       if(debugging_on)
544          DLIF_error(DLET_MISC, "Error allocating memory %d...\n",__LINE__);
545 #endif
546       return;
547    }
548 #if LOADER_DEBUG && LOADER_PROFILE
549    /*------------------------------------------------------------------------*/
550    /* Start clock on initialization of loaded module object.                 */
551    /*------------------------------------------------------------------------*/
552    if (debugging_on || profiling_on)
553    {
554       DLIF_trace("Starting initialize_loaded_module() ...\n");
555       if (profiling_on) profile_start_clock();
556    }
557 #endif
559    if (dyn_module->name)
560    {
561       loaded_module->name = DLIF_malloc(strlen(dyn_module->name) + 1);
562       if (NULL == loaded_module->name) {
563           DLIF_error(DLET_MISC, "Error allocating memory %d...\n",__LINE__);
564           return;
565       }
566       strcpy(loaded_module->name, dyn_module->name);
567    }
568    else
569       loaded_module->name = "<unknown>";
571    loaded_module->file_handle = pHandle->file_handle++;
572    loaded_module->direct_dependent_only = dyn_module->direct_dependent_only;
573    loaded_module->use_count = 1;
574    loaded_module->c_args = 0;
576    /*------------------------------------------------------------------------*/
577    /* In case we wrapped around the file handle, return error.               */
578    /*------------------------------------------------------------------------*/
579    if (pHandle->file_handle == 0)
580       DLIF_error(DLET_MISC, "DLOAD File handle overflowed.\n");
582    /*------------------------------------------------------------------------*/
583    /* Initially the loaded module does not have access to its global         */
584    /* symbols.  These need to be copied from the dynamic module (see call    */
585    /* to DLSYM_copy_globals() below).                                        */
586    /*                                                                        */
587    /* THESE INITIALIZATIONS SHOULD BE MOVED TO AN INIT ROUTINE FOR THE       */
588    /* LOADED MODULE                                                          */
589    /*------------------------------------------------------------------------*/
590    loaded_module->gsymtab = NULL;
591    loaded_module->gstrtab = NULL;
592    loaded_module->gsymnum = loaded_module->gstrsz = 0;
594    /*------------------------------------------------------------------------*/
595    /* Initialize the Array_List of dependencies.                             */
596    /*------------------------------------------------------------------------*/
597    AL_initialize(&(loaded_module->dependencies), sizeof(int), 1);
599    if (dyn_module->symtab)
600       DLSYM_copy_globals(dyn_module);
602    /*------------------------------------------------------------------------*/
603    /* Initialize the module loaded segments Array_List.                      */
604    /*------------------------------------------------------------------------*/
605    AL_initialize(&(loaded_module->loaded_segments),
606                  sizeof(DLIMP_Loaded_Segment), dyn_module->phnum);
608    /*------------------------------------------------------------------------*/
609    /* Spin thru segment headers and process each load segment encountered.   */
610    /*------------------------------------------------------------------------*/
611    for (i = 0; i < dyn_module->phnum; i++)
612       if (dyn_module->phdr[i].p_type == PT_LOAD)
613       {
614          /*------------------------------------------------------------------*/
615          /* Note that this is parallel to and does not supplant the ELF      */
616          /* phdr tables.                                                     */
617          /*------------------------------------------------------------------*/
618          DLIMP_Loaded_Segment seg;
619          seg.obj_desc = DLIF_malloc(sizeof(struct DLOAD_MEMORY_SEGMENT));
620          seg.phdr.p_vaddr = dyn_module->phdr[i].p_vaddr;
621          seg.phdr.p_offset = dyn_module->phdr[i].p_offset;
622          seg.modified = 0;
623          if(seg.obj_desc) {
624             seg.obj_desc->target_page = 0; /*not used*/
625             seg.phdr.p_filesz = seg.obj_desc->objsz_in_bytes
626                           = dyn_module->phdr[i].p_filesz;
627             seg.phdr.p_memsz = seg.obj_desc->memsz_in_bytes
628                          = dyn_module->phdr[i].p_memsz;
629          }
630          seg.phdr.p_align = dyn_module->phdr[i].p_align;
631          seg.phdr.p_flags = dyn_module->phdr[i].p_flags;
632          AL_append(&(loaded_module->loaded_segments), &seg);
633       }
635    /*------------------------------------------------------------------------*/
636    /* Initialize the DSO termination information for this module.            */
637    /* It will be copied over from the enclosing dyn_module object when       */
638    /* placement is completed and dyn_module's local copy of the dynamic      */
639    /* table is updated.                                                      */
640    /*------------------------------------------------------------------------*/
641    loaded_module->fini_array = (Elf32_Addr)NULL;
642    loaded_module->fini_arraysz = 0;
643    loaded_module->fini = (Elf32_Addr) NULL;
645 #if LOADER_DEBUG && LOADER_PROFILE
646    if (debugging_on || profiling_on)
647    {
648       DLIF_trace("Finished initialize_loaded_module()\n");
649       if (profiling_on)
650       {
651          profile_stop_clock();
652          DLIF_trace("Took %lu cycles.\n",
653                 (unsigned long)profile_cycle_count());
654       }
655    }
656 #endif
660 /*****************************************************************************/
661 /* load_static_segment()                                                     */
662 /*                                                                           */
663 /*    The core dynamic loader requires that a statically linked executable   */
664 /*    be placed in target memory at the location that was determined during  */
665 /*    the static link that created the executable.  Failure to get the       */
666 /*    required target memory where the static executable is to be loaded     */
667 /*    will cause the dynamic loader to emit an error and abort the load.     */
668 /*                                                                           */
669 /*****************************************************************************/
670 static BOOL load_static_segment(DLOAD_HANDLE handle, LOADER_FILE_DESC *fd,
671                                 DLIMP_Dynamic_Module *dyn_module)
673    int i;
674    DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
675                               (dyn_module->loaded_module->loaded_segments.buf);
676     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
678 #if LOADER_DEBUG
679     if (debugging_on) {
680         DLIF_trace("dynmodule is 0x%x\n",(UInt32) dyn_module);
681         DLIF_trace("loaded_module is 0x%x\n",(UInt32)dyn_module->loaded_module);
682         DLIF_trace("loaded_segments is 0x%x\n",
683                    (UInt32)&dyn_module->loaded_module->loaded_segments);
684         DLIF_trace("seg is 0x%x\n",
685                    (UInt32)dyn_module->loaded_module->loaded_segments.buf);
686     }
687 #endif
688    /*------------------------------------------------------------------------*/
689    /* For each segment in the loaded module, build up a target memory        */
690    /* request for the segment, get rights to target memory where we want     */
691    /* to load the segment from the client, then get the client to write the  */
692    /* segment contents out to target memory to the appropriate address.      */
693    /*------------------------------------------------------------------------*/
694    for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
695    {
696       struct DLOAD_MEMORY_REQUEST targ_req;
697       seg[i].obj_desc->target_page = 0;
698       targ_req.flags = 0;
700       /*---------------------------------------------------------------------*/
701       /* This is a static executable.  DLIF_allocate should give us the      */
702       /* address we ask for or fail.                                         */
703       /*---------------------------------------------------------------------*/
704       if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
706       targ_req.align = seg[i].phdr.p_align;
707       seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
708       targ_req.flags &= ~DLOAD_SF_relocatable;
709       targ_req.fp = fd;
710       targ_req.segment = seg[i].obj_desc;
711       targ_req.offset = seg[i].phdr.p_offset;
712       targ_req.flip_endian = dyn_module->wrong_endian;
713 #if LOADER_DEBUG
714         if (debugging_on) {
715             DLIF_trace("============================================\n");
716             DLIF_trace("targ_req.align %d\n", targ_req.align);
717             DLIF_trace("targ_req.segment 0x%x\n", (UInt32) targ_req.segment);
718             DLIF_trace("targ_req.offset 0x%x\n", targ_req.offset);
719             DLIF_trace("targ_req.flags 0x%x\n", targ_req.flags);
720         }
721 #endif
722       /*---------------------------------------------------------------------*/
723       /* Ask the client side of the dynamic loader to allocate target memory */
724       /* for this segment to be loaded into.                                 */
725       /*---------------------------------------------------------------------*/
726       if (!DLIF_allocate(pHandle->client_handle, &targ_req)) return FALSE;
728       /*---------------------------------------------------------------------*/
729       /* If there is any initialized data in the segment, we'll first write  */
730       /* it into a host writable buffer (DLIF_copy()) and then flush it to   */
731       /* target memory.                                                      */
732       /*---------------------------------------------------------------------*/
733       if (seg[i].phdr.p_filesz)
734       {
735          DLIF_copy(pHandle->client_handle, &targ_req);
736          DLIF_write(pHandle->client_handle, &targ_req);
737       }
738    }
740    return TRUE;
743 /*****************************************************************************/
744 /* relocate_target_dynamic_tag_info()                                        */
745 /*                                                                           */
746 /*    Update a target specific dynamic tag value that happens to be a        */
747 /*    virtual address of a section. Returns TRUE if the tag was updated or   */
748 /*    is not a virtual address and FALSE if it was not successfully updated  */
749 /*    or was not recognized.                                                 */
750 /*****************************************************************************/
751 static BOOL relocate_target_dynamic_tag_info(DLIMP_Dynamic_Module *dyn_module,
752                                              int i)
754    return cur_target->relocate_dynamic_tag_info(dyn_module, i);
757 /*****************************************************************************/
758 /* DLIMP_update_dyntag_section_address()                                     */
759 /*                                                                           */
760 /*    Given the index of a dynamic tag which we happen to know points to a   */
761 /*    section address, find the program header table entry associated with   */
762 /*    the specified address and update the tag value with the real address   */
763 /*    of the section.                                                        */
764 /*                                                                           */
765 /*****************************************************************************/
766 BOOL DLIMP_update_dyntag_section_address(DLIMP_Dynamic_Module *dyn_module,
767                                          int32_t i)
769    int j;
770    DLIMP_Loaded_Segment *seg = (DLIMP_Loaded_Segment *)
771                               (dyn_module->loaded_module->loaded_segments.buf);
773    /*------------------------------------------------------------------------*/
774    /* If dynamic tag does not access an existing section, then no update     */
775    /* is required.                                                           */
776    /*------------------------------------------------------------------------*/
777    if (dyn_module->dyntab[i].d_un.d_ptr == (Elf32_Addr)0)
778       { return TRUE; }
780    for (j = 0; j < dyn_module->loaded_module->loaded_segments.size; j++)
781    {
782       if ((dyn_module->dyntab[i].d_un.d_ptr >= seg[j].input_vaddr) &&
783           (dyn_module->dyntab[i].d_un.d_ptr <
784        (seg[j].input_vaddr + seg[j].phdr.p_memsz)))
785       {
786          dyn_module->dyntab[i].d_un.d_ptr +=
787                                     (seg[j].phdr.p_vaddr - seg[j].input_vaddr);
788          return TRUE;
789       }
790    }
792    return FALSE;
795 /*****************************************************************************/
796 /* relocate_dynamic_tag_info()                                               */
797 /*                                                                           */
798 /*    Once segment allocation has been completed, we'll need to go through   */
799 /*    the dynamic table and update any tag values that happen to be virtual  */
800 /*    addresses of segments (DT_C6000_DSBT_BASE, for example).               */
801 /*                                                                           */
802 /*****************************************************************************/
803 static BOOL relocate_dynamic_tag_info(LOADER_FILE_DESC *fd,
804                                       DLIMP_Dynamic_Module *dyn_module)
806    /*------------------------------------------------------------------------*/
807    /* Spin through dynamic table loking for tags that have a value which is  */
808    /* the virtual address of a section. After the sections are allocated,    */
809    /* we'll need to update these values with the new address of the section. */
810    /*------------------------------------------------------------------------*/
811    int i;
812    for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
813    {
814       switch (dyn_module->dyntab[i].d_tag)
815       {
816          /*------------------------------------------------------------------*/
817      /* Only tag values that are virtual addresses will be affected.     */
818          /*------------------------------------------------------------------*/
819          case DT_NEEDED:
820          case DT_PLTRELSZ:
821          case DT_HASH:
822          case DT_STRTAB:
823          case DT_SYMTAB:
824          case DT_RELA:
825          case DT_RELASZ:
826          case DT_RELAENT:
827          case DT_STRSZ:
828          case DT_SYMENT:
829          case DT_SONAME:
830          case DT_RPATH:
831          case DT_SYMBOLIC:
832          case DT_REL:
833          case DT_RELSZ:
834          case DT_RELENT:
835          case DT_PLTREL:
836          case DT_DEBUG:
837          case DT_TEXTREL:
838          case DT_BIND_NOW:
839          case DT_INIT_ARRAYSZ:
840          case DT_RUNPATH:
841          case DT_FLAGS:
842          case DT_PREINIT_ARRAYSZ:
843             continue;
845          /*------------------------------------------------------------------*/
846      /* NOTE!!!                                                          */
847          /* case DT_ENCODING:  -- tag type has same "id" as DT_PREINIT_ARRAY */
848          /*------------------------------------------------------------------*/
850          /*------------------------------------------------------------------*/
851          /* This is a generic dynamic tag whose value is a virtual address   */
852          /* of a section. It needs to be relocated to the section's actual   */
853          /* address in target memory.                                        */
854          /*------------------------------------------------------------------*/
855          case DT_PREINIT_ARRAY:
856          case DT_INIT:
857          case DT_INIT_ARRAY:
858         if (!DLIMP_update_dyntag_section_address(dyn_module, i))
859            return FALSE;
861             continue;
863          /*------------------------------------------------------------------*/
864      /* Once we have resolved the actual address of termination function */
865      /* sections, we need to copy their addresses over to the loaded     */
866      /* module object (dyn_module will be deleted before we get to       */
867      /* unloading the module).                                           */
868          /*------------------------------------------------------------------*/
869          case DT_FINI_ARRAY:
870          case DT_FINI:
871         if (!DLIMP_update_dyntag_section_address(dyn_module, i))
872            return FALSE;
874         if (dyn_module->dyntab[i].d_tag == DT_FINI)
875            dyn_module->loaded_module->fini =
876                                           dyn_module->dyntab[i].d_un.d_ptr;
877         else
878            dyn_module->loaded_module->fini_array =
879                                           dyn_module->dyntab[i].d_un.d_ptr;
881             continue;
883          case DT_FINI_ARRAYSZ:
884         dyn_module->loaded_module->fini_arraysz =
885                                           dyn_module->dyntab[i].d_un.d_val;
886         continue;
888          /*------------------------------------------------------------------*/
889      /* Is this a virtual address???                                     */
890          /*------------------------------------------------------------------*/
891          case DT_JMPREL: /* is this a virtual address??? */
892             continue;
894          /*------------------------------------------------------------------*/
895          /* The remaining dynamic tag types should be target specific. If    */
896          /* something generic slips through to here, then the handler for    */
897          /* relocating target specific dynamic tags should fail.             */
898          /*------------------------------------------------------------------*/
899          default:
900             if (!relocate_target_dynamic_tag_info(dyn_module, i))
901                return FALSE;
902       }
903    }
905    /*------------------------------------------------------------------------*/
906    /* We've gotten through all of the dynamic table without incident.        */
907    /* All dynamic tag values that were virtual section addresses should have */
908    /* been updated with the final address of the section that they point to. */
909    /*------------------------------------------------------------------------*/
910    return TRUE;
913 /*****************************************************************************/
914 /* allocate_dynamic_segments_and relocate_symbols()                          */
915 /*                                                                           */
916 /*    Allocate target memory for each segment in this module, getting a      */
917 /*    host-accessible space to copy the content of each segment into.  Then  */
918 /*    update the symbol table and program header table to reflect the new    */
919 /*    target address for each segment.  Processing of the dynamic relocation */
920 /*    entries will wait until all dependent files have been loaded and       */
921 /*    allocated into target memory.                                          */
922 /*                                                                           */
923 /*---------------------------------------------------------------------------*/
924 /*                                                                           */
925 /* The relocation entries in the ELF file do not handle the necessary        */
926 /* adjustments to the memory addresses in the program header or symbol       */
927 /* tables.  These must be done manually.                                     */
928 /*                                                                           */
929 /* This is harder for us than for most dynamic loaders, because we have to   */
930 /* work in environments without virtual memory and thus where the offsets    */
931 /* between segments in memory may be different than they were in the file.   */
932 /* So, even though a dynamic loader usually only has to adjust all the       */
933 /* segments by a single fixed offset, we need to offset the symbols and      */
934 /* program header addresses segment by segment.  This job is done by the     */
935 /* function below.                                                           */
936 /*                                                                           */
937 /*****************************************************************************/
938 static BOOL allocate_dynamic_segments_and_relocate_symbols
939                                              (DLOAD_HANDLE handle,
940                                               LOADER_FILE_DESC *fd,
941                                               DLIMP_Dynamic_Module *dyn_module)
943    int i,j;
944    DLIMP_Loaded_Segment* seg = (DLIMP_Loaded_Segment*)
945                              (dyn_module->loaded_module->loaded_segments.buf);
946    struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
947     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
949 #if LOADER_DEBUG && LOADER_PROFILE
950    if (debugging_on || profiling_on)
951    {
952       DLIF_trace("Dynamic executable found.\n"
953                  "Starting allocate_dynamic_segments_and_relocate_symbols()"
954                  "...\n");
955       if (profiling_on) profile_start_clock();
956    }
957 #endif
959    /*------------------------------------------------------------------------*/
960    /* Spin through the list of loaded segments from the current module.      */
961    /*------------------------------------------------------------------------*/
962    for (i = 0; i < dyn_module->loaded_module->loaded_segments.size; i++)
963    {
964       /*--------------------------------------------------------------------*/
965       /* Allocate target memory for segment via client-provided target      */
966       /* memory API.                                                        */
967       /*--------------------------------------------------------------------*/
968       int32_t addr_offset;
969       struct DLOAD_MEMORY_REQUEST targ_req;
970       seg[i].obj_desc->target_page = 0;
971       targ_req.flags = 0;
972       if (seg[i].phdr.p_flags & PF_X) targ_req.flags |= DLOAD_SF_executable;
973       targ_req.align = 0x20;
974       seg[i].obj_desc->target_address = (TARGET_ADDRESS)seg[i].phdr.p_vaddr;
975       targ_req.flags |= DLOAD_SF_relocatable;
976       targ_req.fp = fd;
977       targ_req.segment = seg[i].obj_desc;
978       targ_req.offset = seg[i].phdr.p_offset;
979       targ_req.flip_endian = dyn_module->wrong_endian;
981       if (!DLIF_allocate(pHandle->client_handle, &targ_req))
982       {
983          DLIF_error(DLET_MEMORY, "DLIF allocation failure.\n");
984          return FALSE;
985       }
987       /*--------------------------------------------------------------------*/
988       /* Calculate the offset we need to adjust segment header and symbol   */
989       /* table addresses.                                                   */
990       /*--------------------------------------------------------------------*/
991       addr_offset = (int32_t)(seg[i].obj_desc->target_address) -
992                                                (int32_t)(seg[i].phdr.p_vaddr);
994 #if LOADER_DEBUG
995       if (debugging_on)
996       {
997          DLIF_trace("Segment %d (at 0x%x, 0x%x bytes) relocated to 0x%x\n", i,
998                 (int32_t)(seg[i].phdr.p_vaddr),
999                 (int32_t)(seg[i].phdr.p_memsz),
1000                 (int32_t)(seg[i].obj_desc->target_address));
1001          DLIF_trace( "Addr Offset is 0x%x\n", addr_offset);
1002       }
1003 #endif
1005       /*--------------------------------------------------------------------*/
1006       /* Update program entry point if needed.  Need to replace to deal     */
1007       /* with full ELF initialization routine.                              */
1008       /*--------------------------------------------------------------------*/
1009       if (dyn_module->relocate_entry_point &&
1010           fhdr->e_entry >= (Elf32_Addr)(seg[i].phdr.p_vaddr) &&
1011           fhdr->e_entry <
1012             (Elf32_Addr)((uint8_t*)(seg[i].phdr.p_vaddr) +
1013                                              (uint32_t)(seg[i].phdr.p_memsz)))
1014       {
1015 #if LOADER_DEBUG
1016          if (debugging_on)
1017          {
1018             DLIF_trace("Entry point 0x%x relocated to 0x%x\n",
1019                    fhdr->e_entry, fhdr->e_entry + addr_offset);
1020          }
1021 #endif
1022          fhdr->e_entry += addr_offset;
1024          /*------------------------------------------------------------------*/
1025          /* Mark the entry point as being relocated so we will not do it     */
1026          /* again.                                                           */
1027          /*------------------------------------------------------------------*/
1028          dyn_module->relocate_entry_point = FALSE;
1029       }
1031       /*---------------------------------------------------------------------*/
1032       /* Fix program header entries in segment and Elf32_Phdr structs.       */
1033       /*---------------------------------------------------------------------*/
1034       for (j = 0; j < fhdr->e_phnum; j++)
1035          if (dyn_module->phdr[j].p_vaddr == (Elf32_Addr)seg[i].phdr.p_vaddr)
1036          {
1037             dyn_module->phdr[j].p_vaddr += addr_offset;
1038             dyn_module->phdr[i].p_paddr += addr_offset;
1039             break;
1040          }
1042       seg[i].input_vaddr = (Elf32_Addr)(seg[i].phdr.p_vaddr);
1043       seg[i].phdr.p_vaddr += addr_offset;
1045       /*---------------------------------------------------------------------*/
1046       /* Great, now the hard part: fix offsets in symbols.  It would be nice */
1047       /* if there were an easier way to deal with this.                      */
1048       /*---------------------------------------------------------------------*/
1049       {
1050          struct Elf32_Sym *gsymtab =
1051                     ((struct Elf32_Sym*)(dyn_module->loaded_module->gsymtab));
1052          Elf32_Addr segment_start = (Elf32_Addr)seg[i].phdr.p_vaddr;
1053          Elf32_Addr segment_end   = (Elf32_Addr)seg[i].phdr.p_vaddr +
1054                                                            seg[i].phdr.p_memsz;
1055          Elf32_Word global_index  = dyn_module->symnum -
1056                                     dyn_module->loaded_module->gsymnum;
1058          for (j = 0; j < dyn_module->symnum; j++)
1059          {
1060             /*---------------------------------------------------------------*/
1061             /* Get the relocated symbol value.                               */
1062             /*---------------------------------------------------------------*/
1063             Elf32_Addr symval_adj = dyn_module->symtab[j].st_value +
1064                                     addr_offset;
1066             /*---------------------------------------------------------------*/
1067             /* If the symbol is defined in this segment, update the symbol   */
1068             /* value and mark the symbol so that we don't relocate it again. */
1069             /*---------------------------------------------------------------*/
1070             if (symval_adj >= segment_start && symval_adj <  segment_end &&
1071                 dyn_module->symtab[j].st_shndx != INT16_MAX)
1072             {
1073                dyn_module->symtab[j].st_value = symval_adj;
1075                /*------------------------------------------------------------*/
1076                /* The module symbol table only has the global symbols.       */
1077                /*------------------------------------------------------------*/
1078                if (j >= global_index)
1079                   gsymtab[j-global_index].st_value = symval_adj;
1081                /*------------------------------------------------------------*/
1082                /* Mark the symbol as relocated.                              */
1083                /*------------------------------------------------------------*/
1084                dyn_module->symtab[j].st_shndx = INT16_MAX;
1085             }
1086          }
1087       }
1088    }
1090    /*------------------------------------------------------------------------*/
1091    /* Update dynamic tag information. Some dynamic tags have values which    */
1092    /* are virtual addresses of sections. These values need to be updated     */
1093    /* once segment allocation is completed and the new segment addresses are */
1094    /* known.                                                                 */
1095    /*------------------------------------------------------------------------*/
1096    /* We should only traverse through the dynamic table once because we want */
1097    /* to avoid the possibility of updating the same tag multiple times (an   */
1098    /* error, if it happens).                                                 */
1099    /*------------------------------------------------------------------------*/
1100    if (!relocate_dynamic_tag_info(fd, dyn_module))
1101    {
1102       DLIF_error(DLET_MISC, "Failed dynamic table update.\n");
1103       return FALSE;
1104    }
1106 #if LOADER_DEBUG && LOADER_PROFILE
1107    if (debugging_on || profiling_on)
1108    {
1109       DLIF_trace("Finished allocate_dynamic_segments_and_relocate_symbols()\n");
1110       if (profiling_on)
1111       {
1112          profile_stop_clock();
1113          DLIF_trace("Took %lu cycles.\n", (unsigned long) profile_cycle_count());
1114       }
1115    }
1116 #endif
1118    return TRUE;
1121 /*****************************************************************************/
1122 /* delete_DLIMP_Loaded_Module()                                              */
1123 /*                                                                           */
1124 /*    Free host memory associated with a DLIMP_Loaded_Module data structure  */
1125 /*    and all of the DLIMP_Loaded_Segment objects that are associated with   */
1126 /*    it.                                                                    */
1127 /*                                                                           */
1128 /*****************************************************************************/
1129 static void delete_DLIMP_Loaded_Module(DLOAD_HANDLE handle,
1130                                        DLIMP_Loaded_Module **pplm)
1132     DLIMP_Loaded_Module *loaded_module = *pplm;
1133     DLIMP_Loaded_Segment *segments = (DLIMP_Loaded_Segment*)
1134                                           (loaded_module->loaded_segments.buf);
1135     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
1137     /*-----------------------------------------------------------------------*/
1138     /* Spin through the segments attached to this loaded module, freeing up  */
1139     /* any target memory that was allocated by the client for the segment.   */
1140     /*-----------------------------------------------------------------------*/
1141     int i;
1142     for (i = 0; i < loaded_module->loaded_segments.size; i++)
1143     {
1144         if (!DLIF_release(pHandle->client_handle, segments[i].obj_desc))
1145             DLIF_error(DLET_MISC, "Failed call to DLIF_release!\n");;
1146         DLIF_free(segments[i].obj_desc);
1147     }
1149     /*----------------------------------------------------------------------*/
1150     /* Hacky way of indicating that the base image is no longer available.  */
1151     /* WHHHHAAAAAAATTT!?!?!?!?!?!                                           */
1152     /*----------------------------------------------------------------------*/
1153     if (loaded_module->file_handle == DLIMP_application_handle)
1154         DLIMP_application_handle = 0;
1156     /*-----------------------------------------------------------------------*/
1157     /* Free host heap memory that was allocated for the internal loaded      */
1158     /* module data structure members.                                        */
1159     /*-----------------------------------------------------------------------*/
1160     if (loaded_module->name)    DLIF_free(loaded_module->name);
1161     if (loaded_module->gsymtab) DLIF_free(loaded_module->gsymtab);
1162     loaded_module->gsymnum = 0;
1163     if (loaded_module->gstrtab) DLIF_free(loaded_module->gstrtab);
1164     loaded_module->gstrsz = 0;
1165     AL_destroy(&(loaded_module->loaded_segments));
1166     AL_destroy(&(loaded_module->dependencies));
1168     /*-----------------------------------------------------------------------*/
1169     /* Finally, free the host memory for the loaded module object, then NULL */
1170     /* the pointer that was passed in.                                       */
1171     /*-----------------------------------------------------------------------*/
1172     DLIF_free(loaded_module);
1173     *pplm = NULL;
1176 /*****************************************************************************/
1177 /* new_DLIMP_Dynamic_Module()                                                */
1178 /*                                                                           */
1179 /*   Allocate a dynamic module data structure from host memory and           */
1180 /*   initialize its members to their default values.                         */
1181 /*                                                                           */
1182 /*****************************************************************************/
1183 static DLIMP_Dynamic_Module *new_DLIMP_Dynamic_Module(LOADER_FILE_DESC *fd)
1185     /*-----------------------------------------------------------------------*/
1186     /* Allocate space for dynamic module data structure from host memory.    */
1187     /*-----------------------------------------------------------------------*/
1188     DLIMP_Dynamic_Module *dyn_module =
1189              (DLIMP_Dynamic_Module *)DLIF_malloc(sizeof(DLIMP_Dynamic_Module));
1191     if (!dyn_module)
1192         return NULL;
1194     /*-----------------------------------------------------------------------*/
1195     /* Initialize data members of the new dynamic module data structure.     */
1196     /*-----------------------------------------------------------------------*/
1197     dyn_module->name = NULL;
1198     dyn_module->fd = fd;
1199     dyn_module->phdr = NULL;
1200     dyn_module->phnum = 0;
1201     dyn_module->strtab = NULL;
1202     dyn_module->strsz = 0;
1203     dyn_module->dyntab = NULL;
1204     dyn_module->symtab = NULL;
1205     dyn_module->symnum = 0;
1206     dyn_module->gsymtab_offset = 0;
1207     dyn_module->gstrtab_offset = 0;
1208     dyn_module->c_args = NULL;
1209     dyn_module->argc = 0;
1210     dyn_module->argv = NULL;
1211     dyn_module->loaded_module = NULL;
1212     dyn_module->wrong_endian = 0;
1213     dyn_module->direct_dependent_only = TRUE;
1214     dyn_module->relocatable = FALSE;
1215     dyn_module->relocate_entry_point = TRUE;
1217     dyn_module->dsbt_size = 0;
1218     dyn_module->dsbt_index = DSBT_INDEX_INVALID;
1219     dyn_module->dsbt_base_tagidx = -1;
1221     dyn_module->preinit_array_idx = -1;
1222     dyn_module->preinit_arraysz = 0;
1223     dyn_module->init_idx = -1;
1224     dyn_module->init_array_idx = -1;
1225     dyn_module->init_arraysz = 0;
1227     return dyn_module;
1230 /*****************************************************************************/
1231 /* detach_loaded_module()                                                    */
1232 /*                                                                           */
1233 /*    Detach loaded module data structure from given dynamic module.  When   */
1234 /*    an object file has been successfully loaded, the loader core will      */
1235 /*    detach the loaded module data structure from the dynamic module data   */
1236 /*    structure because the loaded module must continue to persist until is  */
1237 /*    is actually unloaded from target memory.  If there is a problem with   */
1238 /*    the load, then the host memory associated with the loaded module will  */
1239 /*    be released as part of the destruction of the dynamic module.          */
1240 /*                                                                           */
1241 /*****************************************************************************/
1242 static
1243 DLIMP_Loaded_Module *detach_loaded_module(DLIMP_Dynamic_Module *dyn_module)
1245     if (dyn_module && dyn_module->loaded_module)
1246     {
1247         DLIMP_Loaded_Module *loaded_module = dyn_module->loaded_module;
1248         dyn_module->loaded_module = NULL;
1249         return loaded_module;
1250     }
1252     return NULL;
1254 /*****************************************************************************/
1255 /* delete_DLIMP_Dynamic_Module()                                             */
1256 /*                                                                           */
1257 /*    Remove local copies of the string table, symbol table, program header  */
1258 /*    table, and dynamic table.                                              */
1259 /*                                                                           */
1260 /*****************************************************************************/
1261 static void delete_DLIMP_Dynamic_Module(DLOAD_HANDLE handle,
1262                                         DLIMP_Dynamic_Module **ppdm)
1264    DLIMP_Dynamic_Module *dyn_module = NULL;
1266    if (!ppdm || (*ppdm == NULL))
1267    {
1268       DLIF_error(DLET_MISC,
1269                  "Internal Error: invalid argument to dynamic module "
1270          "destructor function; aborting loader\n");
1271       DLIF_exit(1);
1272    }
1274    dyn_module = *ppdm;
1275    if (dyn_module->name)     DLIF_free(dyn_module->name);
1276    if (dyn_module->strtab)   DLIF_free(dyn_module->strtab);
1277    if (dyn_module->symtab)   DLIF_free(dyn_module->symtab);
1278    if (dyn_module->phdr)     DLIF_free(dyn_module->phdr);
1279    if (dyn_module->dyntab)   DLIF_free(dyn_module->dyntab);
1281    /*------------------------------------------------------------------------*/
1282    /* If we left the loaded module attached to the dynamic module, then      */
1283    /* something must have gone wrong with the load.  Remove the loaded       */
1284    /* module from the queue of loaded modules, if it is there.  Then free    */
1285    /* the host memory allocated to the loaded module and its segments.       */
1286    /*------------------------------------------------------------------------*/
1287    if (dyn_module->loaded_module != NULL)
1288         delete_DLIMP_Loaded_Module(handle, &(dyn_module->loaded_module));
1290    /*------------------------------------------------------------------------*/
1291    /* Finally, free the host memory for this dynamic module object and NULL  */
1292    /* the pointer to the object.                                             */
1293    /*------------------------------------------------------------------------*/
1294    DLIF_free(dyn_module);
1295    *ppdm = NULL;
1298 /*****************************************************************************/
1299 /* file_header_magic_number_is_valid()                                       */
1300 /*                                                                           */
1301 /*    Given an object file header, check the magic number to ensure that it  */
1302 /*    is an object file format that we recognize.  This implementation of    */
1303 /*    the dynamic loader core will handle ELF object file format.            */
1304 /*                                                                           */
1305 /*****************************************************************************/
1306 static BOOL file_header_magic_number_is_valid(struct Elf32_Ehdr* header)
1308    /*------------------------------------------------------------------------*/
1309    /* Check for correct ELF magic numbers in file header.                    */
1310    /*------------------------------------------------------------------------*/
1311    if (!(header->e_ident[EI_MAG0] == ELFMAG0) ||
1312        !(header->e_ident[EI_MAG1] == ELFMAG1) ||
1313        !(header->e_ident[EI_MAG2] == ELFMAG2) ||
1314        !(header->e_ident[EI_MAG3] == ELFMAG3))
1315    {
1316       DLIF_error(DLET_FILE, "Invalid ELF magic number.\n");
1317       return FALSE;
1318    }
1320    return TRUE;
1323 /*****************************************************************************/
1324 /* file_header_machine_is_valid()                                            */
1325 /*                                                                           */
1326 /*    Check if the machine specified in the file header is supported by the  */
1327 /*    loader.  If the loader was compiled with support for all targets,      */
1328 /*    the machine will be initially set to EM_NONE.  Once a module has been  */
1329 /*    loaded, all remaining modules must have the same machine value.        */
1330 /*****************************************************************************/
1331 static int file_header_machine_is_valid(Elf32_Half e_machine)
1333    /*------------------------------------------------------------------------*/
1334    /* Currently we support only ARM or C6x                                   */
1335    /*------------------------------------------------------------------------*/
1336    switch(e_machine)
1337    {
1338 #ifdef ARM_TARGET
1339       case EM_ARM :      return TRUE;
1340 #endif
1341 #ifdef C60_TARGET
1342       case EM_TI_C6000 : return TRUE;
1343 #endif
1345       default :          return FALSE;
1346    }
1349 /*****************************************************************************/
1350 /* is_valid_elf_object_file()                                                */
1351 /*                                                                           */
1352 /*    Check file size against anticipated end location of string table,      */
1353 /*    symbol table, program header tables, etc.  If we anything untoward,    */
1354 /*    then we declare that the ELF file is corrupt and the load is aborted.  */
1355 /*                                                                           */
1356 /*****************************************************************************/
1357 static BOOL is_valid_elf_object_file(LOADER_FILE_DESC *fd,
1358                                      DLIMP_Dynamic_Module *dyn_module)
1360    uint32_t fsz;
1361    int i;
1363    /*------------------------------------------------------------------------*/
1364    /* Get file size.                                                         */
1365    /*------------------------------------------------------------------------*/
1366    DLIF_fseek(fd, 0, LOADER_SEEK_END);
1367    fsz = DLIF_ftell(fd);
1369    /*------------------------------------------------------------------------*/
1370    /* Check for invalid table sizes (string table, symbol table, and         */
1371    /* program header tables).                                                */
1372    /*------------------------------------------------------------------------*/
1373    if (!((dyn_module->strsz < fsz) &&
1374          (dyn_module->symnum < fsz) &&
1375          (dyn_module->phnum * sizeof(struct Elf32_Phdr)) < fsz))
1376    {
1377       DLIF_error(DLET_FILE, "Invalid ELF table bounds.\n");
1378       return FALSE;
1379    }
1381    /*------------------------------------------------------------------------*/
1382    /* Check for null so_name string in file with dynamic information.        */
1383    /*------------------------------------------------------------------------*/
1384    if (dyn_module->dyntab && !strcmp(dyn_module->name, ""))
1385    {
1386       DLIF_error(DLET_MISC, "Dynamic file lacks SO_NAME identifier.\n");
1387       return FALSE;
1388    }
1390    /*------------------------------------------------------------------------*/
1391    /* Check for invalid program header information.                          */
1392    /*------------------------------------------------------------------------*/
1393    for (i = 0; i < dyn_module->phnum; i++)
1394    {
1395       struct Elf32_Phdr* phdr = dyn_module->phdr + i;
1397       /*---------------------------------------------------------------------*/
1398       /* Sanity check for relative sizes of filesz and memsz.                */
1399       /*---------------------------------------------------------------------*/
1400       if (!(phdr->p_type != PT_LOAD || phdr->p_filesz <= phdr->p_memsz))
1401       {
1402          DLIF_error(DLET_MISC,
1403                     "Invalid file or memory size for segment %d.\n", i);
1404          return FALSE;
1405       }
1407       /*---------------------------------------------------------------------*/
1408       /* Check that segment file offset doesn't go off the end of the file.  */
1409       /*---------------------------------------------------------------------*/
1410       if (!(phdr->p_offset + phdr->p_filesz < fsz))
1411       {
1412          DLIF_error(DLET_FILE,
1413                   "File location of segment %d is past the end of file.\n", i);
1414          return FALSE;
1415       }
1416    }
1418    /*------------------------------------------------------------------------*/
1419    /* Check that a ET_DYN-type file is relocatable.                          */
1420    /*------------------------------------------------------------------------*/
1421    if (dyn_module->fhdr.e_type == ET_DYN && !dyn_module->symtab) return FALSE;
1423    /*------------------------------------------------------------------------*/
1424    /* All checks passed.                                                     */
1425    /*------------------------------------------------------------------------*/
1426    return TRUE;
1429 /*****************************************************************************/
1430 /* process_eiosabi()                                                         */
1431 /*                                                                           */
1432 /*   Check the EI_OSABI field to validate it and set any parameters based on */
1433 /*   it.                                                                     */
1434 /*****************************************************************************/
1435 static BOOL process_eiosabi(DLIMP_Dynamic_Module* dyn_module)
1437    return cur_target->process_eiosabi(dyn_module);
1439 /*****************************************************************************/
1440 /* dload_file_header()                                                       */
1441 /*                                                                           */
1442 /*    Read ELF file header.  Store critical information in the provided      */
1443 /*    DLIMP_Dynamic_Module record.  Check file header for validity.          */
1444 /*                                                                           */
1445 /*****************************************************************************/
1446 static BOOL dload_file_header(LOADER_FILE_DESC *fd,
1447                               DLIMP_Dynamic_Module *dyn_module)
1449    /*------------------------------------------------------------------------*/
1450    /* Read ELF file header from given input file.                            */
1451    /*------------------------------------------------------------------------*/
1452    DLIF_fread(&(dyn_module->fhdr), sizeof(struct Elf32_Ehdr), 1, fd);
1454    /*------------------------------------------------------------------------*/
1455    /* Determine target vs. host endian-ness.  Does header data need to be    */
1456    /* byte swapped?                                                          */
1457    /*------------------------------------------------------------------------*/
1458    dyn_module->wrong_endian =
1459                      (dyn_module->fhdr.e_ident[EI_DATA] != DLIMP_get_endian());
1461    /*------------------------------------------------------------------------*/
1462    /* Swap file header structures, if needed.                                */
1463    /*------------------------------------------------------------------------*/
1464    if (dyn_module->wrong_endian)
1465       DLIMP_change_ehdr_endian(&(dyn_module->fhdr));
1467 #if LOADER_DEBUG
1468    if (debugging_on)
1469    {
1470        DLIF_trace("ELF: %c%c%c\n", dyn_module->fhdr.e_ident[1],
1471                                dyn_module->fhdr.e_ident[2],
1472                                dyn_module->fhdr.e_ident[3]);
1473        DLIF_trace("ELF file header entry point: %x\n",
1474                                dyn_module->fhdr.e_entry);
1475    }
1476 #endif
1478    /*------------------------------------------------------------------------*/
1479    /* Verify magic numbers in ELF file header.                               */
1480    /*------------------------------------------------------------------------*/
1481    if (!file_header_magic_number_is_valid(&(dyn_module->fhdr)))
1482    {
1483       DLIF_error(DLET_FILE, "Invalid ELF file header magic number.\n");
1484       return FALSE;
1485    }
1487    if (!file_header_machine_is_valid(dyn_module->fhdr.e_machine))
1488    {
1489        DLIF_error(DLET_FILE, "Invalid ELF file target machine.\n");
1490        return FALSE;
1491    }
1493    /*------------------------------------------------------------------------*/
1494    /* Verify file is an executable or dynamic shared object or library.      */
1495    /*------------------------------------------------------------------------*/
1496    if ((dyn_module->fhdr.e_type != ET_EXEC) &&
1497        (dyn_module->fhdr.e_type != ET_DYN))
1498    {
1499       DLIF_error(DLET_FILE, "Invalid ELF file type.\n");
1500       return FALSE;
1501    }
1503 #if LOADER_DEBUG && LOADER_PROFILE
1504    /*------------------------------------------------------------------------*/
1505    /* Stop profiling clock when file header information has finished         */
1506    /* loading.  Re-start clock on initialization of symbol table, and        */
1507    /* dynamic table pointers.                                                */
1508    /*------------------------------------------------------------------------*/
1509    if (debugging_on || profiling_on)
1510    {
1511       DLIF_trace("done.\n");
1512       if (profiling_on)
1513       {
1514          profile_stop_clock();
1515          DLIF_trace("Took %lu cycles.\n",
1516                 (unsigned long)profile_cycle_count());
1517          profile_start_clock();
1518       }
1519    }
1520 #endif
1522    return TRUE;
1525 /*****************************************************************************/
1526 /* dload_program_header_table()                                              */
1527 /*                                                                           */
1528 /*    Make a local copy of the ELF object file's program header table in the */
1529 /*    dynamic module data structure.                                         */
1530 /*                                                                           */
1531 /*****************************************************************************/
1532 static void dload_program_header_table(LOADER_FILE_DESC *fd,
1533                                        DLIMP_Dynamic_Module *dyn_module)
1535    /*------------------------------------------------------------------------*/
1536    /* Read the program header tables from the object file.                   */
1537    /*------------------------------------------------------------------------*/
1538    struct Elf32_Ehdr *fhdr = &(dyn_module->fhdr);
1539    dyn_module->phdr = (struct Elf32_Phdr*)
1540                               (DLIF_malloc(fhdr->e_phnum * fhdr->e_phentsize));
1541    DLIF_fseek(fd, fhdr->e_phoff, LOADER_SEEK_SET);
1542    if(dyn_module->phdr) {
1543       DLIF_fread(dyn_module->phdr, fhdr->e_phentsize, fhdr->e_phnum,fd);
1544       dyn_module->phnum = fhdr->e_phnum;
1546       /*---------------------------------------------------------------------*/
1547       /* Byte swap the program header tables if the target endian-ness is not*/
1548       /* the same as the host endian-ness.                                   */
1549       /*---------------------------------------------------------------------*/
1550       if (dyn_module->wrong_endian)
1551       {
1552          int i;
1553          for (i = 0; i < dyn_module->phnum; i++)
1554             DLIMP_change_phdr_endian(dyn_module->phdr + i);
1555       }
1556    }
1561 /*****************************************************************************/
1562 /* dload_headers()                                                           */
1563 /*                                                                           */
1564 /*    Read ELF object file header and program header table information into  */
1565 /*    the given dynamic module data structure.  If the object file contains  */
1566 /*    dynamic information, read in the dynamic tags, dynamic symbol table,   */
1567 /*    and global string table.  Check to make sure that we are not already   */
1568 /*    in the process of loading the module (circular dependencies), then     */
1569 /*    perform some level of sanity checking on the content of the file to    */
1570 /*    provide some assurance that the file is not corrupted.                 */
1571 /*                                                                           */
1572 /*****************************************************************************/
1573 static BOOL dload_headers(LOADER_FILE_DESC *fd,
1574                           DLIMP_Dynamic_Module *dyn_module)
1576 #if LOADER_DEBUG && LOADER_PROFILE
1577    /*------------------------------------------------------------------------*/
1578    /* More progress information.  Start timing if profiling is enabled.      */
1579    /*------------------------------------------------------------------------*/
1580    if (debugging_on || profiling_on)
1581    {
1582       DLIF_trace("\nReading file headers ...\n");
1583       if (profiling_on) profile_start_clock();
1584    }
1585 #endif
1587    /*------------------------------------------------------------------------*/
1588    /* Read file header information and check vs. expected ELF object file    */
1589    /* header content.                                                        */
1590    /*------------------------------------------------------------------------*/
1591    if (!dload_file_header(fd, dyn_module))
1592       return FALSE;
1594    /*------------------------------------------------------------------------*/
1595    /* Read program header table information into the dynamic module object.  */
1596    /*------------------------------------------------------------------------*/
1597    dload_program_header_table(fd, dyn_module);
1599    /*------------------------------------------------------------------------*/
1600    /* Once headers have been read in, use e_machine to set virtual target.   */
1601    /* This can then be used to access target specific functions.             */
1602    /*------------------------------------------------------------------------*/
1603    cur_target = get_vt_obj(dyn_module->fhdr.e_machine);
1604    if (!cur_target)
1605    {
1606       DLIF_error(DLET_FILE, "Attempt to load invalid ELF file, '%s'.\n",
1607                     dyn_module->name);
1608       return FALSE;
1609    }
1611    return TRUE;
1614 /*****************************************************************************/
1615 /* find_dynamic_segment()                                                    */
1616 /*                                                                           */
1617 /*    Find the dynamic segment in the given ELF object file, if there is     */
1618 /*    one.  If the segment is found, then the segment ID output parameter    */
1619 /*    is set to the index of the dynamic segment in the program header       */
1620 /*    table.  If the dynamic segment is not found, the dynamic module's      */
1621 /*    relocatable flag is set to FALSE, and return FALSE.                    */
1622 /*                                                                           */
1623 /*****************************************************************************/
1624 static BOOL find_dynamic_segment(DLIMP_Dynamic_Module *dyn_module,
1625                                  Elf32_Word *dyn_seg_idx)
1627    int i;
1629    /*------------------------------------------------------------------------*/
1630    /* We should have a valid dynamic module pointer and somewhere to put the */
1631    /* dynamic segment id, if we find one.  If either of these are missing,   */
1632    /* we should get an internal error and abort the loader.                  */
1633    /*------------------------------------------------------------------------*/
1634    if ((dyn_module == NULL) || (dyn_seg_idx == NULL))
1635    {
1636       DLIF_error(DLET_MISC, "Internal error: find_dynamic_segment() needs "
1637                             "non-NULL arguments.\n");
1638       DLIF_exit(1);
1639    }
1641    /*------------------------------------------------------------------------*/
1642    /* Spin through segment program headers to find the dynamic segment.      */
1643    /*------------------------------------------------------------------------*/
1644    dyn_module->relocatable = TRUE;
1645    for (i = 0; i < dyn_module->phnum; i++)
1646       if (dyn_module->phdr[i].p_type == PT_DYNAMIC)
1647          { *dyn_seg_idx = i; return TRUE; }
1649    /*------------------------------------------------------------------------*/
1650    /* No dynamic segment found, mark the object module as not relocatable    */
1651    /* and warn the user.                                                     */
1652    /*------------------------------------------------------------------------*/
1653    dyn_module->relocatable = FALSE;
1655    return FALSE;
1658 /*****************************************************************************/
1659 /* copy_dynamic_table()                                                      */
1660 /*                                                                           */
1661 /*    Make a local copy of the dynamic table read from the dynamic segment   */
1662 /*    in the ELF object file.                                                */
1663 /*                                                                           */
1664 /*****************************************************************************/
1665 static void copy_dynamic_table(LOADER_FILE_DESC *fd,
1666                                DLIMP_Dynamic_Module *dyn_module,
1667                                Elf32_Word dyn_seg_idx)
1670    /*------------------------------------------------------------------------*/
1671    /* Allocate space for the dynamic table from host memory and read its     */
1672    /* content from the ELF object file.                                      */
1673    /*------------------------------------------------------------------------*/
1674    Elf32_Word num_elem;
1675    dyn_module->dyntab = DLIF_malloc(dyn_module->phdr[dyn_seg_idx].p_filesz);
1676    num_elem = dyn_module->phdr[dyn_seg_idx].p_filesz / sizeof(struct Elf32_Dyn);
1677    DLIF_fseek(fd, dyn_module->phdr[dyn_seg_idx].p_offset, LOADER_SEEK_SET);
1678    if(dyn_module->dyntab) {
1679       DLIF_fread(dyn_module->dyntab, sizeof(struct Elf32_Dyn), num_elem, fd);
1681       /*---------------------------------------------------------------------*/
1682       /* If necessary, byte swap each entry in the dynamic table.            */
1683       /*---------------------------------------------------------------------*/
1684       if (dyn_module->wrong_endian)
1685       {
1686          int i;
1687          for (i = 0; i < num_elem; i++)
1688             DLIMP_change_dynent_endian(&dyn_module->dyntab[i]);
1689       }
1690    }
1693 /*****************************************************************************/
1694 /* process_target_dynamic_tag()                                              */
1695 /*                                                                           */
1696 /* Process a target specific dynamic tag entry.  Returns TRUE if the tag     */
1697 /* was handled and FALSE if it was not recognized.                           */
1698 /*****************************************************************************/
1699 static BOOL process_target_dynamic_tag(DLIMP_Dynamic_Module* dyn_module, int i)
1701    return cur_target->process_dynamic_tag(dyn_module, i);
1704 /*****************************************************************************/
1705 /* process_dynamic_table()                                                   */
1706 /*                                                                           */
1707 /*    Process dynamic tag entries from the dynamic table.  At the conclusion */
1708 /*    of this function, we should have made a copy of the global symbols     */
1709 /*    and the global symbol names.                                           */
1710 /*                                                                           */
1711 /*****************************************************************************/
1712 static BOOL process_dynamic_table(LOADER_FILE_DESC *fd,
1713                                   DLIMP_Dynamic_Module *dyn_module)
1715    int        i;
1716    BOOL       soname_found  = FALSE;
1717    Elf32_Addr soname_offset = 0;
1718    Elf32_Addr strtab_offset = 0;
1719    Elf32_Addr hash_offset   = 0;
1720    Elf32_Addr symtab_offset = 0;
1722    /*------------------------------------------------------------------------*/
1723    /* Iterate over the dynamic table in order to process dynamic tags.       */
1724    /* See ELF TIS Specification for details on the meaning of each dynamic   */
1725    /* tag.  The C6000 ELF ABI Specification provides more details about the  */
1726    /* TI specific C6000 ELF ABI tags.                                        */
1727    /*------------------------------------------------------------------------*/
1728    for (i = 0; dyn_module->dyntab[i].d_tag != DT_NULL; i++)
1729    {
1730       switch(dyn_module->dyntab[i].d_tag)
1731       {
1732          /*------------------------------------------------------------------*/
1733          /* DT_SONAME: Contains name of dynamic object, used for dependency  */
1734          /*            comparisons.  Its value is an offset from the start   */
1735          /*            of the string table.  We need to copy the string at   */
1736          /*            this offset into dmodule->name.                       */
1737          /*------------------------------------------------------------------*/
1738          case DT_SONAME:
1739 #if LOADER_DEBUG
1740             if (debugging_on) DLIF_trace("Found SO_NAME.\n");
1741 #endif
1742             /*---------------------------------------------------------------*/
1743             /* We store the offset of the so_name in the dynamic string      */
1744             /* table so that it doesn't matter which dynamic tag we see      */
1745             /* first (DT_SONAME actually is generated before DT_STRTAB).     */
1746             /*---------------------------------------------------------------*/
1747             soname_found = TRUE;
1748             soname_offset = dyn_module->dyntab[i].d_un.d_ptr;
1749             break;
1751          /*------------------------------------------------------------------*/
1752          /* DT_STRSZ: Contains the size of the string table.                 */
1753          /*------------------------------------------------------------------*/
1754          case DT_STRSZ:
1755             dyn_module->strsz = dyn_module->dyntab[i].d_un.d_val;
1757 #if LOADER_DEBUG
1758         if (debugging_on)
1759            DLIF_trace("Found string table Size: 0x%x\n", dyn_module->strsz);
1760 #endif
1761             break;
1763          /*------------------------------------------------------------------*/
1764          /* DT_STRTAB: Contains the file offset of the string table.  The    */
1765          /*            tag directly after this is guaranteed to be DT_STRSZ, */
1766          /*            containing the string table size.  We need to         */
1767          /*            allocate memory for the string table and copy it from */
1768          /*            the file.                                             */
1769          /*------------------------------------------------------------------*/
1770          case DT_STRTAB:
1771             strtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1772 #if LOADER_DEBUG
1773             if (debugging_on)
1774                DLIF_trace("Found string table: 0x%x\n", strtab_offset);
1775 #endif
1776             break;
1778          /*------------------------------------------------------------------*/
1779          /* DT_HASH: Contains the file offset of the symbol hash table.      */
1780          /*------------------------------------------------------------------*/
1781          case DT_HASH:
1782             hash_offset = dyn_module->dyntab[i].d_un.d_ptr;
1783 #if LOADER_DEBUG
1784             if (debugging_on)
1785                DLIF_trace("Found symbol hash table: 0x%x\n", hash_offset);
1786 #endif
1787             break;
1789          /*------------------------------------------------------------------*/
1790          /* DT_SYMTAB: Contains the file offset of the symbol table.         */
1791          /*------------------------------------------------------------------*/
1792          case DT_SYMTAB:
1793             symtab_offset = dyn_module->dyntab[i].d_un.d_ptr;
1794 #if LOADER_DEBUG
1795             if (debugging_on)
1796                DLIF_trace("Found symbol table: 0x%x\n", symtab_offset);
1797 #endif
1798             break;
1800          /*------------------------------------------------------------------*/
1801      /* DSO Initialization / Termination Model Dynamic Tags              */
1802          /*------------------------------------------------------------------*/
1803      /* For initialization tags, we store indices and array sizes in     */
1804      /* the dyn_module. Termination works a little different, the        */
1805      /* indices into the local copy of the dynamic table are stored in   */
1806      /* dyn_module, but the DT_FINI_ARRAYSZ value is recorded with the   */
1807      /* loaded module.                                                   */
1808          /*------------------------------------------------------------------*/
1809      /* After placement is done, the DT_FINI and DT_FINI_ARRAY values    */
1810      /* need to be copied from the local dynamic table into the loaded   */
1811      /* module object.                                                   */
1812          /*------------------------------------------------------------------*/
1813      case DT_PREINIT_ARRAY:
1814         dyn_module->preinit_array_idx = i;
1815         break;
1817      case DT_PREINIT_ARRAYSZ:
1818         dyn_module->preinit_arraysz = dyn_module->dyntab[i].d_un.d_val;
1819         break;
1821      case DT_INIT:
1822         dyn_module->init_idx = i;
1823         break;
1825      case DT_INIT_ARRAY:
1826         dyn_module->init_array_idx = i;
1827         break;
1829      case DT_INIT_ARRAYSZ:
1830         dyn_module->init_arraysz = dyn_module->dyntab[i].d_un.d_val;
1831         break;
1833          /*------------------------------------------------------------------*/
1834      /* This information will be copied over to the loaded module        */
1835      /* object after placement has been completed and the information    */
1836      /* in the dynamic table has been relocated.                         */
1837          /*------------------------------------------------------------------*/
1838      case DT_FINI_ARRAY:
1839      case DT_FINI_ARRAYSZ:
1840      case DT_FINI:
1841         break;
1843          /*------------------------------------------------------------------*/
1844          /* Unrecognized tag, may not be illegal, but is not explicitly      */
1845          /* handled by this function.  Should it be?                         */
1846          /*------------------------------------------------------------------*/
1847          default:
1848          {
1849             if (!process_target_dynamic_tag(dyn_module, i))
1850             {
1851 #if LOADER_DEBUG
1852                if (debugging_on)
1853                   DLIF_trace("Unrecognized dynamic tag: 0x%X\n",
1854                                dyn_module->dyntab[i].d_tag);
1855 #endif
1856             }
1858             break;
1859          }
1861       }
1862    }
1864    /*------------------------------------------------------------------------*/
1865    /* If string table offset and size were found, read string table in from  */
1866    /* the ELF object file.                                                   */
1867    /*------------------------------------------------------------------------*/
1868    if (strtab_offset && dyn_module->strsz)
1869    {
1870       DLIF_fseek(fd, strtab_offset, LOADER_SEEK_SET);
1871       dyn_module->strtab = DLIF_malloc(dyn_module->strsz);
1872       if(dyn_module->strtab)
1873          DLIF_fread(dyn_module->strtab, sizeof(uint8_t), dyn_module->strsz,
1874                     fd);
1875       else
1876          return FALSE;
1877    }
1878    else
1879    {
1880       DLIF_warning(DLWT_MISC,
1881                    "Mandatory dynamic tag DT_STRTAB/DT_STRSZ not found!\n");
1882       return FALSE;
1883    }
1886    /*------------------------------------------------------------------------*/
1887    /* If symbol hash table is found read-in the hash table.                  */
1888    /*------------------------------------------------------------------------*/
1889    if (hash_offset)
1890    {
1891       /*---------------------------------------------------------------------*/
1892       /* Hash table has the following format. nchain equals the number of    */
1893       /* entries in the symbol table (symnum)                                */
1894       /*                                                                     */
1895       /*             +----------------------------+                          */
1896       /*             |          nbucket           |                          */
1897       /*             +----------------------------+                          */
1898       /*             |          nchain            |                          */
1899       /*             +----------------------------+                          */
1900       /*             |         bucket[0]          |                          */
1901       /*             |            ...             |                          */
1902       /*             |     bucket[nbucket-1]      |                          */
1903       /*             +----------------------------+                          */
1904       /*             |          chain[0]          |                          */
1905       /*             |            ...             |                          */
1906       /*             |       chain[nchain-1]      |                          */
1907       /*             +----------------------------+                          */
1908       /*---------------------------------------------------------------------*/
1909       Elf32_Word hash_nbucket;
1910       Elf32_Word hash_nchain;
1912       /*---------------------------------------------------------------------*/
1913       /* Seek to the hash offset and read first two words into nbucket and   */
1914       /* symnum.                                                             */
1915       /*---------------------------------------------------------------------*/
1916       DLIF_fseek(fd, hash_offset, LOADER_SEEK_SET);
1917       DLIF_fread(&(hash_nbucket), sizeof(Elf32_Word), 1, fd);
1918       DLIF_fread(&(hash_nchain), sizeof(Elf32_Word), 1, fd);
1919       if (dyn_module->wrong_endian)
1920       {
1921          DLIMP_change_endian32((int32_t*)(&(hash_nbucket)));
1922          DLIMP_change_endian32((int32_t*)(&(hash_nchain)));
1923       }
1925       /*---------------------------------------------------------------------*/
1926       /* The number of entires in the dynamic symbol table is not encoded    */
1927       /* anywhere in the elf file. However, the nchain is guaranteed to be   */
1928       /* the same as the number of symbols. Use nchain to set the symnum.    */
1929       /*---------------------------------------------------------------------*/
1930       dyn_module->symnum = hash_nchain;
1931 #if LOADER_DEBUG
1932       if (debugging_on) DLIF_trace("symnum=%d\n", hash_nchain);
1933 #endif
1934    }
1935    else
1936    {
1937       DLIF_warning(DLWT_MISC, "Mandatory dynamic tag DT_HASH is not found!\n");
1938       return FALSE;
1939    }
1941    /*------------------------------------------------------------------------*/
1942    /* Read dynamic symbol table.                                             */
1943    /*------------------------------------------------------------------------*/
1944    if (symtab_offset)
1945    {
1946       int j = 0;
1947       DLIF_fseek(fd, symtab_offset, LOADER_SEEK_SET);
1948       dyn_module->symtab =
1949                  DLIF_malloc(dyn_module->symnum * sizeof(struct Elf32_Sym));
1950       if(dyn_module->symtab == NULL)
1951          return FALSE;
1952       DLIF_fread(dyn_module->symtab, sizeof(struct Elf32_Sym),
1953                  dyn_module->symnum, fd);
1954       if (dyn_module->wrong_endian)
1955       {
1956          for (j = 0; j < dyn_module->symnum; j++)
1957             DLIMP_change_sym_endian(dyn_module->symtab + j);
1958       }
1960       /*---------------------------------------------------------------------*/
1961       /* The st_name field of an Elf32_Sym entity is an offset into the      */
1962       /* string table. Convert it into a pointer to the string.              */
1963       /*---------------------------------------------------------------------*/
1964       if (strtab_offset)
1965          for (j = 0; j < dyn_module->symnum; j++)
1966             dyn_module->symtab[j].st_name += (Elf32_Word) dyn_module->strtab;
1967    }
1968    else
1969    {
1970       DLIF_warning(DLWT_MISC,
1971                    "Mandatory dynamic tag DT_SYMTAB is not found!\n");
1972       return FALSE;
1973    }
1975    /*------------------------------------------------------------------------*/
1976    /* Read the SONAME.                                                       */
1977    /*------------------------------------------------------------------------*/
1978    if (!soname_found)
1979    {
1980       DLIF_warning(DLWT_MISC, "Dynamic tag DT_SONAME is not found!\n");
1981       dyn_module->name = DLIF_malloc(sizeof(char));
1982       if(dyn_module->name)
1983           *dyn_module->name = '\0';
1984       else
1985           return FALSE;
1986    }
1987    else
1988    {
1989       dyn_module->name =
1990                     DLIF_malloc(strlen(dyn_module->strtab + soname_offset) + 1);
1991       if(dyn_module->name) {
1992          strcpy(dyn_module->name, dyn_module->strtab + soname_offset);
1994 #if LOADER_DEBUG
1995          if (debugging_on)
1996             DLIF_trace("Name of dynamic object: %s\n", dyn_module->name);
1997 #endif
1998       }
1999       else {
2000          DLIF_error(DLET_MISC, "Error allocating memory %d.\n",__LINE__);
2001          return FALSE;
2002       }
2003    }
2005    return TRUE;
2009 /*****************************************************************************/
2010 /* dload_dynamic_information()                                               */
2011 /*                                                                           */
2012 /*    Given a dynamic module with a dynamic segment which is located via     */
2013 /*    given dynamic segment index, make a local copy of the dynamic table    */
2014 /*    in the dynamic module object, then process the dynamic tag entries in  */
2015 /*    the table.                                                             */
2016 /*                                                                           */
2017 /*****************************************************************************/
2018 static BOOL dload_dynamic_information(LOADER_FILE_DESC *fd,
2019                                       DLIMP_Dynamic_Module *dyn_module,
2020                                       Elf32_Word dyn_seg_idx)
2022    /*------------------------------------------------------------------------*/
2023    /* Read a copy of the dynamic table into the dynamic module object.       */
2024    /*------------------------------------------------------------------------*/
2025    copy_dynamic_table(fd, dyn_module, dyn_seg_idx);
2027    /*------------------------------------------------------------------------*/
2028    /* Process dynamic entries in the dynamic table.  If any problems are     */
2029    /* encountered, the loader should emit an error or warning and return     */
2030    /* FALSE here.                                                            */
2031    /*------------------------------------------------------------------------*/
2032    return process_dynamic_table(fd, dyn_module);
2035 /*****************************************************************************/
2036 /* check_circular_dependency()                                               */
2037 /*                                                                           */
2038 /*    Determine whether a dynamic module is already in the process of being  */
2039 /*    loaded before we try to start loading it again.  If it is already      */
2040 /*    being loaded, then the dynamic loader has detected a circular          */
2041 /*    dependency.  An error will be emitted and the load will be aborted.    */
2042 /*                                                                           */
2043 /*****************************************************************************/
2044 static BOOL check_circular_dependency(DLOAD_HANDLE handle,
2045                                       const char *dyn_mod_name)
2047    /*------------------------------------------------------------------------*/
2048    /* Check the name of the given dependency module to be loaded against the */
2049    /* list of modules that are currently in the process of being loaded.     */
2050    /* Report an error if any circular dependencies are detected.             */
2051    /*------------------------------------------------------------------------*/
2052    int i;
2053     LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2054     for (i = 0; i < pHandle->DLIMP_module_dependency_list.size; i++)
2055         if (!strcmp(dyn_mod_name,
2056             ((char**)(pHandle->DLIMP_module_dependency_list.buf))[i]))
2057       {
2058          DLIF_error(DLET_MISC,
2059                     "Circular dependency detected, '%s' is already in the "
2060                     "process of loading.\n", dyn_mod_name);
2061          return FALSE;
2062       }
2064    return TRUE;
2067 /*****************************************************************************/
2068 /* dload_dynamic_segment()                                                   */
2069 /*                                                                           */
2070 /*    Find the dynamic segment in the given ELF module, if there is one.     */
2071 /*    If there is a dynamic segment, then make a local copy of the dynamic   */
2072 /*    table in the dynamic module object provided, then process the dynamic  */
2073 /*    tag entries in the table.                                              */
2074 /*                                                                           */
2075 /*    If there is no dynamic segment, then we return success from this       */
2076 /*    function, marking the dynamic module as "not relocatable".             */
2077 /*                                                                           */
2078 /*****************************************************************************/
2079 static BOOL dload_dynamic_segment(DLOAD_HANDLE handle,
2080                                   LOADER_FILE_DESC *fd,
2081                                   DLIMP_Dynamic_Module *dyn_module)
2083    /*------------------------------------------------------------------------*/
2084    /* If we don't find dynamic segment, the relocatable flag will have been  */
2085    /* set to false to indicate that the module is a static executable.  We   */
2086    /* still return TRUE from this function so that we can proceed with       */
2087    /* static loading.                                                        */
2088    /*------------------------------------------------------------------------*/
2089    Elf32_Word dyn_seg_idx = 0;
2090    if (!find_dynamic_segment(dyn_module, &dyn_seg_idx))
2091       return TRUE;
2093    /*------------------------------------------------------------------------*/
2094    /* Process the OSABI now, after we know if the module is relocatable.     */
2095    /*------------------------------------------------------------------------*/
2096    if (!process_eiosabi(dyn_module))
2097    {
2098       DLIF_error(DLET_FILE, "Unsupported EI_OSABI value.\n");
2099       return FALSE;
2100    }
2102    /*------------------------------------------------------------------------*/
2103    /* Read the dynamic table from the ELF file, then process the dynamic     */
2104    /* tags in the table.                                                     */
2105    /*------------------------------------------------------------------------*/
2106    if (!dload_dynamic_information(fd, dyn_module, dyn_seg_idx))
2107       return FALSE;
2109    /*------------------------------------------------------------------------*/
2110    /* Check to make sure that this module is not already being loaded.  If   */
2111    /* is, then it will cause a circular dependency to be introduced.         */
2112    /* Loader should detect circular dependencies and emit an error.          */
2113    /*------------------------------------------------------------------------*/
2114     if (!check_circular_dependency(handle, dyn_module->name))
2115       return FALSE;
2117    return TRUE;
2120 /*****************************************************************************/
2121 /* COPY_SEGMENTS() -                                                         */
2122 /*                                                                           */
2123 /*   Copy all segments into host memory.                                     */
2124 /*****************************************************************************/
2125 static void copy_segments(DLOAD_HANDLE handle, LOADER_FILE_DESC* fp,
2126                           DLIMP_Dynamic_Module* dyn_module)
2128    DLIMP_Loaded_Segment* seg =
2129       (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
2130    int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
2131    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2134    for (s=0; s<seg_size; s++)
2135    {
2136       struct DLOAD_MEMORY_REQUEST targ_req;
2137       targ_req.fp = fp;
2138       targ_req.segment = seg[s].obj_desc;
2139       targ_req.offset = seg[s].phdr.p_offset;
2140       targ_req.flags = DLOAD_SF_relocatable;
2141       if (seg[s].phdr.p_flags & PF_X)
2142          seg[s].phdr.p_flags |= DLOAD_SF_executable;
2143       targ_req.align = seg[s].phdr.p_align;
2145       /*---------------------------------------------------------------------*/
2146       /* Copy segment data from the file into host buffer where it can       */
2147       /* be relocated.                                                       */
2148       /*---------------------------------------------------------------------*/
2149       DLIF_copy(pHandle->client_handle, &targ_req);
2150       seg[s].host_address = targ_req.host_address;
2151    }
2154 /*****************************************************************************/
2155 /* WRITE_SEGMENTS() -                                                        */
2156 /*                                                                           */
2157 /*   Write all segments to target memory.                                    */
2158 /*****************************************************************************/
2159 static void write_segments(DLOAD_HANDLE handle,
2160                           LOADER_FILE_DESC* fp,
2161                           DLIMP_Dynamic_Module* dyn_module)
2163    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2164    DLIMP_Loaded_Segment* seg =
2165       (DLIMP_Loaded_Segment*)(dyn_module->loaded_module->loaded_segments.buf);
2166    int s, seg_size = dyn_module->loaded_module->loaded_segments.size;
2168    for (s=0; s<seg_size; s++)
2169    {
2170       struct DLOAD_MEMORY_REQUEST targ_req;
2171       targ_req.fp = fp;
2172       targ_req.segment = seg[s].obj_desc;
2173       targ_req.offset = seg[s].phdr.p_offset;
2174       targ_req.flags = DLOAD_SF_relocatable;
2175       if (seg[s].phdr.p_flags & PF_X)
2176          seg[s].phdr.p_flags |= DLOAD_SF_executable;
2177       targ_req.align = seg[s].phdr.p_align;
2178       targ_req.host_address = seg[s].host_address;
2180       /*---------------------------------------------------------------------*/
2181       /* Copy segment data from the file into host buffer where it can       */
2182       /* be relocated.                                                       */
2183       /*---------------------------------------------------------------------*/
2184       DLIF_write(pHandle->client_handle, &targ_req);
2185    }
2188 /*****************************************************************************/
2189 /* SEG_HAS_SPACE_FOR_WRITE() -                                               */
2190 /*                                                                           */
2191 /*   Check if segment has enough space to recieve contents of .args section. */
2192 /*****************************************************************************/
2193 static BOOL seg_has_space_for_write(DLIMP_Loaded_Module* lmodule, int sz)
2195    DLIMP_Loaded_Segment* seg =
2196                   (DLIMP_Loaded_Segment*)(lmodule->loaded_segments.buf);
2197    int s, seg_size = lmodule->loaded_segments.size;
2199    Elf32_Addr write_address = (Elf32_Addr)lmodule->c_args;
2201    for (s=0; s<seg_size; s++)
2202    {
2203       Elf32_Addr seg_boundary =
2204             seg[s].phdr.p_vaddr + seg[s].obj_desc->memsz_in_bytes;
2206       /*---------------------------------------------------------------------*/
2207       /* If address to write to is greater than segment addr and less than   */
2208       /* segment end, it must lie in current segment.                        */
2209       /*---------------------------------------------------------------------*/
2210       if ((write_address >= seg[s].phdr.p_vaddr) &&
2211           (write_address < seg_boundary))
2212       {
2213          if ((write_address + sz) > seg_boundary)
2214          {
2215 #if LOADER_DEBUG
2216         if (debugging_on)
2217         {
2218            DLIF_trace("Write requires 0x%x bytes\n",write_address + sz);
2219            DLIF_trace("Seg boundary at : 0x%x\n",seg_boundary);
2220            DLIF_trace("WARNING - Not enough space in segment\n");
2221         }
2222 #endif
2223             return FALSE;
2224          }
2225          else return TRUE;
2226       }
2227    }
2228    /*------------------------------------------------------------------------*/
2229    /* Given address doesn't belong to any known segment.                     */
2230    /*------------------------------------------------------------------------*/
2231    return FALSE;
2234 /*****************************************************************************/
2235 /* DLOAD_initialize()                                                        */
2236 /*                                                                           */
2237 /*    Construct and initialize data structures internal to the dynamic       */
2238 /*    loader core.                                                           */
2239 /*                                                                           */
2240 /*---------------------------------------------------------------------------*/
2241 /*                                                                           */
2242 /*    This function is deprecated, replaced by DLOAD_create().               */
2243 /*                                                                           */
2244 /*****************************************************************************/
2245 void DLOAD_initialize(DLOAD_HANDLE handle)
2250 /*****************************************************************************/
2251 /* DLOAD_finalize()                                                          */
2252 /*                                                                           */
2253 /*    Destroy and finalize data structures internal to the dynamic           */
2254 /*    loader core.                                                           */
2255 /*                                                                           */
2256 /*---------------------------------------------------------------------------*/
2257 /*                                                                           */
2258 /*    This function is deprecated, replaced by DLOAD_destroy().              */
2259 /*                                                                           */
2260 /*****************************************************************************/
2261 void DLOAD_finalize(DLOAD_HANDLE handle)
2266 /*****************************************************************************/
2267 /* dload_static_executable()                                                 */
2268 /*                                                                           */
2269 /*    Account for target memory allocated to static executable and wrap up   */
2270 /*    loading.  No relocation is necessary.                                  */
2271 /*                                                                           */
2272 /*****************************************************************************/
2273 static int32_t dload_static_executable(DLOAD_HANDLE handle,
2274                                        LOADER_FILE_DESC *fd,
2275                                        DLIMP_Dynamic_Module *dyn_module)
2277    int32_t local_file_handle = 0;
2279 #if LOADER_DEBUG
2280    if (debugging_on) DLIF_trace("Starting dload_static_executable() ...\n");
2281 #endif
2283    /*------------------------------------------------------------------------*/
2284    /* Set entry point for static executable and attempt to allocate target   */
2285    /* memory for the static executable.                                      */
2286    /*------------------------------------------------------------------------*/
2287    dyn_module->loaded_module->entry_point = dyn_module->fhdr.e_entry;
2288    if (load_static_segment(handle, fd, dyn_module) &&
2289        load_object(fd, dyn_module))
2290    {
2291       /*---------------------------------------------------------------------*/
2292       /* If successful, we'll want to detach the loaded module object from   */
2293       /* the dynamic module object that created it.  Take note of the file   */
2294       /* handle.                                                             */
2295       /*---------------------------------------------------------------------*/
2296       DLIMP_Loaded_Module *loaded_module = detach_loaded_module(dyn_module);
2297         if (loaded_module)
2298             local_file_handle = loaded_module->file_handle;
2299         else {
2300             DLIF_error(DLET_MISC, "Failed to detach module.\n");
2301             delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2302             return local_file_handle;
2303         }
2304    }
2306    /*------------------------------------------------------------------------*/
2307    /* Static load failed.  Flag an error.                                    */
2308    /*------------------------------------------------------------------------*/
2309    else
2310    {
2311       DLIF_trace("%s:%d EMEMORY\n",__func__,__LINE__);
2312       DLIF_error(DLET_MEMORY,
2313                  "Failed to allocate target memory for static executable.\n");
2314    }
2316    /*------------------------------------------------------------------------*/
2317    /* Destruct dynamic module object.                                        */
2318    /*------------------------------------------------------------------------*/
2319     delete_DLIMP_Dynamic_Module(handle, &dyn_module);
2321 #if LOADER_DEBUG
2322    if (debugging_on) DLIF_trace("Finished dload_static_executable()\n");
2323 #endif
2325    return local_file_handle;
2328 #if LOADER_DEBUG && LOADER_PROFILE
2329 int DLREL_relocations;
2330 time_t DLREL_total_reloc_time;
2331 #endif
2333 /*****************************************************************************/
2334 /* process_dynamic_module_relocations()                                      */
2335 /*                                                                           */
2336 /*    Make a host-accessible copy of all of the segments, process all        */
2337 /*    relocation entries associated with the given module within that        */
2338 /*    space, then write the updated segment buffers back out to target       */
2339 /*    memory.                                                                */
2340 /*                                                                           */
2341 /*****************************************************************************/
2342 static void process_dynamic_module_relocations(DLOAD_HANDLE handle,
2343                                                LOADER_FILE_DESC *fd,
2344                                                DLIMP_Dynamic_Module *dyn_module)
2346 #if LOADER_DEBUG && LOADER_PROFILE
2347    if(debugging_on || profiling_on)
2348    {
2349       DLIF_trace("Running relocate()...\n");
2350       if (profiling_on) profile_start_clock();
2351    }
2352 #endif
2354    /*------------------------------------------------------------------------*/
2355    /* Copy segments from file to host memory                                 */
2356    /*------------------------------------------------------------------------*/
2357    copy_segments(handle, fd, dyn_module);
2359    /*------------------------------------------------------------------------*/
2360    /* Process dynamic relocations.                                           */
2361    /*------------------------------------------------------------------------*/
2362    DLREL_relocate(handle, fd, dyn_module);
2364    /*------------------------------------------------------------------------*/
2365    /* Write segments from host memory to target memory                       */
2366    /*------------------------------------------------------------------------*/
2367    write_segments(handle, fd, dyn_module);
2369 #if 0
2370    /*------------------------------------------------------------------------*/
2371    /* Report timing and progress information for relocation step.            */
2372    /*------------------------------------------------------------------------*/
2373    if (debugging_on || profiling_on)
2374    {
2375       if (profiling_on)
2376       {
2377          profile_stop_clock();
2378          DLIF_trace("Took %d cycles.\n", (int)profile_cycle_count());
2379          DLIF_trace("Total reloc time: %d\n", (int)DLREL_total_reloc_time);
2380          DLIF_trace("Time per relocation: %d\n",
2381                     (DLREL_relocations ?
2382                     (int)(DLREL_total_reloc_time / DLREL_relocations) : 0));
2383       }
2385       DLIF_trace("Number of relocations: %d\n", DLREL_relocations);
2386       DLIF_trace("\nAbout to run load_object()...");
2387       DLREL_total_reloc_time = DLREL_relocations = 0;
2388       if (profiling_on) profile_start_clock();
2389    }
2390 #endif
2394 /*****************************************************************************/
2395 /* store_preinit_data()                                                      */
2396 /*                                                                           */
2397 /*    Given a dynamic module object, store pre-initialization function       */
2398 /*    information. The user may also provide a custom iniitialization        */
2399 /*    function that needs to be executed before the compiler                 */
2400 /*    generated static initialization functions are executed.                */
2401 /*    The dynamic loader will now create a table TI_init_table to store      */
2402 /*    pre-init and init data. This is done because pre-init and              */
2403 /*    init functions could reference as-yet unrelocated symbols from other   */
2404 /*    modules. As such it is safer to store relevant function addresses and  */
2405 /*    execute them only after all modules are relocated (CQ34088).           */
2406 /*                                                                           */
2407 /*****************************************************************************/
2408 static void store_preinit_data(DLIMP_Dynamic_Module *dyn_module)
2410    IF_single_record *preinit_rec = NULL;
2411    /*------------------------------------------------------------------------*/
2412    /* Check for presence of DT_PREINIT_ARRAY and DT_PREINIT_ARRAYSZ          */
2413    /* dynamic tags associated with this module. The dyn_module object will   */
2414    /* hold the relevant indices into the local copy of the dynamic table.    */
2415    /* The value of the DT_INIT_ARRAY tag will have been updated after        */
2416    /* placement of the  module was completed. Arrays of size 0 will be       */
2417    /* ignored (CQ36935).                                                     */
2418    /*------------------------------------------------------------------------*/
2419    if (dyn_module->preinit_arraysz > 0)
2420    {
2421       preinit_rec = (IF_single_record *)DLIF_malloc(sizeof(IF_single_record));
2422       /*---------------------------------------------------------------------*/
2423       /* Retrieve the address of the .preinit_array section from the value   */
2424       /* of the DT_PREINIT_ARRAY tag, and store it in the TI_init_table.     */
2425       /*---------------------------------------------------------------------*/
2426       preinit_rec->size = dyn_module->preinit_arraysz;
2427       preinit_rec->sect_addr = (TARGET_ADDRESS)
2428                 (dyn_module->dyntab[dyn_module->preinit_array_idx].d_un.d_ptr);
2429    }
2431    if (preinit_rec) IF_table_enqueue(&TI_init_table, preinit_rec);
2434 /*****************************************************************************/
2435 /* store_init_data()                                                         */
2436 /*                                                                           */
2437 /*    Given a dynamic module object, save off initialization function(s) for */
2438 /*    all global and static data objects that are defined in the module      */
2439 /*    which require construction. The dynamic loader will now create a table */
2440 /*    TI_init_table to store pre-init and init data. This is done because    */
2441 /*    pre-init and init functions could reference as-yet unrelocated symbols */
2442 /*    from other modules. As such it is safer to store relevant function     */
2443 /*    addresses and execute them only after all modules are relocated.       */
2444 /*                                                                           */
2445 /*****************************************************************************/
2446 static void store_init_data(DLIMP_Dynamic_Module *dyn_module)
2448    /*------------------------------------------------------------------------*/
2449    /* Check for presence of a DT_INIT dynamic tag associated with this       */
2450    /* module. The dynamic module will hold the index into the local copy of  */
2451    /* the dynamic table. This entry in the dynamic table will have been      */
2452    /* updated after placement of the module is completed.                    */
2453    /*------------------------------------------------------------------------*/
2454    if (dyn_module->init_idx != -1)
2455    {
2456       IF_single_record *init_rec =
2457                    (IF_single_record *)DLIF_malloc(sizeof(IF_single_record));
2458       /*---------------------------------------------------------------------*/
2459       /* Retrieve the address of the initialization function from the value  */
2460       /* of the DT_INIT tag, and get the client to execute the function.     */
2461       /*---------------------------------------------------------------------*/
2462       init_rec->size = 0;
2463       init_rec->sect_addr = (TARGET_ADDRESS)
2464                          (dyn_module->dyntab[dyn_module->init_idx].d_un.d_ptr);
2466       IF_table_enqueue(&TI_init_table, init_rec);
2467    }
2469    /*------------------------------------------------------------------------*/
2470    /* Check for presence of a DT_INIT_ARRAY and DT_INIT_ARRAYSZ dynamic tags */
2471    /* associated with this module. The dyn_module object will hold the       */
2472    /* relevant indices into the local copy of the dynamic table. The value   */
2473    /* of the DT_INIT_ARRAY tag will have been updated after placement of the */
2474    /* module was completed. Arraysz must be a postive number > 0, else it    */
2475    /* be ignored (CQ36935).                                                  */
2476    /*------------------------------------------------------------------------*/
2477    if (dyn_module->init_arraysz > 0)
2478    {
2479       IF_single_record *arr_rec =
2480                    (IF_single_record *)DLIF_malloc(sizeof(IF_single_record));
2481       /*---------------------------------------------------------------------*/
2482       /* Retrieve the address of the .init_array section from the value of   */
2483       /* DT_INIT_ARRAY tag.                                                  */
2484       /*---------------------------------------------------------------------*/
2485       arr_rec->size = dyn_module->init_arraysz;
2486       arr_rec->sect_addr = (TARGET_ADDRESS)
2487                    (dyn_module->dyntab[dyn_module->init_array_idx].d_un.d_ptr);
2489       IF_table_enqueue(&TI_init_table, arr_rec);
2490    }
2493 /*****************************************************************************/
2494 /* execute_module_initialization()                                           */
2495 /*                                                                           */
2496 /*    Given a dynamic module object, execute pre-initialization and          */
2497 /*    initialization function(s) for all global and static data objects that */
2498 /*    are defined in the module which require construction. The user may     */
2499 /*    also provide a custom iniitialization function that needs to be        */
2500 /*    executed before the compiler generated static initialization functions */
2501 /*    are executed.                                                          */
2502 /*    Note that the functions to be executed have already been saved off in  */
2503 /*    the TI_init_table, by store_preinit_data() and store_init_data().      */
2504 /*                                                                           */
2505 /*****************************************************************************/
2506 static void execute_module_initialization(DLOAD_HANDLE handle)
2508    IF_single_record *val = NULL;
2509    IF_table_Queue_Node *curr_ptr = TI_init_table.front_ptr;
2510    LOADER_OBJECT *pHandle = (LOADER_OBJECT *)handle;
2512    for (; curr_ptr; curr_ptr = curr_ptr->next_ptr)
2513    {
2514       val = curr_ptr->value;
2516       /*---------------------------------------------------------------------*/
2517       /* A size of 0 indicates DT_INIT, otherwise this is an ARRAY.         */
2518       /*---------------------------------------------------------------------*/
2519       if (val->size != 0)
2520       {
2521          /*------------------------------------------------------------------*/
2522          /* Now make a loader-accessible copy of the .init_array section.    */
2523          /*------------------------------------------------------------------*/
2524          int32_t i;
2525          int32_t num_init_fcns = val->size/sizeof(TARGET_ADDRESS);
2526          TARGET_ADDRESS *init_array_buf = (TARGET_ADDRESS *)
2527                                             DLIF_malloc(val->size);
2529          DLIF_read(pHandle->client_handle,
2530                init_array_buf, 1, val->size,
2531            (TARGET_ADDRESS)val->sect_addr);
2533          /*------------------------------------------------------------------*/
2534          /* Call each function whose address occupies an entry in array in   */
2535          /* the order that they appear in the array. The size of the array is*/
2536          /* provided by the init_arraysz field in the dynamic module (copied */
2537          /* earlier when the dynamic table was read in). Make sure that      */
2538          /* function addresses are valid before execution.                   */
2539          /*------------------------------------------------------------------*/
2540          for (i = 0; i < num_init_fcns; i++)
2541             if (init_array_buf[i])
2542                DLIF_execute(pHandle->client_handle,
2543                         (TARGET_ADDRESS)(init_array_buf[i]));
2544             else
2545                DLIF_warning(DLWT_MISC,
2546                   "DT_INIT_ARRAY/DT_PREINIT_ARRAY function address is NULL!");
2548          DLIF_free(init_array_buf);
2549       }
2550       else
2551       {
2552          if (val->sect_addr)
2553             DLIF_execute(pHandle->client_handle,
2554                      (TARGET_ADDRESS)(val->sect_addr));
2555          else
2556             DLIF_warning(DLWT_MISC, "DT_INIT function address is NULL!");
2557       }
2558    }
2561 /*****************************************************************************/
2562 /* adjust_module_init_fini()                                                 */
2563 /*    If the dynamic loader need not process the module initialization       */
2564 /*    and termination (fini section) then adjust the module info so that     */
2565 /*    the respective sizes become zero.                                      */
2566 /*****************************************************************************/
2567 static void adjust_module_init_fini(DLIMP_Dynamic_Module *dm)
2569    /*------------------------------------------------------------------------*/
2570    /* The C6x RTS boot code has the function _c_int00 which performs         */
2571    /* the C/C++ initialization. This function processes the .init_array      */
2572    /* to perform the C/C++ initialization and handles termination through    */
2573    /* the at_exit functionality. If the dynamic executable we are loading    */
2574    /* includes _c_int00, the loader assumes that the application code takes  */
2575    /* care of all initialization and termination. Hence the loader won't     */
2576    /* perform the initialization and termination.                            */
2577    /* NOTE: Use of __TI_STACK_SIZE is a hack. The _c_int00 symbol is not     */
2578    /*       in the dynamic symbol table. The right fix is for the linker     */
2579    /*       not to generate the init array tags if the build includes RTS    */
2580    /*       boot routine.                                                    */
2581    /*------------------------------------------------------------------------*/
2582    if (dm->fhdr.e_type == ET_EXEC &&
2583        DLSYM_lookup_local_symtab("__TI_STACK_SIZE", dm->symtab, dm->symnum,
2584                                  NULL))
2585    {
2586       dm->init_arraysz   = 0;
2587       dm->init_array_idx = -1;
2589       dm->preinit_arraysz   = 0;
2590       dm->preinit_array_idx = -1;
2592       dm->loaded_module->fini_arraysz = 0;
2593       dm->loaded_module->fini_array   = (Elf32_Addr) NULL;
2594       dm->loaded_module->fini         = (Elf32_Addr) NULL;
2595    }
2598 /*****************************************************************************/
2599 /* relocate_dependency_graph_modules()                                       */
2600 /*                                                                           */
2601 /*    For each dynamic module on the dependency stack, process dynamic       */
2602 /*    relocation entries then perform initialization for all global and      */
2603 /*    static objects that are defined in tha given module. The stack is      */
2604 /*    emptied from the top (LIFO).  Each dynamic module object is popped     */
2605 /*    off the top of the stack, the module gets relocated, its global and    */
2606 /*    static objects that need to be constructed will be constructed, and    */
2607 /*    then, after detaching the loaded module object from its dynamic        */
2608 /*    module, the dynamic module object is destructed.                       */
2609 /*                                                                           */
2610 /*****************************************************************************/
2611 static
2612 int32_t relocate_dependency_graph_modules(DLOAD_HANDLE handle,
2613                                           LOADER_FILE_DESC *fd,
2614                                           DLIMP_Dynamic_Module *dyn_module)
2616    /*------------------------------------------------------------------------*/
2617    /* Processing of relocations will only be triggered when this function    */
2618    /* is called from the top-level object module (at the bottom of the       */
2619    /* dependency graph stack).                                               */
2620    /*------------------------------------------------------------------------*/
2621    int32_t local_file_handle = dyn_module->loaded_module->file_handle;
2622    LOADER_OBJ