4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Copyright (C) 2005-2006 Texas Instruments, Inc.
8 * This package is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 #include "module_list.h"
20 #define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
25 static void dload_symbols(struct dload_state *dlthis);
26 static void dload_data(struct dload_state *dlthis);
27 static void allocate_sections(struct dload_state *dlthis);
28 static void string_table_free(struct dload_state *dlthis);
29 static void symbol_table_free(struct dload_state *dlthis);
30 static void section_table_free(struct dload_state *dlthis);
31 static void init_module_handle(struct dload_state *dlthis);
32 #if BITS_PER_AU > BITS_PER_BYTE
33 static char *unpack_name(struct dload_state *dlthis, u32 soffset);
36 static const char cinitname[] = { ".cinit" };
37 static const char loader_dllview_root[] = { "?DLModules?" };
42 static const char readstrm[] = { "Error reading %s from input stream" };
43 static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
44 static const char tgtalloc[] = {
45 "Target memory allocate failed, section %s size " FMT_UI32 };
46 static const char initfail[] = { "%s to target address " FMT_UI32 " failed" };
47 static const char dlvwrite[] = { "Write to DLLview list failed" };
48 static const char iconnect[] = { "Connect call to init interface failed" };
49 static const char err_checksum[] = { "Checksum failed on %s" };
51 /*************************************************************************
52 * Procedure dload_error
55 * errtxt description of the error, printf style
56 * ... additional information
59 * Reports or records the error as appropriate.
60 *********************************************************************** */
61 void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
65 va_start(args, errtxt);
66 dlthis->mysym->error_report(dlthis->mysym, errtxt, args);
68 dlthis->dload_errcount += 1;
72 #define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
74 /*************************************************************************
75 * Procedure dload_syms_error
78 * errtxt description of the error, printf style
79 * ... additional information
82 * Reports or records the error as appropriate.
83 *********************************************************************** */
84 void dload_syms_error(struct dynamic_loader_sym *syms, const char *errtxt, ...)
88 va_start(args, errtxt);
89 syms->error_report(syms, errtxt, args);
93 /*************************************************************************
94 * Procedure dynamic_load_module
97 * module The input stream that supplies the module image
98 * syms Host-side symbol table and malloc/free functions
99 * alloc Target-side memory allocation
100 * init Target-side memory initialization
101 * options Option flags DLOAD_*
102 * mhandle A module handle for use with Dynamic_Unload
105 * The module image is read using *module. Target storage for the new
107 * obtained from *alloc. Symbols defined and referenced by the module are
108 * managed using *syms. The image is then relocated and references
109 * resolved as necessary, and the resulting executable bits are placed
110 * into target memory using *init.
113 * On a successful load, a module handle is placed in *mhandle,
114 * and zero is returned. On error, the number of errors detected is
115 * returned. Individual errors are reported during the load process
116 * using syms->error_report().
117 ********************************************************************** */
118 int dynamic_load_module(struct dynamic_loader_stream *module,
119 struct dynamic_loader_sym *syms,
120 struct dynamic_loader_allocate *alloc,
121 struct dynamic_loader_initialize *init,
122 unsigned options, void **mhandle)
124 register unsigned *dp, sz;
125 struct dload_state dl_state; /* internal state for this call */
127 /* blast our internal state */
128 dp = (unsigned *)&dl_state;
129 for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
132 /* Enable _only_ BSS initialization if enabled by user */
133 if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
134 dl_state.myoptions = DLOAD_INITBSS;
136 /* Check that mandatory arguments are present */
137 if (!module || !syms) {
138 dload_error(&dl_state, "Required parameter is NULL");
140 dl_state.strm = module;
141 dl_state.mysym = syms;
142 dload_headers(&dl_state);
143 if (!dl_state.dload_errcount)
144 dload_strings(&dl_state, false);
145 if (!dl_state.dload_errcount)
146 dload_sections(&dl_state);
148 if (init && !dl_state.dload_errcount) {
149 if (init->connect(init)) {
150 dl_state.myio = init;
151 dl_state.myalloc = alloc;
152 /* do now, before reducing symbols */
153 allocate_sections(&dl_state);
155 dload_error(&dl_state, iconnect);
158 if (!dl_state.dload_errcount) {
159 /* fix up entry point address */
160 unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
161 if (sref < dl_state.allocated_secn_count)
162 dl_state.dfile_hdr.df_entrypt +=
163 dl_state.ldr_sections[sref].run_addr;
165 dload_symbols(&dl_state);
168 if (init && !dl_state.dload_errcount)
169 dload_data(&dl_state);
171 init_module_handle(&dl_state);
173 /* dl_state.myio is init or 0 at this point. */
175 if ((!dl_state.dload_errcount) &&
176 (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
177 (!init->execute(init,
178 dl_state.dfile_hdr.df_entrypt)))
179 dload_error(&dl_state, "Init->Execute Failed");
183 symbol_table_free(&dl_state);
184 section_table_free(&dl_state);
185 string_table_free(&dl_state);
186 dload_tramp_cleanup(&dl_state);
188 if (dl_state.dload_errcount) {
189 dynamic_unload_module(dl_state.myhandle, syms, alloc,
191 dl_state.myhandle = NULL;
196 *mhandle = dl_state.myhandle; /* give back the handle */
198 return dl_state.dload_errcount;
201 /*************************************************************************
202 * Procedure dynamic_open_module
205 * module The input stream that supplies the module image
206 * syms Host-side symbol table and malloc/free functions
207 * alloc Target-side memory allocation
208 * init Target-side memory initialization
209 * options Option flags DLOAD_*
210 * mhandle A module handle for use with Dynamic_Unload
213 * The module image is read using *module. Target storage for the new
215 * obtained from *alloc. Symbols defined and referenced by the module are
216 * managed using *syms. The image is then relocated and references
217 * resolved as necessary, and the resulting executable bits are placed
218 * into target memory using *init.
221 * On a successful load, a module handle is placed in *mhandle,
222 * and zero is returned. On error, the number of errors detected is
223 * returned. Individual errors are reported during the load process
224 * using syms->error_report().
225 ********************************************************************** */
227 dynamic_open_module(struct dynamic_loader_stream *module,
228 struct dynamic_loader_sym *syms,
229 struct dynamic_loader_allocate *alloc,
230 struct dynamic_loader_initialize *init,
231 unsigned options, void **mhandle)
233 register unsigned *dp, sz;
234 struct dload_state dl_state; /* internal state for this call */
236 /* blast our internal state */
237 dp = (unsigned *)&dl_state;
238 for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
241 /* Enable _only_ BSS initialization if enabled by user */
242 if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
243 dl_state.myoptions = DLOAD_INITBSS;
245 /* Check that mandatory arguments are present */
246 if (!module || !syms) {
247 dload_error(&dl_state, "Required parameter is NULL");
249 dl_state.strm = module;
250 dl_state.mysym = syms;
251 dload_headers(&dl_state);
252 if (!dl_state.dload_errcount)
253 dload_strings(&dl_state, false);
254 if (!dl_state.dload_errcount)
255 dload_sections(&dl_state);
257 if (init && !dl_state.dload_errcount) {
258 if (init->connect(init)) {
259 dl_state.myio = init;
260 dl_state.myalloc = alloc;
261 /* do now, before reducing symbols */
262 allocate_sections(&dl_state);
264 dload_error(&dl_state, iconnect);
267 if (!dl_state.dload_errcount) {
268 /* fix up entry point address */
269 unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
270 if (sref < dl_state.allocated_secn_count)
271 dl_state.dfile_hdr.df_entrypt +=
272 dl_state.ldr_sections[sref].run_addr;
274 dload_symbols(&dl_state);
277 init_module_handle(&dl_state);
279 /* dl_state.myio is either 0 or init at this point. */
281 if ((!dl_state.dload_errcount) &&
282 (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
283 (!init->execute(init,
284 dl_state.dfile_hdr.df_entrypt)))
285 dload_error(&dl_state, "Init->Execute Failed");
289 symbol_table_free(&dl_state);
290 section_table_free(&dl_state);
291 string_table_free(&dl_state);
293 if (dl_state.dload_errcount) {
294 dynamic_unload_module(dl_state.myhandle, syms, alloc,
296 dl_state.myhandle = NULL;
301 *mhandle = dl_state.myhandle; /* give back the handle */
303 return dl_state.dload_errcount;
306 /*************************************************************************
307 * Procedure dload_headers
313 * Loads the DOFF header and verify record. Deals with any byte-order
314 * issues and checks them for validity.
315 *********************************************************************** */
316 #define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
317 sizeof(struct doff_verify_rec_t))
319 void dload_headers(struct dload_state *dlthis)
323 /* Read the header and the verify record as one. If we don't get it
325 if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
326 COMBINED_HEADER_SIZE) !=
327 COMBINED_HEADER_SIZE) {
328 DL_ERROR(readstrm, "File Headers");
332 * Verify that we have the byte order of the file correct.
333 * If not, must fix it before we can continue
335 map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
336 if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
337 /* input is either byte-shuffled or bad */
338 if ((map & 0xFCFCFCFC) == 0) { /* no obviously bogus bits */
339 dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
342 if (dlthis->dfile_hdr.df_byte_reshuffle !=
343 BYTE_RESHUFFLE_VALUE) {
344 /* didn't fix the problem, the byte swap map is bad */
346 "Bad byte swap map " FMT_UI32 " in header",
347 dlthis->dfile_hdr.df_byte_reshuffle);
350 dlthis->reorder_map = map; /* keep map for future use */
354 * Verify checksum of header and verify record
356 if (~dload_checksum(&dlthis->dfile_hdr,
357 sizeof(struct doff_filehdr_t)) ||
358 ~dload_checksum(&dlthis->verify,
359 sizeof(struct doff_verify_rec_t))) {
360 DL_ERROR(err_checksum, "header or verify record");
364 dlthis->dfile_hdr.df_byte_reshuffle = map; /* put back for later */
367 /* Check for valid target ID */
368 if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
369 -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
370 dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
371 dlthis->dfile_hdr.df_target_id, TARGET_ID);
374 /* Check for valid file format */
375 if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
376 dload_error(dlthis, "Bad DOFF version 0x%x",
377 dlthis->dfile_hdr.df_doff_version);
382 * Apply reasonableness checks to count fields
384 if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
385 dload_error(dlthis, "Excessive string table size " FMT_UI32,
386 dlthis->dfile_hdr.df_strtab_size);
389 if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
390 dload_error(dlthis, "Excessive section count 0x%x",
391 dlthis->dfile_hdr.df_no_scns);
394 #ifndef TARGET_ENDIANNESS
396 * Check that endianness does not disagree with explicit specification
398 if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
399 dlthis->myoptions & ENDIANNESS_MASK) {
401 "Input endianness disagrees with specified option");
404 dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
407 } /* dload_headers */
409 /* COFF Section Processing
411 * COFF sections are read in and retained intact. Each record is embedded
412 * in a new structure that records the updated load and
413 * run addresses of the section */
415 static const char secn_errid[] = { "section" };
417 /*************************************************************************
418 * Procedure dload_sections
424 * Loads the section records into an internal table.
425 *********************************************************************** */
426 void dload_sections(struct dload_state *dlthis)
429 struct doff_scnhdr_t *shp;
430 unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
432 /* allocate space for the DOFF section records */
433 siz = nsecs * sizeof(struct doff_scnhdr_t);
435 (struct doff_scnhdr_t *)dlthis->mysym->dload_allocate(dlthis->mysym,
437 if (!shp) { /* not enough storage */
438 DL_ERROR(err_alloc, siz);
441 dlthis->sect_hdrs = shp;
443 /* read in the section records */
444 if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
445 DL_ERROR(readstrm, secn_errid);
449 /* if we need to fix up byte order, do it now */
450 if (dlthis->reorder_map)
451 dload_reorder(shp, siz, dlthis->reorder_map);
453 /* check for validity */
454 if (~dload_checksum(dlthis->sect_hdrs, siz) !=
455 dlthis->verify.dv_scn_rec_checksum) {
456 DL_ERROR(err_checksum, secn_errid);
460 } /* dload_sections */
462 /*****************************************************************************
463 * Procedure allocate_sections
466 * alloc target memory allocator class
469 * Assigns new (target) addresses for sections
470 **************************************************************************** */
471 static void allocate_sections(struct dload_state *dlthis)
473 u16 curr_sect, nsecs, siz;
474 struct doff_scnhdr_t *shp;
475 struct ldr_section_info *asecs;
476 struct my_handle *hndl;
477 nsecs = dlthis->dfile_hdr.df_no_scns;
480 if ((dlthis->myalloc == NULL) &&
481 (dlthis->dfile_hdr.df_target_scns > 0)) {
482 DL_ERROR("Arg 3 (alloc) required but NULL", 0);
486 * allocate space for the module handle, which we will keep for unload
487 * purposes include an additional section store for an auto-generated
488 * trampoline section in case we need it.
490 siz = (dlthis->dfile_hdr.df_target_scns + 1) *
491 sizeof(struct ldr_section_info) + MY_HANDLE_SIZE;
494 (struct my_handle *)dlthis->mysym->dload_allocate(dlthis->mysym,
496 if (!hndl) { /* not enough storage */
497 DL_ERROR(err_alloc, siz);
500 /* initialize the handle header */
501 hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
502 hndl->dm.hroot = NULL;
504 dlthis->myhandle = hndl; /* save away for return */
505 /* pointer to the section list of allocated sections */
506 dlthis->ldr_sections = asecs = hndl->secns;
507 /* * Insert names into all sections, make copies of
508 the sections we allocate */
509 shp = dlthis->sect_hdrs;
510 for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
511 u32 soffset = shp->ds_offset;
512 #if BITS_PER_AU <= BITS_PER_BYTE
513 /* attempt to insert the name of this section */
514 if (soffset < dlthis->dfile_hdr.df_strtab_size)
515 ((struct ldr_section_info *)shp)->name =
516 dlthis->str_head + soffset;
518 dload_error(dlthis, "Bad name offset in section %d",
520 ((struct ldr_section_info *)shp)->name = NULL;
523 /* allocate target storage for sections that require it */
524 if (ds_needs_allocation(shp)) {
525 *asecs = *(struct ldr_section_info *)shp;
526 asecs->context = 0; /* zero the context field */
527 #if BITS_PER_AU > BITS_PER_BYTE
528 asecs->name = unpack_name(dlthis, soffset);
529 dlthis->debug_string_size = soffset + dlthis->temp_len;
531 dlthis->debug_string_size = soffset;
533 if (dlthis->myalloc != NULL) {
534 if (!dlthis->myalloc->
535 dload_allocate(dlthis->myalloc, asecs,
536 ds_alignment(asecs->type))) {
537 dload_error(dlthis, tgtalloc,
538 asecs->name, asecs->size);
542 /* keep address deltas in original section table */
543 shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
544 shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
545 dlthis->allocated_secn_count += 1;
546 } /* allocate target storage */
550 #if BITS_PER_AU <= BITS_PER_BYTE
551 dlthis->debug_string_size +=
552 strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
554 } /* allocate sections */
556 /*************************************************************************
557 * Procedure section_table_free
563 * Frees any state used by the symbol table.
566 * This routine is not allowed to declare errors!
567 *********************************************************************** */
568 static void section_table_free(struct dload_state *dlthis)
570 struct doff_scnhdr_t *shp;
572 shp = dlthis->sect_hdrs;
574 dlthis->mysym->dload_deallocate(dlthis->mysym, shp);
576 } /* section_table_free */
578 /*************************************************************************
579 * Procedure dload_strings
582 * sec_names_only If true only read in the "section names"
583 * portion of the string table
586 * Loads the DOFF string table into memory. DOFF keeps all strings in a
587 * big unsorted array. We just read that array into memory in bulk.
588 *********************************************************************** */
589 static const char stringtbl[] = { "string table" };
591 void dload_strings(struct dload_state *dlthis, bool sec_names_only)
596 if (sec_names_only) {
597 ssiz = BYTE_TO_HOST(DOFF_ALIGN
598 (dlthis->dfile_hdr.df_scn_name_size));
600 ssiz = BYTE_TO_HOST(DOFF_ALIGN
601 (dlthis->dfile_hdr.df_strtab_size));
606 /* get some memory for the string table */
607 #if BITS_PER_AU > BITS_PER_BYTE
608 strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz +
612 strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz);
614 if (strbuf == NULL) {
615 DL_ERROR(err_alloc, ssiz);
618 dlthis->str_head = strbuf;
619 #if BITS_PER_AU > BITS_PER_BYTE
620 dlthis->str_temp = strbuf + ssiz;
622 /* read in the strings and verify them */
623 if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
625 DL_ERROR(readstrm, stringtbl);
627 /* if we need to fix up byte order, do it now */
629 if (dlthis->reorder_map)
630 dload_reorder(strbuf, ssiz, dlthis->reorder_map);
632 if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
633 dlthis->verify.dv_str_tab_checksum)) {
634 DL_ERROR(err_checksum, stringtbl);
637 if (dlthis->dfile_hdr.df_byte_reshuffle !=
638 HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
639 /* put strings in big-endian order, not in PC order */
640 dload_reorder(strbuf, ssiz,
641 HOST_BYTE_ORDER(dlthis->
642 dfile_hdr.df_byte_reshuffle));
644 if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
645 dlthis->verify.dv_str_tab_checksum)) {
646 DL_ERROR(err_checksum, stringtbl);
649 } /* dload_strings */
651 /*************************************************************************
652 * Procedure string_table_free
658 * Frees any state used by the string table.
661 * This routine is not allowed to declare errors!
662 ************************************************************************ */
663 static void string_table_free(struct dload_state *dlthis)
665 if (dlthis->str_head)
666 dlthis->mysym->dload_deallocate(dlthis->mysym,
669 } /* string_table_free */
672 * Symbol Table Maintenance Functions
674 * COFF symbols are read by dload_symbols(), which is called after
675 * sections have been allocated. Symbols which might be used in
676 * relocation (ie, not debug info) are retained in an internal temporary
677 * compressed table (type local_symbol). A particular symbol is recovered
678 * by index by calling dload_find_symbol(). dload_find_symbol
679 * reconstructs a more explicit representation (type SLOTVEC) which is
682 /* real size of debug header */
683 #define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
685 static const char sym_errid[] = { "symbol" };
687 /**************************************************************************
688 * Procedure dload_symbols
694 * Reads in symbols and retains ones that might be needed for relocation
696 *********************************************************************** */
697 /* size of symbol buffer no bigger than target data buffer, to limit stack
699 #define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
700 sizeof(struct doff_syment_t))
702 static void dload_symbols(struct dload_state *dlthis)
704 u32 sym_count, siz, dsiz, symbols_left;
706 struct local_symbol *sp;
707 struct dynload_symbol *symp;
708 struct dynload_symbol *newsym;
710 sym_count = dlthis->dfile_hdr.df_no_syms;
715 * We keep a local symbol table for all of the symbols in the input.
716 * This table contains only section & value info, as we do not have
717 * to do any name processing for locals. We reuse this storage
718 * as a temporary for .dllview record construction.
719 * Allocate storage for the whole table. Add 1 to the section count
720 * in case a trampoline section is auto-generated as well as the
721 * size of the trampoline section name so DLLView doens't get lost.
724 siz = sym_count * sizeof(struct local_symbol);
725 dsiz = DBG_HDR_SIZE +
726 (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
727 BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
729 siz = dsiz; /* larger of symbols and .dllview temp */
730 sp = (struct local_symbol *)dlthis->mysym->dload_allocate(dlthis->mysym,
733 DL_ERROR(err_alloc, siz);
736 dlthis->local_symtab = sp;
737 /* Read the symbols in the input, store them in the table, and post any
738 * globals to the global symbol table. In the process, externals
739 become defined from the global symbol table */
740 checks = dlthis->verify.dv_sym_tab_checksum;
741 symbols_left = sym_count;
742 do { /* read all symbols */
746 struct doff_syment_t *input_sym;
747 unsigned syms_in_buf;
748 struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
749 input_sym = my_sym_buf;
750 syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
751 MY_SYM_BUF_SIZ : symbols_left;
752 siz = syms_in_buf * sizeof(struct doff_syment_t);
753 if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
755 DL_ERROR(readstrm, sym_errid);
758 if (dlthis->reorder_map)
759 dload_reorder(input_sym, siz, dlthis->reorder_map);
761 checks += dload_checksum(input_sym, siz);
762 do { /* process symbols in buffer */
764 /* attempt to derive the name of this symbol */
766 if (input_sym->dn_offset > 0) {
767 #if BITS_PER_AU <= BITS_PER_BYTE
768 if ((u32) input_sym->dn_offset <
769 dlthis->dfile_hdr.df_strtab_size)
770 sname = dlthis->str_head +
771 BYTE_TO_HOST(input_sym->dn_offset);
774 "Bad name offset in symbol "
775 " %d", symbols_left);
777 sname = unpack_name(dlthis,
778 input_sym->dn_offset);
781 val = input_sym->dn_value;
783 sp->sclass = input_sym->dn_sclass;
784 sp->secnn = input_sym->dn_scnum;
785 /* if this is an undefined symbol,
786 * define it (or fail) now */
787 if (sp->secnn == DN_UNDEF) {
788 /* pointless for static undefined */
789 if (input_sym->dn_sclass != DN_EXT)
792 /* try to define symbol from previously
794 symp = dlthis->mysym->find_matching_symbol
795 (dlthis->mysym, sname);
798 ("Undefined external symbol %s",
802 val = delta = symp->value;
803 #ifdef ENABLE_TRAMP_DEBUG
804 dload_syms_error(dlthis->mysym,
805 "===> ext sym [%s] at %x",
811 /* symbol defined by this module */
813 /* symbol references a section */
814 if ((unsigned)sp->secnn <=
815 dlthis->allocated_secn_count) {
816 /* section was allocated */
817 struct doff_scnhdr_t *srefp =
818 &dlthis->sect_hdrs[sp->secnn - 1];
820 if (input_sym->dn_sclass ==
822 input_sym->dn_sclass == DN_EXTLAB) {
824 delta = srefp->ds_vaddr;
827 delta = srefp->ds_paddr;
833 /* This symbol is an absolute symbol */
834 if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
838 dlthis->mysym->find_matching_symbol(dlthis->
843 /* This absolute symbol is already defined. */
844 if (symp->value == input_sym->dn_value) {
845 /* If symbol values are equal, continue
846 * but don't add to the global symbol
854 /* If symbol values are not equal,
855 * return with redefinition error */
856 DL_ERROR("Absolute symbol %s is "
857 "defined multiple times with "
858 "different values", sname);
863 /* if this is a global symbol, post it to the
865 if (input_sym->dn_sclass == DN_EXT ||
866 input_sym->dn_sclass == DN_EXTLAB) {
867 /* Keep this global symbol for subsequent
868 * modules. Don't complain on error, to allow
869 * symbol API to suppress global symbols */
873 newsym = dlthis->mysym->add_to_symbol_table
874 (dlthis->mysym, sname,
875 (unsigned)dlthis->myhandle);
885 } while ((syms_in_buf -= 1) > 0); /* process sym in buf */
886 } while (symbols_left > 0); /* read all symbols */
888 dload_error(dlthis, "Checksum of symbols failed");
890 } /* dload_symbols */
892 /*****************************************************************************
893 * Procedure symbol_table_free
899 * Frees any state used by the symbol table.
902 * This routine is not allowed to declare errors!
903 **************************************************************************** */
904 static void symbol_table_free(struct dload_state *dlthis)
906 if (dlthis->local_symtab) {
907 if (dlthis->dload_errcount) { /* blow off our symbols */
908 dlthis->mysym->purge_symbol_table(dlthis->mysym,
912 dlthis->mysym->dload_deallocate(dlthis->mysym,
913 dlthis->local_symtab);
915 } /* symbol_table_free */
919 * The dynamic loader does .cinit interpretation. cload_cinit()
920 * acts as a special write-to-target function, in that it takes relocated
921 * data from the normal data flow, and interprets it as .cinit actions.
922 * Because the normal data flow does not necessarily process the whole
923 * .cinit section in one buffer, cload_cinit() must be prepared to
924 * interpret the data piecemeal. A state machine is used for this
928 /* The following are only for use by reloc.c and things it calls */
929 static const struct ldr_section_info cinit_info_init = { cinitname, 0, 0,
930 (ldr_addr)-1, 0, DLOAD_BSS, 0
933 /*************************************************************************
934 * Procedure cload_cinit
937 * ipacket Pointer to data packet to be loaded
940 * Interprets the data in the buffer as .cinit data, and performs the
941 * appropriate initializations.
942 *********************************************************************** */
943 static void cload_cinit(struct dload_state *dlthis,
944 struct image_packet_t *ipacket)
946 #if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
947 s32 init_count, left;
949 s16 init_count, left;
951 unsigned char *pktp = ipacket->img_data;
952 unsigned char *pktend = pktp + BYTE_TO_HOST_ROUND(ipacket->packet_size);
955 struct ldr_section_info cinit_info;
957 /* PROCESS ALL THE INITIALIZATION RECORDS THE BUFFER. */
959 left = pktend - pktp;
960 switch (dlthis->cinit_state) {
961 case CI_COUNT: /* count field */
962 if (left < TDATA_TO_HOST(CINIT_COUNT))
964 temp = dload_unpack(dlthis, (tgt_au_t *) pktp,
965 CINIT_COUNT * TDATA_AU_BITS, 0,
967 pktp += TDATA_TO_HOST(CINIT_COUNT);
968 /* negative signifies BSS table, zero means done */
970 dlthis->cinit_state = CI_DONE;
973 dlthis->cinit_count = temp;
974 dlthis->cinit_state = CI_ADDRESS;
976 #if CINIT_ALIGN < CINIT_ADDRESS
978 pktp -= TDATA_TO_HOST(CINIT_ALIGN);
979 /* back up pointer into space courtesy of caller */
980 *(uint16_t *) pktp = dlthis->cinit_addr;
981 /* stuff in saved bits !! FALL THRU !! */
983 case CI_ADDRESS: /* Address field for a copy packet */
984 if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
985 #if CINIT_ALIGN < CINIT_ADDRESS
986 if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
987 /* address broken into halves */
988 dlthis->cinit_addr = *(uint16_t *) pktp;
989 /* remember 1st half */
990 dlthis->cinit_state = CI_PARTADDRESS;
996 atmp = dload_unpack(dlthis, (tgt_au_t *) pktp,
997 CINIT_ADDRESS * TDATA_AU_BITS, 0,
999 pktp += TDATA_TO_HOST(CINIT_ADDRESS);
1000 #if CINIT_PAGE_BITS > 0
1001 dlthis->cinit_page = atmp &
1002 ((1 << CINIT_PAGE_BITS) - 1);
1003 atmp >>= CINIT_PAGE_BITS;
1005 dlthis->cinit_page = CINIT_DEFAULT_PAGE;
1007 dlthis->cinit_addr = atmp;
1008 dlthis->cinit_state = CI_COPY;
1010 case CI_COPY: /* copy bits to the target */
1011 init_count = HOST_TO_TDATA(left);
1012 if (init_count > dlthis->cinit_count)
1013 init_count = dlthis->cinit_count;
1014 if (init_count == 0)
1015 goto loopexit; /* get more bits */
1016 cinit_info = cinit_info_init;
1017 cinit_info.page = dlthis->cinit_page;
1018 if (!dlthis->myio->writemem(dlthis->myio, pktp,
1020 (dlthis->cinit_addr),
1022 TDATA_TO_HOST(init_count))) {
1023 dload_error(dlthis, initfail, "write",
1024 dlthis->cinit_addr);
1026 dlthis->cinit_count -= init_count;
1027 if (dlthis->cinit_count <= 0) {
1028 dlthis->cinit_state = CI_COUNT;
1029 init_count = (init_count + CINIT_ALIGN - 1) &
1031 /* align to next init */
1033 pktp += TDATA_TO_HOST(init_count);
1034 dlthis->cinit_addr += init_count;
1036 case CI_DONE: /* no more .cinit to do */
1038 } /* switch (cinit_state) */
1043 dload_error(dlthis, "%d bytes left over in cinit packet", left);
1044 dlthis->cinit_state = CI_DONE; /* left over bytes are bad */
1048 /* Functions to interface to reloc.c
1050 * reloc.c is the relocation module borrowed from the linker, with
1051 * minimal (we hope) changes for our purposes. cload_sect_data() invokes
1052 * this module on a section to relocate and load the image data for that
1053 * section. The actual read and write actions are supplied by the global
1057 /************************************************************************
1058 * Procedure relocate_packet
1061 * ipacket Pointer to an image packet to relocate
1064 * Performs the required relocations on the packet. Returns a checksum
1065 * of the relocation operations.
1066 *********************************************************************** */
1067 #define MY_RELOC_BUF_SIZ 8
1068 /* careful! exists at the same time as the image buffer */
1069 static int relocate_packet(struct dload_state *dlthis,
1070 struct image_packet_t *ipacket,
1071 u32 *checks, bool *tramps_generated)
1074 *tramps_generated = false;
1076 rnum = ipacket->num_relocs;
1077 do { /* all relocs */
1080 struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
1082 rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
1083 siz = rinbuf * sizeof(struct reloc_record_t);
1084 if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
1085 DL_ERROR(readstrm, "relocation");
1088 /* reorder the bytes if need be */
1089 if (dlthis->reorder_map)
1090 dload_reorder(rp, siz, dlthis->reorder_map);
1092 *checks += dload_checksum(rp, siz);
1094 /* perform the relocation operation */
1095 dload_relocate(dlthis, (tgt_au_t *) ipacket->img_data,
1096 rp, tramps_generated, false);
1099 } while ((rinbuf -= 1) > 0);
1100 } while (rnum > 0); /* all relocs */
1101 /* If trampoline(s) were generated, we need to do an update of the
1102 * trampoline copy of the packet since a 2nd phase relo will be done
1104 if (*tramps_generated == true) {
1105 dload_tramp_pkt_udpate(dlthis,
1106 (dlthis->image_secn -
1107 dlthis->ldr_sections),
1108 dlthis->image_offset, ipacket);
1112 } /* dload_read_reloc */
1114 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
1116 /* VERY dangerous */
1117 static const char imagepak[] = { "image packet" };
1119 /*************************************************************************
1120 * Procedure dload_data
1126 * Read image data from input file, relocate it, and download it to the
1128 *********************************************************************** */
1129 static void dload_data(struct dload_state *dlthis)
1132 struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
1133 struct ldr_section_info *lptr = dlthis->ldr_sections;
1134 #ifdef OPT_ZERO_COPY_LOADER
1135 bool zero_copy = false;
1140 struct image_packet_t ipacket;
1141 u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
1144 /* Indicates whether CINIT processing has occurred */
1145 bool cinit_processed = false;
1147 /* Loop through the sections and load them one at a time.
1149 for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
1151 if (ds_needs_download(sptr)) {
1153 ldr_addr image_offset = 0;
1154 /* set relocation info for this section */
1155 if (curr_sect < dlthis->allocated_secn_count)
1156 dlthis->delta_runaddr = sptr->ds_paddr;
1158 lptr = (struct ldr_section_info *)sptr;
1159 dlthis->delta_runaddr = 0;
1161 dlthis->image_secn = lptr;
1162 #if BITS_PER_AU > BITS_PER_BYTE
1163 lptr->name = unpack_name(dlthis, sptr->ds_offset);
1165 nip = sptr->ds_nipacks;
1166 while ((nip -= 1) >= 0) { /* process packets */
1170 bool tramp_generated = false;
1172 /* get the fixed header bits */
1173 if (dlthis->strm->read_buffer(dlthis->strm,
1177 DL_ERROR(readstrm, imagepak);
1180 /* reorder the header if need be */
1181 if (dlthis->reorder_map) {
1182 dload_reorder(&ibuf.ipacket, IPH_SIZE,
1183 dlthis->reorder_map);
1185 /* now read the rest of the packet */
1187 BYTE_TO_HOST(DOFF_ALIGN
1188 (ibuf.ipacket.packet_size));
1189 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
1190 DL_ERROR("Bad image packet size %d",
1195 #ifdef OPT_ZERO_COPY_LOADER
1197 if (!dload_check_type(sptr, DLOAD_CINIT) {
1198 dlthis->myio->writemem(dlthis->myio,
1203 zero_copy = (dest != ibuf.bufr);
1206 /* End of determination */
1208 if (dlthis->strm->read_buffer(dlthis->strm,
1212 DL_ERROR(readstrm, imagepak);
1215 ibuf.ipacket.img_data = dest;
1217 /* reorder the bytes if need be */
1218 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
1219 if (dlthis->reorder_map) {
1220 dload_reorder(dest, ipsize,
1221 dlthis->reorder_map);
1223 checks = dload_checksum(dest, ipsize);
1225 if (dlthis->dfile_hdr.df_byte_reshuffle !=
1226 TARGET_ORDER(REORDER_MAP
1227 (BYTE_RESHUFFLE_VALUE))) {
1228 /* put image bytes in big-endian order,
1230 dload_reorder(dest, ipsize,
1233 df_byte_reshuffle));
1235 #if TARGET_AU_BITS > 8
1236 checks = dload_reverse_checksum16(dest, ipsize);
1238 checks = dload_reverse_checksum(dest, ipsize);
1242 checks += dload_checksum(&ibuf.ipacket,
1244 /* relocate the image bits as needed */
1245 if (ibuf.ipacket.num_relocs) {
1246 dlthis->image_offset = image_offset;
1247 if (!relocate_packet(dlthis,
1251 return; /* serious error */
1254 DL_ERROR(err_checksum, imagepak);
1255 /* Only write the result to the target if no
1256 * trampoline was generated. Otherwise it
1257 *will be done during trampoline finalize. */
1259 if (tramp_generated == false) {
1261 /* stuff the result into target
1263 if (dload_check_type(sptr,
1267 cinit_processed = true;
1269 #ifdef OPT_ZERO_COPY_LOADER
1293 #ifdef OPT_ZERO_COPY_LOADER
1299 BYTE_TO_TADDR(ibuf.ipacket.packet_size);
1300 } /* process packets */
1301 /* if this is a BSS section, we may want to fill it */
1302 if (!dload_check_type(sptr, DLOAD_BSS))
1305 if (!(dlthis->myoptions & DLOAD_INITBSS))
1308 if (cinit_processed) {
1309 /* Don't clear BSS after load-time
1312 ("Zero-initialization at " FMT_UI32
1313 " after " "load-time initialization!",
1317 /* fill the .bss area */
1318 dlthis->myio->fillmem(dlthis->myio,
1319 TADDR_TO_HOST(lptr->load_addr),
1320 lptr, TADDR_TO_HOST(lptr->size),
1324 /* if DS_DOWNLOAD_MASK */
1325 /* If not loading, but BSS, zero initialize */
1326 if (!dload_check_type(sptr, DLOAD_BSS))
1329 if (!(dlthis->myoptions & DLOAD_INITBSS))
1332 if (curr_sect >= dlthis->allocated_secn_count)
1333 lptr = (struct ldr_section_info *)sptr;
1335 if (cinit_processed) {
1336 /*Don't clear BSS after load-time initialization */
1337 DL_ERROR("Zero-initialization at " FMT_UI32
1339 "load-time initialization!", lptr->load_addr);
1342 /* fill the .bss area */
1343 dlthis->myio->fillmem(dlthis->myio,
1344 TADDR_TO_HOST(lptr->load_addr), lptr,
1345 TADDR_TO_HOST(lptr->size),
1350 } /* load sections */
1352 /* Finalize any trampolines that were created during the load */
1353 if (dload_tramp_finalize(dlthis) == 0) {
1354 DL_ERROR("Finalization of auto-trampolines (size = " FMT_UI32
1355 ") failed", dlthis->tramp.tramp_sect_next_addr);
1359 /*************************************************************************
1360 * Procedure dload_reorder
1363 * data 32-bit aligned pointer to data to be byte-swapped
1364 * dsiz size of the data to be reordered in sizeof() units.
1365 * map 32-bit map defining how to reorder the data. Value
1366 * must be REORDER_MAP() of some permutation
1370 * Re-arranges the bytes in each word according to the map specified.
1372 *********************************************************************** */
1373 /* mask for byte shift count */
1374 #define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
1376 void dload_reorder(void *data, int dsiz, unsigned int map)
1378 register u32 tmp, tmap, datv;
1379 u32 *dp = (u32 *) data;
1381 map <<= LOG_BITS_PER_BYTE; /* align map with SHIFT_COUNT_MASK */
1387 tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
1388 tmap >>= BITS_PER_BYTE;
1389 } while (datv >>= BITS_PER_BYTE);
1391 } while ((dsiz -= sizeof(u32)) > 0);
1392 } /* dload_reorder */
1394 /*************************************************************************
1395 * Procedure dload_checksum
1398 * data 32-bit aligned pointer to data to be checksummed
1399 * siz size of the data to be checksummed in sizeof() units.
1402 * Returns a checksum of the specified block
1404 *********************************************************************** */
1405 u32 dload_checksum(void *data, unsigned siz)
1413 for (left = siz; left > 0; left -= sizeof(u32))
1416 } /* dload_checksum */
1419 /*************************************************************************
1420 * Procedure dload_reverse_checksum
1423 * data 32-bit aligned pointer to data to be checksummed
1424 * siz size of the data to be checksummed in sizeof() units.
1427 * Returns a checksum of the specified block, which is assumed to be bytes
1428 * in big-endian order.
1431 * In a big-endian host, things like the string table are stored as bytes
1432 * in host order. But dllcreate always checksums in little-endian order.
1433 * It is most efficient to just handle the difference a word at a time.
1435 ********************************************************************** */
1436 u32 dload_reverse_checksum(void *data, unsigned siz)
1445 for (left = siz; left > 0; left -= sizeof(u32)) {
1447 sum += temp << BITS_PER_BYTE * 3;
1448 sum += temp >> BITS_PER_BYTE * 3;
1449 sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
1450 sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
1454 } /* dload_reverse_checksum */
1456 #if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
1457 u32 dload_reverse_checksum16(void *data, unsigned siz)
1459 uint_fast32_t sum, temp;
1466 for (left = siz; left > 0; left -= sizeof(u32)) {
1468 sum += temp << BITS_PER_BYTE * 2;
1469 sum += temp >> BITS_PER_BYTE * 2;
1473 } /* dload_reverse_checksum16 */
1477 /*************************************************************************
1478 * Procedure swap_words
1481 * data 32-bit aligned pointer to data to be swapped
1482 * siz size of the data to be swapped.
1483 * bitmap Bit map of how to swap each 32-bit word; 1 => 2 shorts,
1487 * Swaps the specified data according to the specified map
1489 *********************************************************************** */
1490 static void swap_words(void *data, unsigned siz, unsigned bitmap)
1493 #if TARGET_AU_BITS < 16
1500 #if TARGET_AU_BITS < 16
1501 /* pass 1: do all the bytes */
1507 *sp++ = SWAP16BY8(tmp);
1508 } while ((i -= 1) > 0);
1511 #if TARGET_AU_BITS < 32
1512 /* pass 2: fixup the 32-bit words */
1516 if ((bitmap & 1) == 0) {
1519 *lp = SWAP32BY16(tmp);
1523 } while ((i -= 1) > 0);
1527 /*************************************************************************
1528 * Procedure copy_tgt_strings
1531 * dstp Destination address. Assumed to be 32-bit aligned
1532 * srcp Source address. Assumed to be 32-bit aligned
1533 * charcount Number of characters to copy.
1536 * Copies strings from the source (which is in usual .dof file order on
1537 * the loading processor) to the destination buffer (which should be in proper
1538 * target addressable unit order). Makes sure the last string in the
1539 * buffer is NULL terminated (for safety).
1540 * Returns the first unused destination address.
1541 *********************************************************************** */
1542 static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
1544 register tgt_au_t *src = (tgt_au_t *) srcp;
1545 register tgt_au_t *dst = (tgt_au_t *) dstp;
1546 register int cnt = charcount;
1548 #if TARGET_AU_BITS <= BITS_PER_AU
1549 /* byte-swapping issues may exist for strings on target */
1554 } while ((cnt -= (sizeof(tgt_au_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
1555 /*apply force to make sure that the string table has null terminator */
1556 #if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
1560 dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1;
1563 } /* copy_tgt_strings */
1565 /*************************************************************************
1566 * Procedure init_module_handle
1572 * Initializes the module handle we use to enable unloading, and installs
1573 * the debug information required by the target.
1576 * The handle returned from dynamic_load_module needs to encapsulate all the
1577 * allocations done for the module, and enable them plus the modules symbols to
1580 *********************************************************************** */
1582 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1583 (ldr_addr)-1, DBG_LIST_PAGE, DLOAD_DATA, 0
1586 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1587 (ldr_addr)-1, DLOAD_DATA, DBG_LIST_PAGE, 0
1590 static void init_module_handle(struct dload_state *dlthis)
1592 struct my_handle *hndl;
1594 struct ldr_section_info *asecs;
1595 struct dll_module *dbmod;
1596 struct dll_sect *dbsec;
1597 struct dbg_mirror_root *mlist;
1599 struct modules_header mhdr;
1600 struct ldr_section_info dllview_info;
1601 struct dynload_symbol *debug_mirror_sym;
1602 hndl = dlthis->myhandle;
1604 return; /* must be errors detected, so forget it */
1606 /* Store the section count */
1607 hndl->secn_count = dlthis->allocated_secn_count;
1609 /* If a trampoline section was created, add it in */
1610 if (dlthis->tramp.tramp_sect_next_addr != 0)
1611 hndl->secn_count += 1;
1613 hndl->secn_count = hndl->secn_count << 1;
1615 hndl->secn_count = dlthis->allocated_secn_count << 1;
1616 #ifndef TARGET_ENDIANNESS
1617 if (dlthis->big_e_target)
1618 hndl->secn_count += 1; /* flag for big-endian */
1620 if (dlthis->dload_errcount)
1621 return; /* abandon if errors detected */
1622 /* Locate the symbol that names the header for the CCS debug list
1623 of modules. If not found, we just don't generate the debug record.
1624 If found, we create our modules list. We make sure to create the
1625 loader_dllview_root even if there is no relocation info to record,
1626 just to try to put both symbols in the same symbol table and
1628 debug_mirror_sym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1629 loader_dllview_root);
1630 if (!debug_mirror_sym) {
1631 struct dynload_symbol *dlmodsym;
1632 struct dbg_mirror_root *mlst;
1634 /* our root symbol is not yet present;
1635 check if we have DLModules defined */
1636 dlmodsym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1637 LINKER_MODULES_HEADER);
1639 return; /* no DLModules list so no debug info */
1640 /* if we have DLModules defined, construct our header */
1641 mlst = (struct dbg_mirror_root *)
1642 dlthis->mysym->dload_allocate(dlthis->mysym,
1646 DL_ERROR(err_alloc, sizeof(struct dbg_mirror_root));
1652 mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
1653 /* add our root symbol */
1654 debug_mirror_sym = dlthis->mysym->add_to_symbol_table
1655 (dlthis->mysym, loader_dllview_root,
1656 (unsigned)dlthis->myhandle);
1657 if (!debug_mirror_sym) {
1658 /* failed, recover memory */
1659 dlthis->mysym->dload_deallocate(dlthis->mysym, mlst);
1662 debug_mirror_sym->value = (u32) mlst;
1664 /* First create the DLLview record and stuff it into the buffer.
1665 Then write it to the DSP. Record pertinent locations in our hndl,
1666 and add it to the per-processor list of handles with debug info. */
1667 #ifndef DEBUG_HEADER_IN_LOADER
1668 mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
1672 mlist = (struct dbg_mirror_root *)&debug_list_header;
1674 hndl->dm.hroot = mlist; /* set pointer to root into our handle */
1675 if (!dlthis->allocated_secn_count)
1676 return; /* no load addresses to be recorded */
1677 /* reuse temporary symbol storage */
1678 dbmod = (struct dll_module *)dlthis->local_symtab;
1679 /* Create the DLLview record in the memory we retain for our handle */
1680 dbmod->num_sects = dlthis->allocated_secn_count;
1681 dbmod->timestamp = dlthis->verify.dv_timdat;
1682 dbmod->version = INIT_VERSION;
1683 dbmod->verification = VERIFICATION;
1684 asecs = dlthis->ldr_sections;
1685 dbsec = dbmod->sects;
1686 for (curr_sect = dlthis->allocated_secn_count;
1687 curr_sect > 0; curr_sect -= 1) {
1688 dbsec->sect_load_adr = asecs->load_addr;
1689 dbsec->sect_run_adr = asecs->run_addr;
1694 /* If a trampoline section was created go ahead and add its info */
1695 if (dlthis->tramp.tramp_sect_next_addr != 0) {
1697 dbsec->sect_load_adr = asecs->load_addr;
1698 dbsec->sect_run_adr = asecs->run_addr;
1703 /* now cram in the names */
1704 cp = copy_tgt_strings(dbsec, dlthis->str_head,
1705 dlthis->debug_string_size);
1707 /* If a trampoline section was created, add its name so DLLView
1708 * can show the user the section info. */
1709 if (dlthis->tramp.tramp_sect_next_addr != 0) {
1710 cp = copy_tgt_strings(cp,
1711 dlthis->tramp.final_string_table,
1712 strlen(dlthis->tramp.final_string_table) +
1716 /* round off the size of the debug record, and remember same */
1717 hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
1718 *cp = 0; /* strictly to make our test harness happy */
1719 dllview_info = dllview_info_init;
1720 dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1721 /* Initialize memory context to default heap */
1722 dllview_info.context = 0;
1723 hndl->dm.context = 0;
1724 /* fill in next pointer and size */
1726 dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
1727 dbmod->next_module_size = mlist->hnext->dm.dbsiz;
1729 dbmod->next_module_size = 0;
1730 dbmod->next_module = 0;
1732 /* allocate memory for on-DSP DLLview debug record */
1733 if (!dlthis->myalloc)
1735 if (!dlthis->myalloc->dload_allocate(dlthis->myalloc, &dllview_info,
1736 HOST_TO_TADDR(sizeof(u32)))) {
1739 /* Store load address of .dllview section */
1740 hndl->dm.dbthis = dllview_info.load_addr;
1741 /* Store memory context (segid) in which .dllview section
1743 hndl->dm.context = dllview_info.context;
1744 mlist->refcount += 1;
1745 /* swap bytes in the entire debug record, but not the string table */
1746 if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1747 swap_words(dbmod, (char *)dbsec - (char *)dbmod,
1750 /* Update the DLLview list on the DSP write new record */
1751 if (!dlthis->myio->writemem(dlthis->myio, dbmod,
1752 dllview_info.load_addr, &dllview_info,
1753 TADDR_TO_HOST(dllview_info.size))) {
1756 /* write new header */
1757 mhdr.first_module_size = hndl->dm.dbsiz;
1758 mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
1759 /* swap bytes in the module header, if needed */
1760 if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1761 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1762 MODULES_HEADER_BITMAP);
1764 dllview_info = dllview_info_init;
1765 if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
1767 sizeof(struct modules_header) -
1771 /* Add the module handle to this processor's list
1772 of handles with debug info */
1773 hndl->dm.hnext = mlist->hnext;
1775 hndl->dm.hnext->dm.hprev = hndl;
1776 hndl->dm.hprev = (struct my_handle *)mlist;
1777 mlist->hnext = hndl; /* insert after root */
1778 } /* init_module_handle */
1780 /*************************************************************************
1781 * Procedure dynamic_unload_module
1784 * mhandle A module handle from dynamic_load_module
1785 * syms Host-side symbol table and malloc/free functions
1786 * alloc Target-side memory allocation
1789 * The module specified by mhandle is unloaded. Unloading causes all
1790 * target memory to be deallocated, all symbols defined by the module to
1791 * be purged, and any host-side storage used by the dynamic loader for
1792 * this module to be released.
1795 * Zero for success. On error, the number of errors detected is returned.
1796 * Individual errors are reported using syms->error_report().
1797 *********************************************************************** */
1798 int dynamic_unload_module(void *mhandle,
1799 struct dynamic_loader_sym *syms,
1800 struct dynamic_loader_allocate *alloc,
1801 struct dynamic_loader_initialize *init)
1804 struct ldr_section_info *asecs;
1805 struct my_handle *hndl;
1806 struct dbg_mirror_root *root;
1807 unsigned errcount = 0;
1808 struct ldr_section_info dllview_info = dllview_info_init;
1809 struct modules_header mhdr;
1811 hndl = (struct my_handle *)mhandle;
1813 return 0; /* if handle is null, nothing to do */
1814 /* Clear out the module symbols
1815 * Note that if this is the module that defined MODULES_HEADER
1816 (the head of the target debug list)
1817 * then this operation will blow away that symbol.
1818 It will therefore be impossible for subsequent
1819 * operations to add entries to this un-referenceable list. */
1822 syms->purge_symbol_table(syms, (unsigned)hndl);
1823 /* Deallocate target memory for sections
1824 * NOTE: The trampoline section, if created, gets deleted here, too */
1826 asecs = hndl->secns;
1828 for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
1831 alloc->dload_deallocate(alloc, asecs++);
1833 root = hndl->dm.hroot;
1835 /* there is a debug list containing this module */
1838 if (!hndl->dm.dbthis) { /* target-side dllview record exists */
1841 /* Retrieve memory context in which .dllview was allocated */
1842 dllview_info.context = hndl->dm.context;
1843 if (hndl->dm.hprev == hndl)
1846 /* target-side dllview record is in list */
1847 /* dequeue this record from our GPP-side mirror list */
1848 hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
1850 hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
1851 /* Update next_module of previous entry in target list
1852 * We are using mhdr here as a surrogate for either a
1853 struct modules_header or a dll_module */
1854 if (hndl->dm.hnext) {
1855 mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
1856 mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
1858 mhdr.first_module = 0;
1859 mhdr.first_module_size = 0;
1864 if (!init->connect(init)) {
1865 dload_syms_error(syms, iconnect);
1869 /* swap bytes in the module header, if needed */
1870 if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
1871 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1872 MODULES_HEADER_BITMAP);
1874 if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
1875 &dllview_info, sizeof(struct modules_header) -
1876 sizeof(mhdr.update_flag))) {
1877 dload_syms_error(syms, dlvwrite);
1880 /* update change counter */
1882 if (!init->writemem(init, &(root->changes),
1883 root->dbthis + HOST_TO_TADDR
1884 (sizeof(mhdr.first_module) +
1885 sizeof(mhdr.first_module_size)),
1886 &dllview_info, sizeof(mhdr.update_flag))) {
1887 dload_syms_error(syms, dlvwrite);
1890 init->release(init);
1892 /* release target storage */
1893 dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1894 dllview_info.load_addr = hndl->dm.dbthis;
1896 alloc->dload_deallocate(alloc, &dllview_info);
1897 root->refcount -= 1;
1898 /* target-side dllview record exists */
1900 #ifndef DEBUG_HEADER_IN_LOADER
1901 if (root->refcount <= 0) {
1902 /* if all references gone, blow off the header */
1903 /* our root symbol may be gone due to the Purge above,
1904 but if not, do not destroy the root */
1905 if (syms->find_matching_symbol
1906 (syms, loader_dllview_root) == NULL)
1907 syms->dload_deallocate(syms, root);
1911 /* there is a debug list containing this module */
1912 syms->dload_deallocate(syms, mhandle); /* release our storage */
1914 } /* dynamic_unload_module */
1916 #if BITS_PER_AU > BITS_PER_BYTE
1917 /*************************************************************************
1918 * Procedure unpack_name
1921 * soffset Byte offset into the string table
1924 * Returns a pointer to the string specified by the offset supplied, or
1927 *********************************************************************** */
1928 static char *unpack_name(struct dload_state *dlthis, u32 soffset)
1933 if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
1934 dload_error(dlthis, "Bad string table offset " FMT_UI32,
1938 src = (uint_least8_t *) dlthis->str_head +
1939 (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
1940 dst = dlthis->str_temp;
1942 *dst++ = *src++; /* only 1 character in first word */
1945 *dst = (tmp >> BITS_PER_BYTE);
1948 } while ((*dst++ = tmp & BYTE_MASK));
1949 dlthis->temp_len = dst - dlthis->str_temp;
1950 /* squirrel away length including terminating null */
1951 return dlthis->str_temp;