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.
17 #include <linux/slab.h>
21 #include "module_list.h"
22 #define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
27 static void dload_symbols(struct dload_state *dlthis);
28 static void dload_data(struct dload_state *dlthis);
29 static void allocate_sections(struct dload_state *dlthis);
30 static void string_table_free(struct dload_state *dlthis);
31 static void symbol_table_free(struct dload_state *dlthis);
32 static void section_table_free(struct dload_state *dlthis);
33 static void init_module_handle(struct dload_state *dlthis);
34 #if BITS_PER_AU > BITS_PER_BYTE
35 static char *unpack_name(struct dload_state *dlthis, u32 soffset);
38 static const char cinitname[] = { ".cinit" };
39 static const char loader_dllview_root[] = { "?DLModules?" };
44 static const char readstrm[] = { "Error reading %s from input stream" };
45 static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
46 static const char tgtalloc[] = {
47 "Target memory allocate failed, section %s size " FMT_UI32 };
48 static const char initfail[] = { "%s to target address " FMT_UI32 " failed" };
49 static const char dlvwrite[] = { "Write to DLLview list failed" };
50 static const char iconnect[] = { "Connect call to init interface failed" };
51 static const char err_checksum[] = { "Checksum failed on %s" };
53 /*************************************************************************
54 * Procedure dload_error
57 * errtxt description of the error, printf style
58 * ... additional information
61 * Reports or records the error as appropriate.
62 *********************************************************************** */
63 void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
67 va_start(args, errtxt);
68 dlthis->mysym->error_report(dlthis->mysym, errtxt, args);
70 dlthis->dload_errcount += 1;
74 #define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
76 /*************************************************************************
77 * Procedure dload_syms_error
80 * errtxt description of the error, printf style
81 * ... additional information
84 * Reports or records the error as appropriate.
85 *********************************************************************** */
86 void dload_syms_error(struct dynamic_loader_sym *syms, const char *errtxt, ...)
90 va_start(args, errtxt);
91 syms->error_report(syms, errtxt, args);
95 /*************************************************************************
96 * Procedure dynamic_load_module
99 * module The input stream that supplies the module image
100 * syms Host-side symbol table and malloc/free functions
101 * alloc Target-side memory allocation
102 * init Target-side memory initialization
103 * options Option flags DLOAD_*
104 * mhandle A module handle for use with Dynamic_Unload
107 * The module image is read using *module. Target storage for the new
109 * obtained from *alloc. Symbols defined and referenced by the module are
110 * managed using *syms. The image is then relocated and references
111 * resolved as necessary, and the resulting executable bits are placed
112 * into target memory using *init.
115 * On a successful load, a module handle is placed in *mhandle,
116 * and zero is returned. On error, the number of errors detected is
117 * returned. Individual errors are reported during the load process
118 * using syms->error_report().
119 ********************************************************************** */
120 int dynamic_load_module(struct dynamic_loader_stream *module,
121 struct dynamic_loader_sym *syms,
122 struct dynamic_loader_allocate *alloc,
123 struct dynamic_loader_initialize *init,
124 unsigned options, void **mhandle)
126 register unsigned *dp, sz;
127 struct dload_state dl_state; /* internal state for this call */
129 /* blast our internal state */
130 dp = (unsigned *)&dl_state;
131 for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
134 /* Enable _only_ BSS initialization if enabled by user */
135 if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
136 dl_state.myoptions = DLOAD_INITBSS;
138 /* Check that mandatory arguments are present */
139 if (!module || !syms) {
140 dload_error(&dl_state, "Required parameter is NULL");
142 dl_state.strm = module;
143 dl_state.mysym = syms;
144 dload_headers(&dl_state);
145 if (!dl_state.dload_errcount)
146 dload_strings(&dl_state, false);
147 if (!dl_state.dload_errcount)
148 dload_sections(&dl_state);
150 if (init && !dl_state.dload_errcount) {
151 if (init->connect(init)) {
152 dl_state.myio = init;
153 dl_state.myalloc = alloc;
154 /* do now, before reducing symbols */
155 allocate_sections(&dl_state);
157 dload_error(&dl_state, iconnect);
160 if (!dl_state.dload_errcount) {
161 /* fix up entry point address */
162 unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
163 if (sref < dl_state.allocated_secn_count)
164 dl_state.dfile_hdr.df_entrypt +=
165 dl_state.ldr_sections[sref].run_addr;
167 dload_symbols(&dl_state);
170 if (init && !dl_state.dload_errcount)
171 dload_data(&dl_state);
173 init_module_handle(&dl_state);
175 /* dl_state.myio is init or 0 at this point. */
177 if ((!dl_state.dload_errcount) &&
178 (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
179 (!init->execute(init,
180 dl_state.dfile_hdr.df_entrypt)))
181 dload_error(&dl_state, "Init->Execute Failed");
185 symbol_table_free(&dl_state);
186 section_table_free(&dl_state);
187 string_table_free(&dl_state);
188 dload_tramp_cleanup(&dl_state);
190 if (dl_state.dload_errcount) {
191 dynamic_unload_module(dl_state.myhandle, syms, alloc,
193 dl_state.myhandle = NULL;
198 *mhandle = dl_state.myhandle; /* give back the handle */
200 return dl_state.dload_errcount;
203 /*************************************************************************
204 * Procedure dynamic_open_module
207 * module The input stream that supplies the module image
208 * syms Host-side symbol table and malloc/free functions
209 * alloc Target-side memory allocation
210 * init Target-side memory initialization
211 * options Option flags DLOAD_*
212 * mhandle A module handle for use with Dynamic_Unload
215 * The module image is read using *module. Target storage for the new
217 * obtained from *alloc. Symbols defined and referenced by the module are
218 * managed using *syms. The image is then relocated and references
219 * resolved as necessary, and the resulting executable bits are placed
220 * into target memory using *init.
223 * On a successful load, a module handle is placed in *mhandle,
224 * and zero is returned. On error, the number of errors detected is
225 * returned. Individual errors are reported during the load process
226 * using syms->error_report().
227 ********************************************************************** */
229 dynamic_open_module(struct dynamic_loader_stream *module,
230 struct dynamic_loader_sym *syms,
231 struct dynamic_loader_allocate *alloc,
232 struct dynamic_loader_initialize *init,
233 unsigned options, void **mhandle)
235 register unsigned *dp, sz;
236 struct dload_state dl_state; /* internal state for this call */
238 /* blast our internal state */
239 dp = (unsigned *)&dl_state;
240 for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
243 /* Enable _only_ BSS initialization if enabled by user */
244 if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
245 dl_state.myoptions = DLOAD_INITBSS;
247 /* Check that mandatory arguments are present */
248 if (!module || !syms) {
249 dload_error(&dl_state, "Required parameter is NULL");
251 dl_state.strm = module;
252 dl_state.mysym = syms;
253 dload_headers(&dl_state);
254 if (!dl_state.dload_errcount)
255 dload_strings(&dl_state, false);
256 if (!dl_state.dload_errcount)
257 dload_sections(&dl_state);
259 if (init && !dl_state.dload_errcount) {
260 if (init->connect(init)) {
261 dl_state.myio = init;
262 dl_state.myalloc = alloc;
263 /* do now, before reducing symbols */
264 allocate_sections(&dl_state);
266 dload_error(&dl_state, iconnect);
269 if (!dl_state.dload_errcount) {
270 /* fix up entry point address */
271 unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
272 if (sref < dl_state.allocated_secn_count)
273 dl_state.dfile_hdr.df_entrypt +=
274 dl_state.ldr_sections[sref].run_addr;
276 dload_symbols(&dl_state);
279 init_module_handle(&dl_state);
281 /* dl_state.myio is either 0 or init at this point. */
283 if ((!dl_state.dload_errcount) &&
284 (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
285 (!init->execute(init,
286 dl_state.dfile_hdr.df_entrypt)))
287 dload_error(&dl_state, "Init->Execute Failed");
291 symbol_table_free(&dl_state);
292 section_table_free(&dl_state);
293 string_table_free(&dl_state);
295 if (dl_state.dload_errcount) {
296 dynamic_unload_module(dl_state.myhandle, syms, alloc,
298 dl_state.myhandle = NULL;
303 *mhandle = dl_state.myhandle; /* give back the handle */
305 return dl_state.dload_errcount;
308 /*************************************************************************
309 * Procedure dload_headers
315 * Loads the DOFF header and verify record. Deals with any byte-order
316 * issues and checks them for validity.
317 *********************************************************************** */
318 #define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
319 sizeof(struct doff_verify_rec_t))
321 void dload_headers(struct dload_state *dlthis)
325 /* Read the header and the verify record as one. If we don't get it
327 if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
328 COMBINED_HEADER_SIZE) !=
329 COMBINED_HEADER_SIZE) {
330 DL_ERROR(readstrm, "File Headers");
334 * Verify that we have the byte order of the file correct.
335 * If not, must fix it before we can continue
337 map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
338 if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
339 /* input is either byte-shuffled or bad */
340 if ((map & 0xFCFCFCFC) == 0) { /* no obviously bogus bits */
341 dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
344 if (dlthis->dfile_hdr.df_byte_reshuffle !=
345 BYTE_RESHUFFLE_VALUE) {
346 /* didn't fix the problem, the byte swap map is bad */
348 "Bad byte swap map " FMT_UI32 " in header",
349 dlthis->dfile_hdr.df_byte_reshuffle);
352 dlthis->reorder_map = map; /* keep map for future use */
356 * Verify checksum of header and verify record
358 if (~dload_checksum(&dlthis->dfile_hdr,
359 sizeof(struct doff_filehdr_t)) ||
360 ~dload_checksum(&dlthis->verify,
361 sizeof(struct doff_verify_rec_t))) {
362 DL_ERROR(err_checksum, "header or verify record");
366 dlthis->dfile_hdr.df_byte_reshuffle = map; /* put back for later */
369 /* Check for valid target ID */
370 if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
371 -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
372 dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
373 dlthis->dfile_hdr.df_target_id, TARGET_ID);
376 /* Check for valid file format */
377 if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
378 dload_error(dlthis, "Bad DOFF version 0x%x",
379 dlthis->dfile_hdr.df_doff_version);
384 * Apply reasonableness checks to count fields
386 if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
387 dload_error(dlthis, "Excessive string table size " FMT_UI32,
388 dlthis->dfile_hdr.df_strtab_size);
391 if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
392 dload_error(dlthis, "Excessive section count 0x%x",
393 dlthis->dfile_hdr.df_no_scns);
396 #ifndef TARGET_ENDIANNESS
398 * Check that endianness does not disagree with explicit specification
400 if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
401 dlthis->myoptions & ENDIANNESS_MASK) {
403 "Input endianness disagrees with specified option");
406 dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
409 } /* dload_headers */
411 /* COFF Section Processing
413 * COFF sections are read in and retained intact. Each record is embedded
414 * in a new structure that records the updated load and
415 * run addresses of the section */
417 static const char secn_errid[] = { "section" };
419 /*************************************************************************
420 * Procedure dload_sections
426 * Loads the section records into an internal table.
427 *********************************************************************** */
428 void dload_sections(struct dload_state *dlthis)
431 struct doff_scnhdr_t *shp;
432 unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
434 /* allocate space for the DOFF section records */
435 siz = nsecs * sizeof(struct doff_scnhdr_t);
437 (struct doff_scnhdr_t *)dlthis->mysym->dload_allocate(dlthis->mysym,
439 if (!shp) { /* not enough storage */
440 DL_ERROR(err_alloc, siz);
443 dlthis->sect_hdrs = shp;
445 /* read in the section records */
446 if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
447 DL_ERROR(readstrm, secn_errid);
451 /* if we need to fix up byte order, do it now */
452 if (dlthis->reorder_map)
453 dload_reorder(shp, siz, dlthis->reorder_map);
455 /* check for validity */
456 if (~dload_checksum(dlthis->sect_hdrs, siz) !=
457 dlthis->verify.dv_scn_rec_checksum) {
458 DL_ERROR(err_checksum, secn_errid);
462 } /* dload_sections */
464 /*****************************************************************************
465 * Procedure allocate_sections
468 * alloc target memory allocator class
471 * Assigns new (target) addresses for sections
472 **************************************************************************** */
473 static void allocate_sections(struct dload_state *dlthis)
475 u16 curr_sect, nsecs, siz;
476 struct doff_scnhdr_t *shp;
477 struct ldr_section_info *asecs;
478 struct my_handle *hndl;
479 nsecs = dlthis->dfile_hdr.df_no_scns;
482 if ((dlthis->myalloc == NULL) &&
483 (dlthis->dfile_hdr.df_target_scns > 0)) {
484 DL_ERROR("Arg 3 (alloc) required but NULL", 0);
488 * allocate space for the module handle, which we will keep for unload
489 * purposes include an additional section store for an auto-generated
490 * trampoline section in case we need it.
492 siz = (dlthis->dfile_hdr.df_target_scns + 1) *
493 sizeof(struct ldr_section_info) + MY_HANDLE_SIZE;
496 (struct my_handle *)dlthis->mysym->dload_allocate(dlthis->mysym,
498 if (!hndl) { /* not enough storage */
499 DL_ERROR(err_alloc, siz);
502 /* initialize the handle header */
503 hndl->dm.next = hndl->dm.prev = hndl; /* circular list */
504 hndl->dm.root = NULL;
506 dlthis->myhandle = hndl; /* save away for return */
507 /* pointer to the section list of allocated sections */
508 dlthis->ldr_sections = asecs = hndl->secns;
509 /* * Insert names into all sections, make copies of
510 the sections we allocate */
511 shp = dlthis->sect_hdrs;
512 for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
513 u32 soffset = shp->ds_offset;
514 #if BITS_PER_AU <= BITS_PER_BYTE
515 /* attempt to insert the name of this section */
516 if (soffset < dlthis->dfile_hdr.df_strtab_size)
517 ((struct ldr_section_info *)shp)->name =
518 dlthis->str_head + soffset;
520 dload_error(dlthis, "Bad name offset in section %d",
522 ((struct ldr_section_info *)shp)->name = NULL;
525 /* allocate target storage for sections that require it */
526 if (ds_needs_allocation(shp)) {
527 *asecs = *(struct ldr_section_info *)shp;
528 asecs->context = 0; /* zero the context field */
529 #if BITS_PER_AU > BITS_PER_BYTE
530 asecs->name = unpack_name(dlthis, soffset);
531 dlthis->debug_string_size = soffset + dlthis->temp_len;
533 dlthis->debug_string_size = soffset;
535 if (dlthis->myalloc != NULL) {
536 if (!dlthis->myalloc->
537 dload_allocate(dlthis->myalloc, asecs,
538 ds_alignment(asecs->type))) {
539 dload_error(dlthis, tgtalloc,
540 asecs->name, asecs->size);
544 /* keep address deltas in original section table */
545 shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
546 shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
547 dlthis->allocated_secn_count += 1;
548 } /* allocate target storage */
552 #if BITS_PER_AU <= BITS_PER_BYTE
553 dlthis->debug_string_size +=
554 strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
556 } /* allocate sections */
558 /*************************************************************************
559 * Procedure section_table_free
565 * Frees any state used by the symbol table.
568 * This routine is not allowed to declare errors!
569 *********************************************************************** */
570 static void section_table_free(struct dload_state *dlthis)
572 struct doff_scnhdr_t *shp;
574 shp = dlthis->sect_hdrs;
576 dlthis->mysym->dload_deallocate(dlthis->mysym, shp);
578 } /* section_table_free */
580 /*************************************************************************
581 * Procedure dload_strings
584 * sec_names_only If true only read in the "section names"
585 * portion of the string table
588 * Loads the DOFF string table into memory. DOFF keeps all strings in a
589 * big unsorted array. We just read that array into memory in bulk.
590 *********************************************************************** */
591 static const char stringtbl[] = { "string table" };
593 void dload_strings(struct dload_state *dlthis, bool sec_names_only)
598 if (sec_names_only) {
599 ssiz = BYTE_TO_HOST(DOFF_ALIGN
600 (dlthis->dfile_hdr.df_scn_name_size));
602 ssiz = BYTE_TO_HOST(DOFF_ALIGN
603 (dlthis->dfile_hdr.df_strtab_size));
608 /* get some memory for the string table */
609 #if BITS_PER_AU > BITS_PER_BYTE
610 strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz +
614 strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz);
616 if (strbuf == NULL) {
617 DL_ERROR(err_alloc, ssiz);
620 dlthis->str_head = strbuf;
621 #if BITS_PER_AU > BITS_PER_BYTE
622 dlthis->str_temp = strbuf + ssiz;
624 /* read in the strings and verify them */
625 if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
627 DL_ERROR(readstrm, stringtbl);
629 /* if we need to fix up byte order, do it now */
631 if (dlthis->reorder_map)
632 dload_reorder(strbuf, ssiz, dlthis->reorder_map);
634 if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
635 dlthis->verify.dv_str_tab_checksum)) {
636 DL_ERROR(err_checksum, stringtbl);
639 if (dlthis->dfile_hdr.df_byte_reshuffle !=
640 HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
641 /* put strings in big-endian order, not in PC order */
642 dload_reorder(strbuf, ssiz,
643 HOST_BYTE_ORDER(dlthis->
644 dfile_hdr.df_byte_reshuffle));
646 if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
647 dlthis->verify.dv_str_tab_checksum)) {
648 DL_ERROR(err_checksum, stringtbl);
651 } /* dload_strings */
653 /*************************************************************************
654 * Procedure string_table_free
660 * Frees any state used by the string table.
663 * This routine is not allowed to declare errors!
664 ************************************************************************ */
665 static void string_table_free(struct dload_state *dlthis)
667 if (dlthis->str_head)
668 dlthis->mysym->dload_deallocate(dlthis->mysym,
671 } /* string_table_free */
674 * Symbol Table Maintenance Functions
676 * COFF symbols are read by dload_symbols(), which is called after
677 * sections have been allocated. Symbols which might be used in
678 * relocation (ie, not debug info) are retained in an internal temporary
679 * compressed table (type local_symbol). A particular symbol is recovered
680 * by index by calling dload_find_symbol(). dload_find_symbol
681 * reconstructs a more explicit representation (type SLOTVEC) which is
684 /* real size of debug header */
685 #define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
687 static const char sym_errid[] = { "symbol" };
689 /**************************************************************************
690 * Procedure dload_symbols
696 * Reads in symbols and retains ones that might be needed for relocation
698 *********************************************************************** */
699 /* size of symbol buffer no bigger than target data buffer, to limit stack
701 #define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
702 sizeof(struct doff_syment_t))
704 static void dload_symbols(struct dload_state *dlthis)
706 u32 sym_count, siz, dsiz, symbols_left;
708 struct local_symbol *sp;
709 struct dynload_symbol *symp;
710 struct dynload_symbol *newsym;
711 struct doff_syment_t *my_sym_buf;
713 sym_count = dlthis->dfile_hdr.df_no_syms;
718 * We keep a local symbol table for all of the symbols in the input.
719 * This table contains only section & value info, as we do not have
720 * to do any name processing for locals. We reuse this storage
721 * as a temporary for .dllview record construction.
722 * Allocate storage for the whole table. Add 1 to the section count
723 * in case a trampoline section is auto-generated as well as the
724 * size of the trampoline section name so DLLView doesn't get lost.
727 siz = sym_count * sizeof(struct local_symbol);
728 dsiz = DBG_HDR_SIZE +
729 (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
730 BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
732 siz = dsiz; /* larger of symbols and .dllview temp */
733 sp = (struct local_symbol *)dlthis->mysym->dload_allocate(dlthis->mysym,
736 DL_ERROR(err_alloc, siz);
739 dlthis->local_symtab = sp;
740 /* Read the symbols in the input, store them in the table, and post any
741 * globals to the global symbol table. In the process, externals
742 become defined from the global symbol table */
743 checks = dlthis->verify.dv_sym_tab_checksum;
744 symbols_left = sym_count;
746 my_sym_buf = kzalloc(sizeof(*my_sym_buf) * MY_SYM_BUF_SIZ, GFP_KERNEL);
750 do { /* read all symbols */
754 struct doff_syment_t *input_sym;
755 unsigned syms_in_buf;
757 input_sym = my_sym_buf;
758 syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
759 MY_SYM_BUF_SIZ : symbols_left;
760 siz = syms_in_buf * sizeof(struct doff_syment_t);
761 if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
763 DL_ERROR(readstrm, sym_errid);
766 if (dlthis->reorder_map)
767 dload_reorder(input_sym, siz, dlthis->reorder_map);
769 checks += dload_checksum(input_sym, siz);
770 do { /* process symbols in buffer */
772 /* attempt to derive the name of this symbol */
774 if (input_sym->dn_offset > 0) {
775 #if BITS_PER_AU <= BITS_PER_BYTE
776 if ((u32) input_sym->dn_offset <
777 dlthis->dfile_hdr.df_strtab_size)
778 sname = dlthis->str_head +
779 BYTE_TO_HOST(input_sym->dn_offset);
782 "Bad name offset in symbol "
783 " %d", symbols_left);
785 sname = unpack_name(dlthis,
786 input_sym->dn_offset);
789 val = input_sym->dn_value;
791 sp->sclass = input_sym->dn_sclass;
792 sp->secnn = input_sym->dn_scnum;
793 /* if this is an undefined symbol,
794 * define it (or fail) now */
795 if (sp->secnn == DN_UNDEF) {
796 /* pointless for static undefined */
797 if (input_sym->dn_sclass != DN_EXT)
800 /* try to define symbol from previously
802 symp = dlthis->mysym->find_matching_symbol
803 (dlthis->mysym, sname);
806 ("Undefined external symbol %s",
810 val = delta = symp->value;
811 #ifdef ENABLE_TRAMP_DEBUG
812 dload_syms_error(dlthis->mysym,
813 "===> ext sym [%s] at %x",
819 /* symbol defined by this module */
821 /* symbol references a section */
822 if ((unsigned)sp->secnn <=
823 dlthis->allocated_secn_count) {
824 /* section was allocated */
825 struct doff_scnhdr_t *srefp =
826 &dlthis->sect_hdrs[sp->secnn - 1];
828 if (input_sym->dn_sclass ==
830 input_sym->dn_sclass == DN_EXTLAB) {
832 delta = srefp->ds_vaddr;
835 delta = srefp->ds_paddr;
841 /* This symbol is an absolute symbol */
842 if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
846 dlthis->mysym->find_matching_symbol(dlthis->
851 /* This absolute symbol is already defined. */
852 if (symp->value == input_sym->dn_value) {
853 /* If symbol values are equal, continue
854 * but don't add to the global symbol
862 /* If symbol values are not equal,
863 * return with redefinition error */
864 DL_ERROR("Absolute symbol %s is "
865 "defined multiple times with "
866 "different values", sname);
871 /* if this is a global symbol, post it to the
873 if (input_sym->dn_sclass == DN_EXT ||
874 input_sym->dn_sclass == DN_EXTLAB) {
875 /* Keep this global symbol for subsequent
876 * modules. Don't complain on error, to allow
877 * symbol API to suppress global symbols */
881 newsym = dlthis->mysym->add_to_symbol_table
882 (dlthis->mysym, sname,
883 (unsigned)dlthis->myhandle);
893 } while ((syms_in_buf -= 1) > 0); /* process sym in buf */
894 } while (symbols_left > 0); /* read all symbols */
896 dload_error(dlthis, "Checksum of symbols failed");
901 } /* dload_symbols */
903 /*****************************************************************************
904 * Procedure symbol_table_free
910 * Frees any state used by the symbol table.
913 * This routine is not allowed to declare errors!
914 **************************************************************************** */
915 static void symbol_table_free(struct dload_state *dlthis)
917 if (dlthis->local_symtab) {
918 if (dlthis->dload_errcount) { /* blow off our symbols */
919 dlthis->mysym->purge_symbol_table(dlthis->mysym,
923 dlthis->mysym->dload_deallocate(dlthis->mysym,
924 dlthis->local_symtab);
926 } /* symbol_table_free */
930 * The dynamic loader does .cinit interpretation. cload_cinit()
931 * acts as a special write-to-target function, in that it takes relocated
932 * data from the normal data flow, and interprets it as .cinit actions.
933 * Because the normal data flow does not necessarily process the whole
934 * .cinit section in one buffer, cload_cinit() must be prepared to
935 * interpret the data piecemeal. A state machine is used for this
939 /* The following are only for use by reloc.c and things it calls */
940 static const struct ldr_section_info cinit_info_init = { cinitname, 0, 0,
941 (ldr_addr)-1, 0, DLOAD_BSS, 0
944 /*************************************************************************
945 * Procedure cload_cinit
948 * ipacket Pointer to data packet to be loaded
951 * Interprets the data in the buffer as .cinit data, and performs the
952 * appropriate initializations.
953 *********************************************************************** */
954 static void cload_cinit(struct dload_state *dlthis,
955 struct image_packet_t *ipacket)
957 #if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
958 s32 init_count, left;
960 s16 init_count, left;
962 unsigned char *pktp = ipacket->img_data;
963 unsigned char *pktend = pktp + BYTE_TO_HOST_ROUND(ipacket->packet_size);
966 struct ldr_section_info cinit_info;
968 /* PROCESS ALL THE INITIALIZATION RECORDS THE BUFFER. */
970 left = pktend - pktp;
971 switch (dlthis->cinit_state) {
972 case CI_COUNT: /* count field */
973 if (left < TDATA_TO_HOST(CINIT_COUNT))
975 temp = dload_unpack(dlthis, (tgt_au_t *) pktp,
976 CINIT_COUNT * TDATA_AU_BITS, 0,
978 pktp += TDATA_TO_HOST(CINIT_COUNT);
979 /* negative signifies BSS table, zero means done */
981 dlthis->cinit_state = CI_DONE;
984 dlthis->cinit_count = temp;
985 dlthis->cinit_state = CI_ADDRESS;
987 #if CINIT_ALIGN < CINIT_ADDRESS
989 pktp -= TDATA_TO_HOST(CINIT_ALIGN);
990 /* back up pointer into space courtesy of caller */
991 *(uint16_t *) pktp = dlthis->cinit_addr;
992 /* stuff in saved bits !! FALL THRU !! */
994 case CI_ADDRESS: /* Address field for a copy packet */
995 if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
996 #if CINIT_ALIGN < CINIT_ADDRESS
997 if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
998 /* address broken into halves */
999 dlthis->cinit_addr = *(uint16_t *) pktp;
1000 /* remember 1st half */
1001 dlthis->cinit_state = CI_PARTADDRESS;
1007 atmp = dload_unpack(dlthis, (tgt_au_t *) pktp,
1008 CINIT_ADDRESS * TDATA_AU_BITS, 0,
1010 pktp += TDATA_TO_HOST(CINIT_ADDRESS);
1011 #if CINIT_PAGE_BITS > 0
1012 dlthis->cinit_page = atmp &
1013 ((1 << CINIT_PAGE_BITS) - 1);
1014 atmp >>= CINIT_PAGE_BITS;
1016 dlthis->cinit_page = CINIT_DEFAULT_PAGE;
1018 dlthis->cinit_addr = atmp;
1019 dlthis->cinit_state = CI_COPY;
1021 case CI_COPY: /* copy bits to the target */
1022 init_count = HOST_TO_TDATA(left);
1023 if (init_count > dlthis->cinit_count)
1024 init_count = dlthis->cinit_count;
1025 if (init_count == 0)
1026 goto loopexit; /* get more bits */
1027 cinit_info = cinit_info_init;
1028 cinit_info.page = dlthis->cinit_page;
1029 if (!dlthis->myio->writemem(dlthis->myio, pktp,
1031 (dlthis->cinit_addr),
1033 TDATA_TO_HOST(init_count))) {
1034 dload_error(dlthis, initfail, "write",
1035 dlthis->cinit_addr);
1037 dlthis->cinit_count -= init_count;
1038 if (dlthis->cinit_count <= 0) {
1039 dlthis->cinit_state = CI_COUNT;
1040 init_count = (init_count + CINIT_ALIGN - 1) &
1042 /* align to next init */
1044 pktp += TDATA_TO_HOST(init_count);
1045 dlthis->cinit_addr += init_count;
1047 case CI_DONE: /* no more .cinit to do */
1049 } /* switch (cinit_state) */
1054 dload_error(dlthis, "%d bytes left over in cinit packet", left);
1055 dlthis->cinit_state = CI_DONE; /* left over bytes are bad */
1059 /* Functions to interface to reloc.c
1061 * reloc.c is the relocation module borrowed from the linker, with
1062 * minimal (we hope) changes for our purposes. cload_sect_data() invokes
1063 * this module on a section to relocate and load the image data for that
1064 * section. The actual read and write actions are supplied by the global
1068 /************************************************************************
1069 * Procedure relocate_packet
1072 * ipacket Pointer to an image packet to relocate
1075 * Performs the required relocations on the packet. Returns a checksum
1076 * of the relocation operations.
1077 *********************************************************************** */
1078 #define MY_RELOC_BUF_SIZ 8
1079 /* careful! exists at the same time as the image buffer */
1080 static int relocate_packet(struct dload_state *dlthis,
1081 struct image_packet_t *ipacket,
1082 u32 *checks, bool *tramps_generated)
1085 *tramps_generated = false;
1087 rnum = ipacket->num_relocs;
1088 do { /* all relocs */
1091 struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
1093 rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
1094 siz = rinbuf * sizeof(struct reloc_record_t);
1095 if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
1096 DL_ERROR(readstrm, "relocation");
1099 /* reorder the bytes if need be */
1100 if (dlthis->reorder_map)
1101 dload_reorder(rp, siz, dlthis->reorder_map);
1103 *checks += dload_checksum(rp, siz);
1105 /* perform the relocation operation */
1106 dload_relocate(dlthis, (tgt_au_t *) ipacket->img_data,
1107 rp, tramps_generated, false);
1110 } while ((rinbuf -= 1) > 0);
1111 } while (rnum > 0); /* all relocs */
1112 /* If trampoline(s) were generated, we need to do an update of the
1113 * trampoline copy of the packet since a 2nd phase relo will be done
1115 if (*tramps_generated == true) {
1116 dload_tramp_pkt_udpate(dlthis,
1117 (dlthis->image_secn -
1118 dlthis->ldr_sections),
1119 dlthis->image_offset, ipacket);
1123 } /* dload_read_reloc */
1125 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
1127 /* VERY dangerous */
1128 static const char imagepak[] = { "image packet" };
1131 struct image_packet_t ipacket;
1132 u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
1135 /*************************************************************************
1136 * Procedure dload_data
1142 * Read image data from input file, relocate it, and download it to the
1144 *********************************************************************** */
1145 static void dload_data(struct dload_state *dlthis)
1148 struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
1149 struct ldr_section_info *lptr = dlthis->ldr_sections;
1150 struct img_buffer *ibuf;
1153 /* Indicates whether CINIT processing has occurred */
1154 bool cinit_processed = false;
1156 ibuf = kzalloc(sizeof(*ibuf), GFP_KERNEL);
1160 /* Loop through the sections and load them one at a time.
1162 for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
1164 if (ds_needs_download(sptr)) {
1166 ldr_addr image_offset = 0;
1167 /* set relocation info for this section */
1168 if (curr_sect < dlthis->allocated_secn_count)
1169 dlthis->delta_runaddr = sptr->ds_paddr;
1171 lptr = (struct ldr_section_info *)sptr;
1172 dlthis->delta_runaddr = 0;
1174 dlthis->image_secn = lptr;
1175 #if BITS_PER_AU > BITS_PER_BYTE
1176 lptr->name = unpack_name(dlthis, sptr->ds_offset);
1178 nip = sptr->ds_nipacks;
1179 while ((nip -= 1) >= 0) { /* process packets */
1183 bool tramp_generated = false;
1185 /* get the fixed header bits */
1186 if (dlthis->strm->read_buffer(dlthis->strm,
1190 DL_ERROR(readstrm, imagepak);
1193 /* reorder the header if need be */
1194 if (dlthis->reorder_map) {
1195 dload_reorder(&ibuf->ipacket, IPH_SIZE,
1196 dlthis->reorder_map);
1198 /* now read the rest of the packet */
1200 BYTE_TO_HOST(DOFF_ALIGN
1201 (ibuf->ipacket.packet_size));
1202 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
1203 DL_ERROR("Bad image packet size %d",
1208 /* End of determination */
1210 if (dlthis->strm->read_buffer(dlthis->strm,
1214 DL_ERROR(readstrm, imagepak);
1217 ibuf->ipacket.img_data = dest;
1219 /* reorder the bytes if need be */
1220 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
1221 if (dlthis->reorder_map) {
1222 dload_reorder(dest, ipsize,
1223 dlthis->reorder_map);
1225 checks = dload_checksum(dest, ipsize);
1227 if (dlthis->dfile_hdr.df_byte_reshuffle !=
1228 TARGET_ORDER(REORDER_MAP
1229 (BYTE_RESHUFFLE_VALUE))) {
1230 /* put image bytes in big-endian order,
1232 dload_reorder(dest, ipsize,
1235 df_byte_reshuffle));
1237 #if TARGET_AU_BITS > 8
1238 checks = dload_reverse_checksum16(dest, ipsize);
1240 checks = dload_reverse_checksum(dest, ipsize);
1244 checks += dload_checksum(&ibuf->ipacket,
1246 /* relocate the image bits as needed */
1247 if (ibuf->ipacket.num_relocs) {
1248 dlthis->image_offset = image_offset;
1249 if (!relocate_packet(dlthis,
1253 goto free_ibuf; /* error */
1256 DL_ERROR(err_checksum, imagepak);
1257 /* Only write the result to the target if no
1258 * trampoline was generated. Otherwise it
1259 *will be done during trampoline finalize. */
1261 if (tramp_generated == false) {
1263 /* stuff the result into target
1265 if (dload_check_type(sptr,
1269 cinit_processed = true;
1295 BYTE_TO_TADDR(ibuf->ipacket.packet_size);
1296 } /* process packets */
1297 /* if this is a BSS section, we may want to fill it */
1298 if (!dload_check_type(sptr, DLOAD_BSS))
1301 if (!(dlthis->myoptions & DLOAD_INITBSS))
1304 if (cinit_processed) {
1305 /* Don't clear BSS after load-time
1308 ("Zero-initialization at " FMT_UI32
1309 " after " "load-time initialization!",
1313 /* fill the .bss area */
1314 dlthis->myio->fillmem(dlthis->myio,
1315 TADDR_TO_HOST(lptr->load_addr),
1316 lptr, TADDR_TO_HOST(lptr->size),
1320 /* if DS_DOWNLOAD_MASK */
1321 /* If not loading, but BSS, zero initialize */
1322 if (!dload_check_type(sptr, DLOAD_BSS))
1325 if (!(dlthis->myoptions & DLOAD_INITBSS))
1328 if (curr_sect >= dlthis->allocated_secn_count)
1329 lptr = (struct ldr_section_info *)sptr;
1331 if (cinit_processed) {
1332 /*Don't clear BSS after load-time initialization */
1333 DL_ERROR("Zero-initialization at " FMT_UI32
1335 "load-time initialization!", lptr->load_addr);
1338 /* fill the .bss area */
1339 dlthis->myio->fillmem(dlthis->myio,
1340 TADDR_TO_HOST(lptr->load_addr), lptr,
1341 TADDR_TO_HOST(lptr->size),
1346 } /* load sections */
1348 /* Finalize any trampolines that were created during the load */
1349 if (dload_tramp_finalize(dlthis) == 0) {
1350 DL_ERROR("Finalization of auto-trampolines (size = " FMT_UI32
1351 ") failed", dlthis->tramp.tramp_sect_next_addr);
1358 /*************************************************************************
1359 * Procedure dload_reorder
1362 * data 32-bit aligned pointer to data to be byte-swapped
1363 * dsiz size of the data to be reordered in sizeof() units.
1364 * map 32-bit map defining how to reorder the data. Value
1365 * must be REORDER_MAP() of some permutation
1369 * Re-arranges the bytes in each word according to the map specified.
1371 *********************************************************************** */
1372 /* mask for byte shift count */
1373 #define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
1375 void dload_reorder(void *data, int dsiz, unsigned int map)
1377 register u32 tmp, tmap, datv;
1378 u32 *dp = (u32 *) data;
1380 map <<= LOG_BITS_PER_BYTE; /* align map with SHIFT_COUNT_MASK */
1386 tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
1387 tmap >>= BITS_PER_BYTE;
1388 } while (datv >>= BITS_PER_BYTE);
1390 } while ((dsiz -= sizeof(u32)) > 0);
1391 } /* dload_reorder */
1393 /*************************************************************************
1394 * Procedure dload_checksum
1397 * data 32-bit aligned pointer to data to be checksummed
1398 * siz size of the data to be checksummed in sizeof() units.
1401 * Returns a checksum of the specified block
1403 *********************************************************************** */
1404 u32 dload_checksum(void *data, unsigned siz)
1412 for (left = siz; left > 0; left -= sizeof(u32))
1415 } /* dload_checksum */
1418 /*************************************************************************
1419 * Procedure dload_reverse_checksum
1422 * data 32-bit aligned pointer to data to be checksummed
1423 * siz size of the data to be checksummed in sizeof() units.
1426 * Returns a checksum of the specified block, which is assumed to be bytes
1427 * in big-endian order.
1430 * In a big-endian host, things like the string table are stored as bytes
1431 * in host order. But dllcreate always checksums in little-endian order.
1432 * It is most efficient to just handle the difference a word at a time.
1434 ********************************************************************** */
1435 u32 dload_reverse_checksum(void *data, unsigned siz)
1444 for (left = siz; left > 0; left -= sizeof(u32)) {
1446 sum += temp << BITS_PER_BYTE * 3;
1447 sum += temp >> BITS_PER_BYTE * 3;
1448 sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
1449 sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
1453 } /* dload_reverse_checksum */
1455 #if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
1456 u32 dload_reverse_checksum16(void *data, unsigned siz)
1458 uint_fast32_t sum, temp;
1465 for (left = siz; left > 0; left -= sizeof(u32)) {
1467 sum += temp << BITS_PER_BYTE * 2;
1468 sum += temp >> BITS_PER_BYTE * 2;
1472 } /* dload_reverse_checksum16 */
1476 /*************************************************************************
1477 * Procedure swap_words
1480 * data 32-bit aligned pointer to data to be swapped
1481 * siz size of the data to be swapped.
1482 * bitmap Bit map of how to swap each 32-bit word; 1 => 2 shorts,
1486 * Swaps the specified data according to the specified map
1488 *********************************************************************** */
1489 static void swap_words(void *data, unsigned siz, unsigned bitmap)
1492 #if TARGET_AU_BITS < 16
1499 #if TARGET_AU_BITS < 16
1500 /* pass 1: do all the bytes */
1506 *sp++ = SWAP16BY8(tmp);
1507 } while ((i -= 1) > 0);
1510 #if TARGET_AU_BITS < 32
1511 /* pass 2: fixup the 32-bit words */
1515 if ((bitmap & 1) == 0) {
1518 *lp = SWAP32BY16(tmp);
1522 } while ((i -= 1) > 0);
1526 /*************************************************************************
1527 * Procedure copy_tgt_strings
1530 * dstp Destination address. Assumed to be 32-bit aligned
1531 * srcp Source address. Assumed to be 32-bit aligned
1532 * charcount Number of characters to copy.
1535 * Copies strings from the source (which is in usual .dof file order on
1536 * the loading processor) to the destination buffer (which should be in proper
1537 * target addressable unit order). Makes sure the last string in the
1538 * buffer is NULL terminated (for safety).
1539 * Returns the first unused destination address.
1540 *********************************************************************** */
1541 static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
1543 register tgt_au_t *src = (tgt_au_t *) srcp;
1544 register tgt_au_t *dst = (tgt_au_t *) dstp;
1545 register int cnt = charcount;
1547 #if TARGET_AU_BITS <= BITS_PER_AU
1548 /* byte-swapping issues may exist for strings on target */
1553 } while ((cnt -= (sizeof(tgt_au_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
1554 /*apply force to make sure that the string table has null terminator */
1555 #if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
1559 dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1;
1562 } /* copy_tgt_strings */
1564 /*************************************************************************
1565 * Procedure init_module_handle
1571 * Initializes the module handle we use to enable unloading, and installs
1572 * the debug information required by the target.
1575 * The handle returned from dynamic_load_module needs to encapsulate all the
1576 * allocations done for the module, and enable them plus the modules symbols to
1579 *********************************************************************** */
1581 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1582 (ldr_addr)-1, DBG_LIST_PAGE, DLOAD_DATA, 0
1585 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1586 (ldr_addr)-1, DLOAD_DATA, DBG_LIST_PAGE, 0
1589 static void init_module_handle(struct dload_state *dlthis)
1591 struct my_handle *hndl;
1593 struct ldr_section_info *asecs;
1594 struct dll_module *dbmod;
1595 struct dll_sect *dbsec;
1596 struct dbg_mirror_root *mlist;
1598 struct modules_header mhdr;
1599 struct ldr_section_info dllview_info;
1600 struct dynload_symbol *debug_mirror_sym;
1601 hndl = dlthis->myhandle;
1603 return; /* must be errors detected, so forget it */
1605 /* Store the section count */
1606 hndl->secn_count = dlthis->allocated_secn_count;
1608 /* If a trampoline section was created, add it in */
1609 if (dlthis->tramp.tramp_sect_next_addr != 0)
1610 hndl->secn_count += 1;
1612 hndl->secn_count = hndl->secn_count << 1;
1614 hndl->secn_count = dlthis->allocated_secn_count << 1;
1615 #ifndef TARGET_ENDIANNESS
1616 if (dlthis->big_e_target)
1617 hndl->secn_count += 1; /* flag for big-endian */
1619 if (dlthis->dload_errcount)
1620 return; /* abandon if errors detected */
1621 /* Locate the symbol that names the header for the CCS debug list
1622 of modules. If not found, we just don't generate the debug record.
1623 If found, we create our modules list. We make sure to create the
1624 loader_dllview_root even if there is no relocation info to record,
1625 just to try to put both symbols in the same symbol table and
1627 debug_mirror_sym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1628 loader_dllview_root);
1629 if (!debug_mirror_sym) {
1630 struct dynload_symbol *dlmodsym;
1631 struct dbg_mirror_root *mlst;
1633 /* our root symbol is not yet present;
1634 check if we have DLModules defined */
1635 dlmodsym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1636 LINKER_MODULES_HEADER);
1638 return; /* no DLModules list so no debug info */
1639 /* if we have DLModules defined, construct our header */
1640 mlst = (struct dbg_mirror_root *)
1641 dlthis->mysym->dload_allocate(dlthis->mysym,
1645 DL_ERROR(err_alloc, sizeof(struct dbg_mirror_root));
1651 mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
1652 /* add our root symbol */
1653 debug_mirror_sym = dlthis->mysym->add_to_symbol_table
1654 (dlthis->mysym, loader_dllview_root,
1655 (unsigned)dlthis->myhandle);
1656 if (!debug_mirror_sym) {
1657 /* failed, recover memory */
1658 dlthis->mysym->dload_deallocate(dlthis->mysym, mlst);
1661 debug_mirror_sym->value = (u32) mlst;
1663 /* First create the DLLview record and stuff it into the buffer.
1664 Then write it to the DSP. Record pertinent locations in our hndl,
1665 and add it to the per-processor list of handles with debug info. */
1666 #ifndef DEBUG_HEADER_IN_LOADER
1667 mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
1671 mlist = (struct dbg_mirror_root *)&debug_list_header;
1673 hndl->dm.root = mlist; /* set pointer to root into our handle */
1674 if (!dlthis->allocated_secn_count)
1675 return; /* no load addresses to be recorded */
1676 /* reuse temporary symbol storage */
1677 dbmod = (struct dll_module *)dlthis->local_symtab;
1678 /* Create the DLLview record in the memory we retain for our handle */
1679 dbmod->num_sects = dlthis->allocated_secn_count;
1680 dbmod->timestamp = dlthis->verify.dv_timdat;
1681 dbmod->version = INIT_VERSION;
1682 dbmod->verification = VERIFICATION;
1683 asecs = dlthis->ldr_sections;
1684 dbsec = dbmod->sects;
1685 for (curr_sect = dlthis->allocated_secn_count;
1686 curr_sect > 0; curr_sect -= 1) {
1687 dbsec->sect_load_adr = asecs->load_addr;
1688 dbsec->sect_run_adr = asecs->run_addr;
1693 /* If a trampoline section was created go ahead and add its info */
1694 if (dlthis->tramp.tramp_sect_next_addr != 0) {
1696 dbsec->sect_load_adr = asecs->load_addr;
1697 dbsec->sect_run_adr = asecs->run_addr;
1702 /* now cram in the names */
1703 cp = copy_tgt_strings(dbsec, dlthis->str_head,
1704 dlthis->debug_string_size);
1706 /* If a trampoline section was created, add its name so DLLView
1707 * can show the user the section info. */
1708 if (dlthis->tramp.tramp_sect_next_addr != 0) {
1709 cp = copy_tgt_strings(cp,
1710 dlthis->tramp.final_string_table,
1711 strlen(dlthis->tramp.final_string_table) +
1715 /* round off the size of the debug record, and remember same */
1716 hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
1717 *cp = 0; /* strictly to make our test harness happy */
1718 dllview_info = dllview_info_init;
1719 dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1720 /* Initialize memory context to default heap */
1721 dllview_info.context = 0;
1722 hndl->dm.context = 0;
1723 /* fill in next pointer and size */
1725 dbmod->next_module = TADDR_TO_TDATA(mlist->next->dm.dbthis);
1726 dbmod->next_module_size = mlist->next->dm.dbsiz;
1728 dbmod->next_module_size = 0;
1729 dbmod->next_module = 0;
1731 /* allocate memory for on-DSP DLLview debug record */
1732 if (!dlthis->myalloc)
1734 if (!dlthis->myalloc->dload_allocate(dlthis->myalloc, &dllview_info,
1735 HOST_TO_TADDR(sizeof(u32)))) {
1738 /* Store load address of .dllview section */
1739 hndl->dm.dbthis = dllview_info.load_addr;
1740 /* Store memory context (segid) in which .dllview section
1742 hndl->dm.context = dllview_info.context;
1743 mlist->refcount += 1;
1744 /* swap bytes in the entire debug record, but not the string table */
1745 if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1746 swap_words(dbmod, (char *)dbsec - (char *)dbmod,
1749 /* Update the DLLview list on the DSP write new record */
1750 if (!dlthis->myio->writemem(dlthis->myio, dbmod,
1751 dllview_info.load_addr, &dllview_info,
1752 TADDR_TO_HOST(dllview_info.size))) {
1755 /* write new header */
1756 mhdr.first_module_size = hndl->dm.dbsiz;
1757 mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
1758 /* swap bytes in the module header, if needed */
1759 if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1760 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1761 MODULES_HEADER_BITMAP);
1763 dllview_info = dllview_info_init;
1764 if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
1766 sizeof(struct modules_header) -
1770 /* Add the module handle to this processor's list
1771 of handles with debug info */
1772 hndl->dm.next = mlist->next;
1774 hndl->dm.next->dm.prev = hndl;
1775 hndl->dm.prev = (struct my_handle *)mlist;
1776 mlist->next = hndl; /* insert after root */
1777 } /* init_module_handle */
1779 /*************************************************************************
1780 * Procedure dynamic_unload_module
1783 * mhandle A module handle from dynamic_load_module
1784 * syms Host-side symbol table and malloc/free functions
1785 * alloc Target-side memory allocation
1788 * The module specified by mhandle is unloaded. Unloading causes all
1789 * target memory to be deallocated, all symbols defined by the module to
1790 * be purged, and any host-side storage used by the dynamic loader for
1791 * this module to be released.
1794 * Zero for success. On error, the number of errors detected is returned.
1795 * Individual errors are reported using syms->error_report().
1796 *********************************************************************** */
1797 int dynamic_unload_module(void *mhandle,
1798 struct dynamic_loader_sym *syms,
1799 struct dynamic_loader_allocate *alloc,
1800 struct dynamic_loader_initialize *init)
1803 struct ldr_section_info *asecs;
1804 struct my_handle *hndl;
1805 struct dbg_mirror_root *root;
1806 unsigned errcount = 0;
1807 struct ldr_section_info dllview_info = dllview_info_init;
1808 struct modules_header mhdr;
1810 hndl = (struct my_handle *)mhandle;
1812 return 0; /* if handle is null, nothing to do */
1813 /* Clear out the module symbols
1814 * Note that if this is the module that defined MODULES_HEADER
1815 (the head of the target debug list)
1816 * then this operation will blow away that symbol.
1817 It will therefore be impossible for subsequent
1818 * operations to add entries to this un-referenceable list. */
1821 syms->purge_symbol_table(syms, (unsigned)hndl);
1822 /* Deallocate target memory for sections
1823 * NOTE: The trampoline section, if created, gets deleted here, too */
1825 asecs = hndl->secns;
1827 for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
1830 alloc->dload_deallocate(alloc, asecs++);
1832 root = hndl->dm.root;
1834 /* there is a debug list containing this module */
1837 if (!hndl->dm.dbthis) { /* target-side dllview record exists */
1840 /* Retrieve memory context in which .dllview was allocated */
1841 dllview_info.context = hndl->dm.context;
1842 if (hndl->dm.prev == hndl)
1845 /* target-side dllview record is in list */
1846 /* dequeue this record from our GPP-side mirror list */
1847 hndl->dm.prev->dm.next = hndl->dm.next;
1849 hndl->dm.next->dm.prev = hndl->dm.prev;
1850 /* Update next_module of previous entry in target list
1851 * We are using mhdr here as a surrogate for either a
1852 struct modules_header or a dll_module */
1853 if (hndl->dm.next) {
1854 mhdr.first_module = TADDR_TO_TDATA(hndl->dm.next->dm.dbthis);
1855 mhdr.first_module_size = hndl->dm.next->dm.dbsiz;
1857 mhdr.first_module = 0;
1858 mhdr.first_module_size = 0;
1863 if (!init->connect(init)) {
1864 dload_syms_error(syms, iconnect);
1868 /* swap bytes in the module header, if needed */
1869 if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
1870 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1871 MODULES_HEADER_BITMAP);
1873 if (!init->writemem(init, &mhdr, hndl->dm.prev->dm.dbthis,
1874 &dllview_info, sizeof(struct modules_header) -
1875 sizeof(mhdr.update_flag))) {
1876 dload_syms_error(syms, dlvwrite);
1879 /* update change counter */
1881 if (!init->writemem(init, &(root->changes),
1882 root->dbthis + HOST_TO_TADDR
1883 (sizeof(mhdr.first_module) +
1884 sizeof(mhdr.first_module_size)),
1885 &dllview_info, sizeof(mhdr.update_flag))) {
1886 dload_syms_error(syms, dlvwrite);
1889 init->release(init);
1891 /* release target storage */
1892 dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1893 dllview_info.load_addr = hndl->dm.dbthis;
1895 alloc->dload_deallocate(alloc, &dllview_info);
1896 root->refcount -= 1;
1897 /* target-side dllview record exists */
1899 #ifndef DEBUG_HEADER_IN_LOADER
1900 if (root->refcount <= 0) {
1901 /* if all references gone, blow off the header */
1902 /* our root symbol may be gone due to the Purge above,
1903 but if not, do not destroy the root */
1904 if (syms->find_matching_symbol
1905 (syms, loader_dllview_root) == NULL)
1906 syms->dload_deallocate(syms, root);
1910 /* there is a debug list containing this module */
1911 syms->dload_deallocate(syms, mhandle); /* release our storage */
1913 } /* dynamic_unload_module */
1915 #if BITS_PER_AU > BITS_PER_BYTE
1916 /*************************************************************************
1917 * Procedure unpack_name
1920 * soffset Byte offset into the string table
1923 * Returns a pointer to the string specified by the offset supplied, or
1926 *********************************************************************** */
1927 static char *unpack_name(struct dload_state *dlthis, u32 soffset)
1932 if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
1933 dload_error(dlthis, "Bad string table offset " FMT_UI32,
1937 src = (uint_least8_t *) dlthis->str_head +
1938 (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
1939 dst = dlthis->str_temp;
1941 *dst++ = *src++; /* only 1 character in first word */
1944 *dst = (tmp >> BITS_PER_BYTE);
1947 } while ((*dst++ = tmp & BYTE_MASK));
1948 dlthis->temp_len = dst - dlthis->str_temp;
1949 /* squirrel away length including terminating null */
1950 return dlthis->str_temp;