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