staging: ti dspbridge: add DOFF binaries loader
[linux-2.6.git] / drivers / staging / tidspbridge / dynload / cload.c
1 /*
2  * cload.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Copyright (C) 2005-2006 Texas Instruments, Inc.
7  *
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.
11  *
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.
15  */
16
17 #include "header.h"
18
19 #include "module_list.h"
20 #define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
21
22 /*
23  * we use the fact that DOFF section records are shaped just like
24  * ldr_section_info to reduce our section storage usage.  This macro marks
25  * the places where that assumption is made
26  */
27 #define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct ldr_section_info *)(pdoffsec))
28
29 /*
30  * forward references
31  */
32 static void dload_symbols(struct dload_state *dlthis);
33 static void dload_data(struct dload_state *dlthis);
34 static void allocate_sections(struct dload_state *dlthis);
35 static void string_table_free(struct dload_state *dlthis);
36 static void symbol_table_free(struct dload_state *dlthis);
37 static void section_table_free(struct dload_state *dlthis);
38 static void init_module_handle(struct dload_state *dlthis);
39 #if BITS_PER_AU > BITS_PER_BYTE
40 static char *unpack_name(struct dload_state *dlthis, u32 soffset);
41 #endif
42
43 static const char cinitname[] = { ".cinit" };
44 static const char loader_dllview_root[] = { "?DLModules?" };
45
46 /*
47  * Error strings
48  */
49 static const char readstrm[] = { "Error reading %s from input stream" };
50 static const char err_alloc[] = { "Syms->dload_allocate( %d ) failed" };
51 static const char tgtalloc[] = {
52         "Target memory allocate failed, section %s size " FMT_UI32 };
53 static const char initfail[] = { "%s to target address " FMT_UI32 " failed" };
54 static const char dlvwrite[] = { "Write to DLLview list failed" };
55 static const char iconnect[] = { "Connect call to init interface failed" };
56 static const char err_checksum[] = { "Checksum failed on %s" };
57
58 /*************************************************************************
59  * Procedure dload_error
60  *
61  * Parameters:
62  *      errtxt  description of the error, printf style
63  *      ...             additional information
64  *
65  * Effect:
66  *      Reports or records the error as appropriate.
67  *********************************************************************** */
68 void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
69 {
70         va_list args;
71
72         va_start(args, errtxt);
73         dlthis->mysym->error_report(dlthis->mysym, errtxt, args);
74         va_end(args);
75         dlthis->dload_errcount += 1;
76
77 }                               /* dload_error */
78
79 #define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
80
81 /*************************************************************************
82  * Procedure dload_syms_error
83  *
84  * Parameters:
85  *      errtxt  description of the error, printf style
86  *      ...             additional information
87  *
88  * Effect:
89  *      Reports or records the error as appropriate.
90  *********************************************************************** */
91 void dload_syms_error(struct dynamic_loader_sym *syms, const char *errtxt, ...)
92 {
93         va_list args;
94
95         va_start(args, errtxt);
96         syms->error_report(syms, errtxt, args);
97         va_end(args);
98 }
99
100 /*************************************************************************
101  * Procedure dynamic_load_module
102  *
103  * Parameters:
104  *      module  The input stream that supplies the module image
105  *      syms    Host-side symbol table and malloc/free functions
106  *      alloc   Target-side memory allocation
107  *      init    Target-side memory initialization
108  *      options Option flags DLOAD_*
109  *      mhandle A module handle for use with Dynamic_Unload
110  *
111  * Effect:
112  *      The module image is read using *module.  Target storage for the new
113  *      image is
114  * obtained from *alloc.  Symbols defined and referenced by the module are
115  * managed using *syms.  The image is then relocated and references
116  *      resolved as necessary, and the resulting executable bits are placed
117  *      into target memory using *init.
118  *
119  * Returns:
120  *      On a successful load, a module handle is placed in *mhandle,
121  *      and zero is returned.  On error, the number of errors detected is
122  *      returned.  Individual errors are reported during the load process
123  *      using syms->error_report().
124  ********************************************************************** */
125 int dynamic_load_module(struct dynamic_loader_stream *module,
126                         struct dynamic_loader_sym *syms,
127                         struct dynamic_loader_allocate *alloc,
128                         struct dynamic_loader_initialize *init,
129                         unsigned options, void **mhandle)
130 {
131         register unsigned *dp, sz;
132         struct dload_state dl_state;    /* internal state for this call */
133
134         /* blast our internal state */
135         dp = (unsigned *)&dl_state;
136         for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
137                 *dp++ = 0;
138
139         /* Enable _only_ BSS initialization if enabled by user */
140         if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
141                 dl_state.myoptions = DLOAD_INITBSS;
142
143         /* Check that mandatory arguments are present */
144         if (!module || !syms) {
145                 dload_error(&dl_state, "Required parameter is NULL");
146         } else {
147                 dl_state.strm = module;
148                 dl_state.mysym = syms;
149                 dload_headers(&dl_state);
150                 if (!dl_state.dload_errcount)
151                         dload_strings(&dl_state, false);
152                 if (!dl_state.dload_errcount)
153                         dload_sections(&dl_state);
154
155                 if (init && !dl_state.dload_errcount) {
156                         if (init->connect(init)) {
157                                 dl_state.myio = init;
158                                 dl_state.myalloc = alloc;
159                                 /* do now, before reducing symbols */
160                                 allocate_sections(&dl_state);
161                         } else
162                                 dload_error(&dl_state, iconnect);
163                 }
164
165                 if (!dl_state.dload_errcount) {
166                         /* fix up entry point address */
167                         unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
168                         if (sref < dl_state.allocated_secn_count)
169                                 dl_state.dfile_hdr.df_entrypt +=
170                                     dl_state.ldr_sections[sref].run_addr;
171
172                         dload_symbols(&dl_state);
173                 }
174
175                 if (init && !dl_state.dload_errcount)
176                         dload_data(&dl_state);
177
178                 init_module_handle(&dl_state);
179
180                 /* dl_state.myio is init or 0 at this point. */
181                 if (dl_state.myio) {
182                         if ((!dl_state.dload_errcount) &&
183                             (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
184                             (!init->execute(init,
185                                             dl_state.dfile_hdr.df_entrypt)))
186                                 dload_error(&dl_state, "Init->Execute Failed");
187                         init->release(init);
188                 }
189
190                 symbol_table_free(&dl_state);
191                 section_table_free(&dl_state);
192                 string_table_free(&dl_state);
193                 dload_tramp_cleanup(&dl_state);
194
195                 if (dl_state.dload_errcount) {
196                         dynamic_unload_module(dl_state.myhandle, syms, alloc,
197                                               init);
198                         dl_state.myhandle = NULL;
199                 }
200         }
201
202         if (mhandle)
203                 *mhandle = dl_state.myhandle;   /* give back the handle */
204
205         return dl_state.dload_errcount;
206 }                               /* DLOAD_File */
207
208 /*************************************************************************
209  * Procedure dynamic_open_module
210  *
211  * Parameters:
212  *      module  The input stream that supplies the module image
213  *      syms    Host-side symbol table and malloc/free functions
214  *      alloc   Target-side memory allocation
215  *      init    Target-side memory initialization
216  *      options Option flags DLOAD_*
217  *      mhandle A module handle for use with Dynamic_Unload
218  *
219  * Effect:
220  *      The module image is read using *module.  Target storage for the new
221  *      image is
222  *      obtained from *alloc.  Symbols defined and referenced by the module are
223  *      managed using *syms.  The image is then relocated and references
224  *      resolved as necessary, and the resulting executable bits are placed
225  *      into target memory using *init.
226  *
227  * Returns:
228  *      On a successful load, a module handle is placed in *mhandle,
229  *      and zero is returned.  On error, the number of errors detected is
230  *      returned.  Individual errors are reported during the load process
231  *      using syms->error_report().
232  ********************************************************************** */
233 int
234 dynamic_open_module(struct dynamic_loader_stream *module,
235                     struct dynamic_loader_sym *syms,
236                     struct dynamic_loader_allocate *alloc,
237                     struct dynamic_loader_initialize *init,
238                     unsigned options, void **mhandle)
239 {
240         register unsigned *dp, sz;
241         struct dload_state dl_state;    /* internal state for this call */
242
243         /* blast our internal state */
244         dp = (unsigned *)&dl_state;
245         for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
246                 *dp++ = 0;
247
248         /* Enable _only_ BSS initialization if enabled by user */
249         if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
250                 dl_state.myoptions = DLOAD_INITBSS;
251
252         /* Check that mandatory arguments are present */
253         if (!module || !syms) {
254                 dload_error(&dl_state, "Required parameter is NULL");
255         } else {
256                 dl_state.strm = module;
257                 dl_state.mysym = syms;
258                 dload_headers(&dl_state);
259                 if (!dl_state.dload_errcount)
260                         dload_strings(&dl_state, false);
261                 if (!dl_state.dload_errcount)
262                         dload_sections(&dl_state);
263
264                 if (init && !dl_state.dload_errcount) {
265                         if (init->connect(init)) {
266                                 dl_state.myio = init;
267                                 dl_state.myalloc = alloc;
268                                 /* do now, before reducing symbols */
269                                 allocate_sections(&dl_state);
270                         } else
271                                 dload_error(&dl_state, iconnect);
272                 }
273
274                 if (!dl_state.dload_errcount) {
275                         /* fix up entry point address */
276                         unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
277                         if (sref < dl_state.allocated_secn_count)
278                                 dl_state.dfile_hdr.df_entrypt +=
279                                     dl_state.ldr_sections[sref].run_addr;
280
281                         dload_symbols(&dl_state);
282                 }
283
284                 init_module_handle(&dl_state);
285
286                 /* dl_state.myio is either 0 or init at this point. */
287                 if (dl_state.myio) {
288                         if ((!dl_state.dload_errcount) &&
289                             (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF) &&
290                             (!init->execute(init,
291                                             dl_state.dfile_hdr.df_entrypt)))
292                                 dload_error(&dl_state, "Init->Execute Failed");
293                         init->release(init);
294                 }
295
296                 symbol_table_free(&dl_state);
297                 section_table_free(&dl_state);
298                 string_table_free(&dl_state);
299
300                 if (dl_state.dload_errcount) {
301                         dynamic_unload_module(dl_state.myhandle, syms, alloc,
302                                               init);
303                         dl_state.myhandle = NULL;
304                 }
305         }
306
307         if (mhandle)
308                 *mhandle = dl_state.myhandle;   /* give back the handle */
309
310         return dl_state.dload_errcount;
311 }                               /* DLOAD_File */
312
313 /*************************************************************************
314  * Procedure dload_headers
315  *
316  * Parameters:
317  *      none
318  *
319  * Effect:
320  *      Loads the DOFF header and verify record.  Deals with any byte-order
321  * issues and checks them for validity.
322  *********************************************************************** */
323 #define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
324                              sizeof(struct doff_verify_rec_t))
325
326 void dload_headers(struct dload_state *dlthis)
327 {
328         u32 map;
329
330         /* Read the header and the verify record as one.  If we don't get it
331            all, we're done */
332         if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
333                                       COMBINED_HEADER_SIZE) !=
334             COMBINED_HEADER_SIZE) {
335                 DL_ERROR(readstrm, "File Headers");
336                 return;
337         }
338         /*
339          * Verify that we have the byte order of the file correct.
340          * If not, must fix it before we can continue
341          */
342         map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
343         if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
344                 /* input is either byte-shuffled or bad */
345                 if ((map & 0xFCFCFCFC) == 0) {  /* no obviously bogus bits */
346                         dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
347                                       map);
348                 }
349                 if (dlthis->dfile_hdr.df_byte_reshuffle !=
350                     BYTE_RESHUFFLE_VALUE) {
351                         /* didn't fix the problem, the byte swap map is bad */
352                         dload_error(dlthis,
353                                     "Bad byte swap map " FMT_UI32 " in header",
354                                     dlthis->dfile_hdr.df_byte_reshuffle);
355                         return;
356                 }
357                 dlthis->reorder_map = map;      /* keep map for future use */
358         }
359
360         /*
361          * Verify checksum of header and verify record
362          */
363         if (~dload_checksum(&dlthis->dfile_hdr,
364                             sizeof(struct doff_filehdr_t)) ||
365             ~dload_checksum(&dlthis->verify,
366                             sizeof(struct doff_verify_rec_t))) {
367                 DL_ERROR(err_checksum, "header or verify record");
368                 return;
369         }
370 #if HOST_ENDIANNESS
371         dlthis->dfile_hdr.df_byte_reshuffle = map;      /* put back for later */
372 #endif
373
374         /* Check for valid target ID */
375         if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
376             -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
377                 dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
378                             dlthis->dfile_hdr.df_target_id, TARGET_ID);
379                 return;
380         }
381         /* Check for valid file format */
382         if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
383                 dload_error(dlthis, "Bad DOFF version 0x%x",
384                             dlthis->dfile_hdr.df_doff_version);
385                 return;
386         }
387
388         /*
389          * Apply reasonableness checks to count fields
390          */
391         if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
392                 dload_error(dlthis, "Excessive string table size " FMT_UI32,
393                             dlthis->dfile_hdr.df_strtab_size);
394                 return;
395         }
396         if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
397                 dload_error(dlthis, "Excessive section count 0x%x",
398                             dlthis->dfile_hdr.df_no_scns);
399                 return;
400         }
401 #ifndef TARGET_ENDIANNESS
402         /*
403          * Check that endianness does not disagree with explicit specification
404          */
405         if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
406             dlthis->myoptions & ENDIANNESS_MASK) {
407                 dload_error(dlthis,
408                             "Input endianness disagrees with specified option");
409                 return;
410         }
411         dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
412 #endif
413
414 }                               /* dload_headers */
415
416 /*      COFF Section Processing
417  *
418  *      COFF sections are read in and retained intact.  Each record is embedded
419  *      in a new structure that records the updated load and
420  *      run addresses of the section */
421
422 static const char secn_errid[] = { "section" };
423
424 /*************************************************************************
425  * Procedure dload_sections
426  *
427  * Parameters:
428  *      none
429  *
430  * Effect:
431  *      Loads the section records into an internal table.
432  *********************************************************************** */
433 void dload_sections(struct dload_state *dlthis)
434 {
435         s16 siz;
436         struct doff_scnhdr_t *shp;
437         unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
438
439         /* allocate space for the DOFF section records */
440         siz = nsecs * sizeof(struct doff_scnhdr_t);
441         shp =
442             (struct doff_scnhdr_t *)dlthis->mysym->dload_allocate(dlthis->mysym,
443                                                                   siz);
444         if (!shp) {             /* not enough storage */
445                 DL_ERROR(err_alloc, siz);
446                 return;
447         }
448         dlthis->sect_hdrs = shp;
449
450         /* read in the section records */
451         if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
452                 DL_ERROR(readstrm, secn_errid);
453                 return;
454         }
455
456         /* if we need to fix up byte order, do it now */
457         if (dlthis->reorder_map)
458                 dload_reorder(shp, siz, dlthis->reorder_map);
459
460         /* check for validity */
461         if (~dload_checksum(dlthis->sect_hdrs, siz) !=
462             dlthis->verify.dv_scn_rec_checksum) {
463                 DL_ERROR(err_checksum, secn_errid);
464                 return;
465         }
466
467 }                               /* dload_sections */
468
469 /*****************************************************************************
470  * Procedure allocate_sections
471  *
472  * Parameters:
473  *      alloc   target memory allocator class
474  *
475  * Effect:
476  *      Assigns new (target) addresses for sections
477  **************************************************************************** */
478 static void allocate_sections(struct dload_state *dlthis)
479 {
480         u16 curr_sect, nsecs, siz;
481         struct doff_scnhdr_t *shp;
482         struct ldr_section_info *asecs;
483         struct my_handle *hndl;
484         nsecs = dlthis->dfile_hdr.df_no_scns;
485         if (!nsecs)
486                 return;
487         if ((dlthis->myalloc == NULL) &&
488             (dlthis->dfile_hdr.df_target_scns > 0)) {
489                 DL_ERROR("Arg 3 (alloc) required but NULL", 0);
490                 return;
491         }
492         /*
493          * allocate space for the module handle, which we will keep for unload
494          * purposes include an additional section store for an auto-generated
495          * trampoline section in case we need it.
496          */
497         siz = (dlthis->dfile_hdr.df_target_scns + 1) *
498             sizeof(struct ldr_section_info) + MY_HANDLE_SIZE;
499
500         hndl =
501             (struct my_handle *)dlthis->mysym->dload_allocate(dlthis->mysym,
502                                                               siz);
503         if (!hndl) {            /* not enough storage */
504                 DL_ERROR(err_alloc, siz);
505                 return;
506         }
507         /* initialize the handle header */
508         hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
509         hndl->dm.hroot = NULL;
510         hndl->dm.dbthis = 0;
511         dlthis->myhandle = hndl;        /* save away for return */
512         /* pointer to the section list of allocated sections */
513         dlthis->ldr_sections = asecs = hndl->secns;
514         /* * Insert names into all sections, make copies of
515            the sections we allocate */
516         shp = dlthis->sect_hdrs;
517         for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
518                 u32 soffset = shp->ds_offset;
519 #if BITS_PER_AU <= BITS_PER_BYTE
520                 /* attempt to insert the name of this section */
521                 if (soffset < dlthis->dfile_hdr.df_strtab_size)
522                         DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
523                             soffset;
524                 else {
525                         dload_error(dlthis, "Bad name offset in section %d",
526                                     curr_sect);
527                         DOFFSEC_IS_LDRSEC(shp)->name = NULL;
528                 }
529 #endif
530                 /* allocate target storage for sections that require it */
531                 if (DS_NEEDS_ALLOCATION(shp)) {
532                         *asecs = *DOFFSEC_IS_LDRSEC(shp);
533                         asecs->context = 0;     /* zero the context field */
534 #if BITS_PER_AU > BITS_PER_BYTE
535                         asecs->name = unpack_name(dlthis, soffset);
536                         dlthis->debug_string_size = soffset + dlthis->temp_len;
537 #else
538                         dlthis->debug_string_size = soffset;
539 #endif
540                         if (dlthis->myalloc != NULL) {
541                                 if (!dlthis->myalloc->
542                                     dload_allocate(dlthis->myalloc, asecs,
543                                                    DS_ALIGNMENT(asecs->type))) {
544                                         dload_error(dlthis, tgtalloc,
545                                                     asecs->name, asecs->size);
546                                         return;
547                                 }
548                         }
549                         /* keep address deltas in original section table */
550                         shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
551                         shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
552                         dlthis->allocated_secn_count += 1;
553                 }               /* allocate target storage */
554                 shp += 1;
555                 asecs += 1;
556         }
557 #if BITS_PER_AU <= BITS_PER_BYTE
558         dlthis->debug_string_size +=
559             strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
560 #endif
561 }                               /* allocate sections */
562
563 /*************************************************************************
564  * Procedure section_table_free
565  *
566  * Parameters:
567  *      none
568  *
569  * Effect:
570  *      Frees any state used by the symbol table.
571  *
572  * WARNING:
573  *      This routine is not allowed to declare errors!
574  *********************************************************************** */
575 static void section_table_free(struct dload_state *dlthis)
576 {
577         struct doff_scnhdr_t *shp;
578
579         shp = dlthis->sect_hdrs;
580         if (shp)
581                 dlthis->mysym->dload_deallocate(dlthis->mysym, shp);
582
583 }                               /* section_table_free */
584
585 /*************************************************************************
586  * Procedure dload_strings
587  *
588  * Parameters:
589  *  sec_names_only   If true only read in the "section names"
590  *                   portion of the string table
591  *
592  * Effect:
593  *      Loads the DOFF string table into memory. DOFF keeps all strings in a
594  * big unsorted array.  We just read that array into memory in bulk.
595  *********************************************************************** */
596 static const char stringtbl[] = { "string table" };
597
598 void dload_strings(struct dload_state *dlthis, bool sec_names_only)
599 {
600         u32 ssiz;
601         char *strbuf;
602
603         if (sec_names_only) {
604                 ssiz = BYTE_TO_HOST(DOFF_ALIGN
605                                     (dlthis->dfile_hdr.df_scn_name_size));
606         } else {
607                 ssiz = BYTE_TO_HOST(DOFF_ALIGN
608                                     (dlthis->dfile_hdr.df_strtab_size));
609         }
610         if (ssiz == 0)
611                 return;
612
613         /* get some memory for the string table */
614 #if BITS_PER_AU > BITS_PER_BYTE
615         strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz +
616                                                        dlthis->dfile_hdr.
617                                                        df_max_str_len);
618 #else
619         strbuf = (char *)dlthis->mysym->dload_allocate(dlthis->mysym, ssiz);
620 #endif
621         if (strbuf == NULL) {
622                 DL_ERROR(err_alloc, ssiz);
623                 return;
624         }
625         dlthis->str_head = strbuf;
626 #if BITS_PER_AU > BITS_PER_BYTE
627         dlthis->str_temp = strbuf + ssiz;
628 #endif
629         /* read in the strings and verify them */
630         if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
631                                                  ssiz)) != ssiz) {
632                 DL_ERROR(readstrm, stringtbl);
633         }
634         /* if we need to fix up byte order, do it now */
635 #ifndef _BIG_ENDIAN
636         if (dlthis->reorder_map)
637                 dload_reorder(strbuf, ssiz, dlthis->reorder_map);
638
639         if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
640                                   dlthis->verify.dv_str_tab_checksum)) {
641                 DL_ERROR(err_checksum, stringtbl);
642         }
643 #else
644         if (dlthis->dfile_hdr.df_byte_reshuffle !=
645             HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
646                 /* put strings in big-endian order, not in PC order */
647                 dload_reorder(strbuf, ssiz,
648                               HOST_BYTE_ORDER(dlthis->
649                                               dfile_hdr.df_byte_reshuffle));
650         }
651         if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
652                                   dlthis->verify.dv_str_tab_checksum)) {
653                 DL_ERROR(err_checksum, stringtbl);
654         }
655 #endif
656 }                               /* dload_strings */
657
658 /*************************************************************************
659  * Procedure string_table_free
660  *
661  * Parameters:
662  *      none
663  *
664  * Effect:
665  *      Frees any state used by the string table.
666  *
667  * WARNING:
668  *      This routine is not allowed to declare errors!
669  ************************************************************************ */
670 static void string_table_free(struct dload_state *dlthis)
671 {
672         if (dlthis->str_head)
673                 dlthis->mysym->dload_deallocate(dlthis->mysym,
674                                                 dlthis->str_head);
675
676 }                               /* string_table_free */
677
678 /*
679  * Symbol Table Maintenance Functions
680  *
681  * COFF symbols are read by dload_symbols(), which is called after
682  * sections have been allocated.  Symbols which might be used in
683  * relocation (ie, not debug info) are retained in an internal temporary
684  * compressed table (type local_symbol). A particular symbol is recovered
685  * by index by calling dload_find_symbol().  dload_find_symbol
686  * reconstructs a more explicit representation (type SLOTVEC) which is
687  * used by reloc.c
688  */
689 /* real size of debug header */
690 #define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
691
692 static const char sym_errid[] = { "symbol" };
693
694 /**************************************************************************
695  * Procedure dload_symbols
696  *
697  * Parameters:
698  *      none
699  *
700  * Effect:
701  *      Reads in symbols and retains ones that might be needed for relocation
702  * purposes.
703  *********************************************************************** */
704 /* size of symbol buffer no bigger than target data buffer, to limit stack
705  * usage */
706 #define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
707                         sizeof(struct doff_syment_t))
708
709 static void dload_symbols(struct dload_state *dlthis)
710 {
711         u32 sym_count, siz, dsiz, symbols_left;
712         u32 checks;
713         struct local_symbol *sp;
714         struct dynload_symbol *symp;
715         struct dynload_symbol *newsym;
716
717         sym_count = dlthis->dfile_hdr.df_no_syms;
718         if (sym_count == 0)
719                 return;
720
721         /*
722          * We keep a local symbol table for all of the symbols in the input.
723          * This table contains only section & value info, as we do not have
724          * to do any name processing for locals.  We reuse this storage
725          * as a temporary for .dllview record construction.
726          * Allocate storage for the whole table.  Add 1 to the section count
727          * in case a trampoline section is auto-generated as well as the
728          * size of the trampoline section name so DLLView doens't get lost.
729          */
730
731         siz = sym_count * sizeof(struct local_symbol);
732         dsiz = DBG_HDR_SIZE +
733             (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
734             BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
735         if (dsiz > siz)
736                 siz = dsiz;     /* larger of symbols and .dllview temp */
737         sp = (struct local_symbol *)dlthis->mysym->dload_allocate(dlthis->mysym,
738                                                                   siz);
739         if (!sp) {
740                 DL_ERROR(err_alloc, siz);
741                 return;
742         }
743         dlthis->local_symtab = sp;
744         /* Read the symbols in the input, store them in the table, and post any
745          * globals to the global symbol table.  In the process, externals
746          become defined from the global symbol table */
747         checks = dlthis->verify.dv_sym_tab_checksum;
748         symbols_left = sym_count;
749         do {                    /* read all symbols */
750                 char *sname;
751                 u32 val;
752                 s32 delta;
753                 struct doff_syment_t *input_sym;
754                 unsigned syms_in_buf;
755                 struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
756                 input_sym = my_sym_buf;
757                 syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
758                     MY_SYM_BUF_SIZ : symbols_left;
759                 siz = syms_in_buf * sizeof(struct doff_syment_t);
760                 if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
761                     siz) {
762                         DL_ERROR(readstrm, sym_errid);
763                         return;
764                 }
765                 if (dlthis->reorder_map)
766                         dload_reorder(input_sym, siz, dlthis->reorder_map);
767
768                 checks += dload_checksum(input_sym, siz);
769                 do {            /* process symbols in buffer */
770                         symbols_left -= 1;
771                         /* attempt to derive the name of this symbol */
772                         sname = NULL;
773                         if (input_sym->dn_offset > 0) {
774 #if BITS_PER_AU <= BITS_PER_BYTE
775                                 if ((u32) input_sym->dn_offset <
776                                     dlthis->dfile_hdr.df_strtab_size)
777                                         sname = dlthis->str_head +
778                                             BYTE_TO_HOST(input_sym->dn_offset);
779                                 else
780                                         dload_error(dlthis,
781                                                     "Bad name offset in symbol "
782                                                     " %d", symbols_left);
783 #else
784                                 sname = unpack_name(dlthis,
785                                                     input_sym->dn_offset);
786 #endif
787                         }
788                         val = input_sym->dn_value;
789                         delta = 0;
790                         sp->sclass = input_sym->dn_sclass;
791                         sp->secnn = input_sym->dn_scnum;
792                         /* if this is an undefined symbol,
793                          * define it (or fail) now */
794                         if (sp->secnn == DN_UNDEF) {
795                                 /* pointless for static undefined */
796                                 if (input_sym->dn_sclass != DN_EXT)
797                                         goto loop_cont;
798
799                                 /* try to define symbol from previously
800                                  * loaded images */
801                                 symp = dlthis->mysym->find_matching_symbol
802                                     (dlthis->mysym, sname);
803                                 if (!symp) {
804                                         DL_ERROR
805                                             ("Undefined external symbol %s",
806                                              sname);
807                                         goto loop_cont;
808                                 }
809                                 val = delta = symp->value;
810 #ifdef ENABLE_TRAMP_DEBUG
811                                 dload_syms_error(dlthis->mysym,
812                                                  "===> ext sym [%s] at %x",
813                                                  sname, val);
814 #endif
815
816                                 goto loop_cont;
817                         }
818                         /* symbol defined by this module */
819                         if (sp->secnn > 0) {
820                                 /* symbol references a section */
821                                 if ((unsigned)sp->secnn <=
822                                     dlthis->allocated_secn_count) {
823                                         /* section was allocated */
824                                         struct doff_scnhdr_t *srefp =
825                                             &dlthis->sect_hdrs[sp->secnn - 1];
826
827                                         if (input_sym->dn_sclass ==
828                                             DN_STATLAB ||
829                                             input_sym->dn_sclass == DN_EXTLAB) {
830                                                 /* load */
831                                                 delta = srefp->ds_vaddr;
832                                         } else {
833                                                 /* run */
834                                                 delta = srefp->ds_paddr;
835                                         }
836                                         val += delta;
837                                 }
838                                 goto loop_itr;
839                         }
840                         /* This symbol is an absolute symbol */
841                         if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
842                                                     (sp->sclass ==
843                                                      DN_EXTLAB))) {
844                                 symp =
845                                     dlthis->mysym->find_matching_symbol(dlthis->
846                                                                         mysym,
847                                                                         sname);
848                                 if (!symp)
849                                         goto loop_itr;
850                                 /* This absolute symbol is already defined. */
851                                 if (symp->value == input_sym->dn_value) {
852                                         /* If symbol values are equal, continue
853                                          * but don't add to the global symbol
854                                          * table */
855                                         sp->value = val;
856                                         sp->delta = delta;
857                                         sp += 1;
858                                         input_sym += 1;
859                                         continue;
860                                 } else {
861                                         /* If symbol values are not equal,
862                                          * return with redefinition error */
863                                         DL_ERROR("Absolute symbol %s is "
864                                                  "defined multiple times with "
865                                                  "different values", sname);
866                                         return;
867                                 }
868                         }
869 loop_itr:
870                         /* if this is a global symbol, post it to the
871                          * global table */
872                         if (input_sym->dn_sclass == DN_EXT ||
873                             input_sym->dn_sclass == DN_EXTLAB) {
874                                 /* Keep this global symbol for subsequent
875                                  * modules. Don't complain on error, to allow
876                                  * symbol API to suppress global symbols */
877                                 if (!sname)
878                                         goto loop_cont;
879
880                                 newsym = dlthis->mysym->add_to_symbol_table
881                                     (dlthis->mysym, sname,
882                                      (unsigned)dlthis->myhandle);
883                                 if (newsym)
884                                         newsym->value = val;
885
886                         }       /* global */
887 loop_cont:
888                         sp->value = val;
889                         sp->delta = delta;
890                         sp += 1;
891                         input_sym += 1;
892                 } while ((syms_in_buf -= 1) > 0);       /* process sym in buf */
893         } while (symbols_left > 0);     /* read all symbols */
894         if (~checks)
895                 dload_error(dlthis, "Checksum of symbols failed");
896
897 }                               /* dload_symbols */
898
899 /*****************************************************************************
900  * Procedure symbol_table_free
901  *
902  * Parameters:
903  *      none
904  *
905  * Effect:
906  *      Frees any state used by the symbol table.
907  *
908  * WARNING:
909  *      This routine is not allowed to declare errors!
910  **************************************************************************** */
911 static void symbol_table_free(struct dload_state *dlthis)
912 {
913         if (dlthis->local_symtab) {
914                 if (dlthis->dload_errcount) {   /* blow off our symbols */
915                         dlthis->mysym->purge_symbol_table(dlthis->mysym,
916                                                           (unsigned)
917                                                           dlthis->myhandle);
918                 }
919                 dlthis->mysym->dload_deallocate(dlthis->mysym,
920                                                 dlthis->local_symtab);
921         }
922 }                               /* symbol_table_free */
923
924 /* .cinit Processing
925  *
926  * The dynamic loader does .cinit interpretation.  cload_cinit()
927  * acts as a special write-to-target function, in that it takes relocated
928  * data from the normal data flow, and interprets it as .cinit actions.
929  * Because the normal data flow does not  necessarily process the whole
930  * .cinit section in one buffer, cload_cinit() must be prepared to
931  * interpret the data piecemeal.  A state machine is used for this
932  * purpose.
933  */
934
935 /* The following are only for use by reloc.c and things it calls */
936 static const struct ldr_section_info cinit_info_init = { cinitname, 0, 0,
937         (ldr_addr)-1, 0, DLOAD_BSS, 0
938 };
939
940 /*************************************************************************
941  * Procedure cload_cinit
942  *
943  * Parameters:
944  *      ipacket         Pointer to data packet to be loaded
945  *
946  * Effect:
947  *      Interprets the data in the buffer as .cinit data, and performs the
948  * appropriate initializations.
949  *********************************************************************** */
950 static void cload_cinit(struct dload_state *dlthis,
951                         struct image_packet_t *ipacket)
952 {
953 #if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
954         s32 init_count, left;
955 #else
956         s16 init_count, left;
957 #endif
958         unsigned char *pktp = ipacket->img_data;
959         unsigned char *pktend = pktp + BYTE_TO_HOST_ROUND(ipacket->packet_size);
960         int temp;
961         ldr_addr atmp;
962         struct ldr_section_info cinit_info;
963
964         /*  PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER. */
965         while (true) {
966                 left = pktend - pktp;
967                 switch (dlthis->cinit_state) {
968                 case CI_COUNT:  /* count field */
969                         if (left < TDATA_TO_HOST(CINIT_COUNT))
970                                 goto loopexit;
971                         temp = dload_unpack(dlthis, (tgt_au_t *) pktp,
972                                             CINIT_COUNT * TDATA_AU_BITS, 0,
973                                             ROP_SGN);
974                         pktp += TDATA_TO_HOST(CINIT_COUNT);
975                         /* negative signifies BSS table, zero means done */
976                         if (temp <= 0) {
977                                 dlthis->cinit_state = CI_DONE;
978                                 break;
979                         }
980                         dlthis->cinit_count = temp;
981                         dlthis->cinit_state = CI_ADDRESS;
982                         break;
983 #if CINIT_ALIGN < CINIT_ADDRESS
984                 case CI_PARTADDRESS:
985                         pktp -= TDATA_TO_HOST(CINIT_ALIGN);
986                         /* back up pointer into space courtesy of caller */
987                         *(uint16_t *) pktp = dlthis->cinit_addr;
988                         /* stuff in saved bits  !! FALL THRU !! */
989 #endif
990                 case CI_ADDRESS:        /* Address field for a copy packet */
991                         if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
992 #if CINIT_ALIGN < CINIT_ADDRESS
993                                 if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
994                                         /* address broken into halves */
995                                         dlthis->cinit_addr = *(uint16_t *) pktp;
996                                         /* remember 1st half */
997                                         dlthis->cinit_state = CI_PARTADDRESS;
998                                         left = 0;
999                                 }
1000 #endif
1001                                 goto loopexit;
1002                         }
1003                         atmp = dload_unpack(dlthis, (tgt_au_t *) pktp,
1004                                             CINIT_ADDRESS * TDATA_AU_BITS, 0,
1005                                             ROP_UNS);
1006                         pktp += TDATA_TO_HOST(CINIT_ADDRESS);
1007 #if CINIT_PAGE_BITS > 0
1008                         dlthis->cinit_page = atmp &
1009                             ((1 << CINIT_PAGE_BITS) - 1);
1010                         atmp >>= CINIT_PAGE_BITS;
1011 #else
1012                         dlthis->cinit_page = CINIT_DEFAULT_PAGE;
1013 #endif
1014                         dlthis->cinit_addr = atmp;
1015                         dlthis->cinit_state = CI_COPY;
1016                         break;
1017                 case CI_COPY:   /* copy bits to the target */
1018                         init_count = HOST_TO_TDATA(left);
1019                         if (init_count > dlthis->cinit_count)
1020                                 init_count = dlthis->cinit_count;
1021                         if (init_count == 0)
1022                                 goto loopexit;  /* get more bits */
1023                         cinit_info = cinit_info_init;
1024                         cinit_info.page = dlthis->cinit_page;
1025                         if (!dlthis->myio->writemem(dlthis->myio, pktp,
1026                                                    TDATA_TO_TADDR
1027                                                    (dlthis->cinit_addr),
1028                                                    &cinit_info,
1029                                                    TDATA_TO_HOST(init_count))) {
1030                                 dload_error(dlthis, initfail, "write",
1031                                             dlthis->cinit_addr);
1032                         }
1033                         dlthis->cinit_count -= init_count;
1034                         if (dlthis->cinit_count <= 0) {
1035                                 dlthis->cinit_state = CI_COUNT;
1036                                 init_count = (init_count + CINIT_ALIGN - 1) &
1037                                     -CINIT_ALIGN;
1038                                 /* align to next init */
1039                         }
1040                         pktp += TDATA_TO_HOST(init_count);
1041                         dlthis->cinit_addr += init_count;
1042                         break;
1043                 case CI_DONE:   /* no more .cinit to do */
1044                         return;
1045                 }               /* switch (cinit_state) */
1046         }                       /* while */
1047
1048 loopexit:
1049         if (left > 0) {
1050                 dload_error(dlthis, "%d bytes left over in cinit packet", left);
1051                 dlthis->cinit_state = CI_DONE;  /* left over bytes are bad */
1052         }
1053 }                               /* cload_cinit */
1054
1055 /*      Functions to interface to reloc.c
1056  *
1057  * reloc.c is the relocation module borrowed from the linker, with
1058  * minimal (we hope) changes for our purposes.  cload_sect_data() invokes
1059  * this module on a section to relocate and load the image data for that
1060  * section.  The actual read and write actions are supplied by the global
1061  * routines below.
1062  */
1063
1064 /************************************************************************
1065  * Procedure relocate_packet
1066  *
1067  * Parameters:
1068  *      ipacket         Pointer to an image packet to relocate
1069  *
1070  * Effect:
1071  *      Performs the required relocations on the packet.  Returns a checksum
1072  * of the relocation operations.
1073  *********************************************************************** */
1074 #define MY_RELOC_BUF_SIZ 8
1075 /* careful! exists at the same time as the image buffer */
1076 static int relocate_packet(struct dload_state *dlthis,
1077                            struct image_packet_t *ipacket,
1078                            u32 *checks, bool *tramps_generated)
1079 {
1080         u32 rnum;
1081         *tramps_generated = false;
1082
1083         rnum = ipacket->num_relocs;
1084         do {                    /* all relocs */
1085                 unsigned rinbuf;
1086                 int siz;
1087                 struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
1088                 rp = rrec;
1089                 rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
1090                 siz = rinbuf * sizeof(struct reloc_record_t);
1091                 if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
1092                         DL_ERROR(readstrm, "relocation");
1093                         return 0;
1094                 }
1095                 /* reorder the bytes if need be */
1096                 if (dlthis->reorder_map)
1097                         dload_reorder(rp, siz, dlthis->reorder_map);
1098
1099                 *checks += dload_checksum(rp, siz);
1100                 do {
1101                         /* perform the relocation operation */
1102                         dload_relocate(dlthis, (tgt_au_t *) ipacket->img_data,
1103                                        rp, tramps_generated, false);
1104                         rp += 1;
1105                         rnum -= 1;
1106                 } while ((rinbuf -= 1) > 0);
1107         } while (rnum > 0);     /* all relocs */
1108         /* If trampoline(s) were generated, we need to do an update of the
1109          * trampoline copy of the packet since a 2nd phase relo will be done
1110          * later. */
1111         if (*tramps_generated == true) {
1112                 dload_tramp_pkt_udpate(dlthis,
1113                                        (dlthis->image_secn -
1114                                         dlthis->ldr_sections),
1115                                        dlthis->image_offset, ipacket);
1116         }
1117
1118         return 1;
1119 }                               /* dload_read_reloc */
1120
1121 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
1122
1123 /* VERY dangerous */
1124 static const char imagepak[] = { "image packet" };
1125
1126 /*************************************************************************
1127  * Procedure dload_data
1128  *
1129  * Parameters:
1130  *      none
1131  *
1132  * Effect:
1133  *      Read image data from input file, relocate it, and download it to the
1134  *      target.
1135  *********************************************************************** */
1136 static void dload_data(struct dload_state *dlthis)
1137 {
1138         u16 curr_sect;
1139         struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
1140         struct ldr_section_info *lptr = dlthis->ldr_sections;
1141 #ifdef OPT_ZERO_COPY_LOADER
1142         bool zero_copy = false;
1143 #endif
1144         u8 *dest;
1145
1146         struct {
1147                 struct image_packet_t ipacket;
1148                 u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
1149         } ibuf;
1150
1151         /* Indicates whether CINIT processing has occurred */
1152         bool cinit_processed = false;
1153
1154         /* Loop through the sections and load them one at a time.
1155          */
1156         for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
1157              curr_sect += 1) {
1158                 if (DS_NEEDS_DOWNLOAD(sptr)) {
1159                         s32 nip;
1160                         ldr_addr image_offset = 0;
1161                         /* set relocation info for this section */
1162                         if (curr_sect < dlthis->allocated_secn_count)
1163                                 dlthis->delta_runaddr = sptr->ds_paddr;
1164                         else {
1165                                 lptr = DOFFSEC_IS_LDRSEC(sptr);
1166                                 dlthis->delta_runaddr = 0;
1167                         }
1168                         dlthis->image_secn = lptr;
1169 #if BITS_PER_AU > BITS_PER_BYTE
1170                         lptr->name = unpack_name(dlthis, sptr->ds_offset);
1171 #endif
1172                         nip = sptr->ds_nipacks;
1173                         while ((nip -= 1) >= 0) {       /* process packets */
1174
1175                                 s32 ipsize;
1176                                 u32 checks;
1177                                 bool tramp_generated = false;
1178
1179                                 /* get the fixed header bits */
1180                                 if (dlthis->strm->read_buffer(dlthis->strm,
1181                                                               &ibuf.ipacket,
1182                                                               IPH_SIZE) !=
1183                                     IPH_SIZE) {
1184                                         DL_ERROR(readstrm, imagepak);
1185                                         return;
1186                                 }
1187                                 /* reorder the header if need be */
1188                                 if (dlthis->reorder_map) {
1189                                         dload_reorder(&ibuf.ipacket, IPH_SIZE,
1190                                                       dlthis->reorder_map);
1191                                 }
1192                                 /* now read the rest of the packet */
1193                                 ipsize =
1194                                     BYTE_TO_HOST(DOFF_ALIGN
1195                                                  (ibuf.ipacket.packet_size));
1196                                 if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
1197                                         DL_ERROR("Bad image packet size %d",
1198                                                  ipsize);
1199                                         return;
1200                                 }
1201                                 dest = ibuf.bufr;
1202 #ifdef OPT_ZERO_COPY_LOADER
1203                                 zero_copy = false;
1204                                 if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
1205                                         dlthis->myio->writemem(dlthis->myio,
1206                                                                &dest,
1207                                                                lptr->load_addr +
1208                                                                image_offset,
1209                                                                lptr, 0);
1210                                         zero_copy = (dest != ibuf.bufr);
1211                                 }
1212 #endif
1213                                 /* End of determination */
1214
1215                                 if (dlthis->strm->read_buffer(dlthis->strm,
1216                                                               ibuf.bufr,
1217                                                               ipsize) !=
1218                                     ipsize) {
1219                                         DL_ERROR(readstrm, imagepak);
1220                                         return;
1221                                 }
1222                                 ibuf.ipacket.img_data = dest;
1223
1224                                 /* reorder the bytes if need be */
1225 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
1226                                 if (dlthis->reorder_map) {
1227                                         dload_reorder(dest, ipsize,
1228                                                       dlthis->reorder_map);
1229                                 }
1230                                 checks = dload_checksum(dest, ipsize);
1231 #else
1232                                 if (dlthis->dfile_hdr.df_byte_reshuffle !=
1233                                     TARGET_ORDER(REORDER_MAP
1234                                                  (BYTE_RESHUFFLE_VALUE))) {
1235                                         /* put image bytes in big-endian order,
1236                                          * not PC order */
1237                                         dload_reorder(dest, ipsize,
1238                                                       TARGET_ORDER
1239                                                       (dlthis->dfile_hdr.
1240                                                        df_byte_reshuffle));
1241                                 }
1242 #if TARGET_AU_BITS > 8
1243                                 checks = dload_reverse_checksum16(dest, ipsize);
1244 #else
1245                                 checks = dload_reverse_checksum(dest, ipsize);
1246 #endif
1247 #endif
1248
1249                                 checks += dload_checksum(&ibuf.ipacket,
1250                                                          IPH_SIZE);
1251                                 /* relocate the image bits as needed */
1252                                 if (ibuf.ipacket.num_relocs) {
1253                                         dlthis->image_offset = image_offset;
1254                                         if (!relocate_packet(dlthis,
1255                                                              &ibuf.ipacket,
1256                                                              &checks,
1257                                                              &tramp_generated))
1258                                                 return; /* serious error */
1259                                 }
1260                                 if (~checks)
1261                                         DL_ERROR(err_checksum, imagepak);
1262                                 /* Only write the result to the target if no
1263                                  * trampoline was generated.  Otherwise it
1264                                  *will be done during trampoline finalize. */
1265
1266                                 if (tramp_generated == false) {
1267
1268                                         /* stuff the result into target
1269                                          * memory */
1270                                         if (DLOAD_SECT_TYPE(sptr) ==
1271                                             DLOAD_CINIT) {
1272                                                 cload_cinit(dlthis,
1273                                                             &ibuf.ipacket);
1274                                                 cinit_processed = true;
1275                                         } else {
1276 #ifdef OPT_ZERO_COPY_LOADER
1277                                                 if (!zero_copy) {
1278 #endif
1279                                                         /* FIXME */
1280                                                         if (!dlthis->myio->
1281                                                             writemem(dlthis->
1282                                                                 myio,
1283                                                                 ibuf.bufr,
1284                                                                 lptr->
1285                                                                 load_addr +
1286                                                                 image_offset,
1287                                                                 lptr,
1288                                                                 BYTE_TO_HOST
1289                                                                 (ibuf.
1290                                                                 ipacket.
1291                                                                 packet_size))) {
1292                                                                 DL_ERROR
1293                                                                   ("Write to "
1294                                                                   FMT_UI32
1295                                                                   " failed",
1296                                                                   lptr->
1297                                                                   load_addr +
1298                                                                   image_offset);
1299                                                         }
1300 #ifdef OPT_ZERO_COPY_LOADER
1301                                                 }
1302 #endif
1303                                         }
1304                                 }
1305                                 image_offset +=
1306                                     BYTE_TO_TADDR(ibuf.ipacket.packet_size);
1307                         }       /* process packets */
1308                         /* if this is a BSS section, we may want to fill it */
1309                         if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
1310                                 goto loop_cont;
1311
1312                         if (!(dlthis->myoptions & DLOAD_INITBSS))
1313                                 goto loop_cont;
1314
1315                         if (cinit_processed) {
1316                                 /* Don't clear BSS after load-time
1317                                  * initialization */
1318                                 DL_ERROR
1319                                     ("Zero-initialization at " FMT_UI32
1320                                      " after " "load-time initialization!",
1321                                      lptr->load_addr);
1322                                 goto loop_cont;
1323                         }
1324                         /* fill the .bss area */
1325                         dlthis->myio->fillmem(dlthis->myio,
1326                                               TADDR_TO_HOST(lptr->load_addr),
1327                                               lptr, TADDR_TO_HOST(lptr->size),
1328                                               DLOAD_FILL_BSS);
1329                         goto loop_cont;
1330                 }
1331                 /* if DS_DOWNLOAD_MASK */
1332                 /* If not loading, but BSS, zero initialize */
1333                 if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
1334                         goto loop_cont;
1335
1336                 if (!(dlthis->myoptions & DLOAD_INITBSS))
1337                         goto loop_cont;
1338
1339                 if (curr_sect >= dlthis->allocated_secn_count)
1340                         lptr = DOFFSEC_IS_LDRSEC(sptr);
1341
1342                 if (cinit_processed) {
1343                         /*Don't clear BSS after load-time initialization */
1344                         DL_ERROR("Zero-initialization at " FMT_UI32
1345                                  " attempted after "
1346                                  "load-time initialization!", lptr->load_addr);
1347                         goto loop_cont;
1348                 }
1349                 /* fill the .bss area */
1350                 dlthis->myio->fillmem(dlthis->myio,
1351                                       TADDR_TO_HOST(lptr->load_addr), lptr,
1352                                       TADDR_TO_HOST(lptr->size),
1353                                       DLOAD_FILL_BSS);
1354 loop_cont:
1355                 sptr += 1;
1356                 lptr += 1;
1357         }                       /* load sections */
1358
1359         /*  Finalize any trampolines that were created during the load */
1360         if (dload_tramp_finalize(dlthis) == 0) {
1361                 DL_ERROR("Finalization of auto-trampolines (size = " FMT_UI32
1362                          ") failed", dlthis->tramp.tramp_sect_next_addr);
1363         }
1364 }                               /* dload_data */
1365
1366 /*************************************************************************
1367  * Procedure dload_reorder
1368  *
1369  * Parameters:
1370  *      data    32-bit aligned pointer to data to be byte-swapped
1371  *      dsiz    size of the data to be reordered in sizeof() units.
1372  *      map             32-bit map defining how to reorder the data.  Value
1373  *                      must be REORDER_MAP() of some permutation
1374  *                      of 0x00 01 02 03
1375  *
1376  * Effect:
1377  *      Re-arranges the bytes in each word according to the map specified.
1378  *
1379  *********************************************************************** */
1380 /* mask for byte shift count */
1381 #define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
1382
1383 void dload_reorder(void *data, int dsiz, unsigned int map)
1384 {
1385         register u32 tmp, tmap, datv;
1386         u32 *dp = (u32 *) data;
1387
1388         map <<= LOG_BITS_PER_BYTE;      /* align map with SHIFT_COUNT_MASK */
1389         do {
1390                 tmp = 0;
1391                 datv = *dp;
1392                 tmap = map;
1393                 do {
1394                         tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
1395                         tmap >>= BITS_PER_BYTE;
1396                 } while (datv >>= BITS_PER_BYTE);
1397                 *dp++ = tmp;
1398         } while ((dsiz -= sizeof(u32)) > 0);
1399 }                               /* dload_reorder */
1400
1401 /*************************************************************************
1402  * Procedure dload_checksum
1403  *
1404  * Parameters:
1405  *      data    32-bit aligned pointer to data to be checksummed
1406  *      siz             size of the data to be checksummed in sizeof() units.
1407  *
1408  * Effect:
1409  *      Returns a checksum of the specified block
1410  *
1411  *********************************************************************** */
1412 u32 dload_checksum(void *data, unsigned siz)
1413 {
1414         u32 sum;
1415         u32 *dp;
1416         int left;
1417
1418         sum = 0;
1419         dp = (u32 *) data;
1420         for (left = siz; left > 0; left -= sizeof(u32))
1421                 sum += *dp++;
1422         return sum;
1423 }                               /* dload_checksum */
1424
1425 #if HOST_ENDIANNESS
1426 /*************************************************************************
1427  * Procedure dload_reverse_checksum
1428  *
1429  * Parameters:
1430  *      data    32-bit aligned pointer to data to be checksummed
1431  *      siz             size of the data to be checksummed in sizeof() units.
1432  *
1433  * Effect:
1434  *      Returns a checksum of the specified block, which is assumed to be bytes
1435  * in big-endian order.
1436  *
1437  * Notes:
1438  *      In a big-endian host, things like the string table are stored as bytes
1439  * in host order. But dllcreate always checksums in little-endian order.
1440  * It is most efficient to just handle the difference a word at a time.
1441  *
1442  ********************************************************************** */
1443 u32 dload_reverse_checksum(void *data, unsigned siz)
1444 {
1445         u32 sum, temp;
1446         u32 *dp;
1447         int left;
1448
1449         sum = 0;
1450         dp = (u32 *) data;
1451
1452         for (left = siz; left > 0; left -= sizeof(u32)) {
1453                 temp = *dp++;
1454                 sum += temp << BITS_PER_BYTE * 3;
1455                 sum += temp >> BITS_PER_BYTE * 3;
1456                 sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
1457                 sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
1458         }
1459
1460         return sum;
1461 }                               /* dload_reverse_checksum */
1462
1463 #if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
1464 u32 dload_reverse_checksum16(void *data, unsigned siz)
1465 {
1466         uint_fast32_t sum, temp;
1467         u32 *dp;
1468         int left;
1469
1470         sum = 0;
1471         dp = (u32 *) data;
1472
1473         for (left = siz; left > 0; left -= sizeof(u32)) {
1474                 temp = *dp++;
1475                 sum += temp << BITS_PER_BYTE * 2;
1476                 sum += temp >> BITS_PER_BYTE * 2;
1477         }
1478
1479         return sum;
1480 }                               /* dload_reverse_checksum16 */
1481 #endif
1482 #endif
1483
1484 /*************************************************************************
1485  * Procedure swap_words
1486  *
1487  * Parameters:
1488  *      data    32-bit aligned pointer to data to be swapped
1489  *      siz     size of the data to be swapped.
1490  *      bitmap  Bit map of how to swap each 32-bit word; 1 => 2 shorts,
1491  *              0 => 1 long
1492  *
1493  * Effect:
1494  *      Swaps the specified data according to the specified map
1495  *
1496  *********************************************************************** */
1497 static void swap_words(void *data, unsigned siz, unsigned bitmap)
1498 {
1499         register int i;
1500 #if TARGET_AU_BITS < 16
1501         register u16 *sp;
1502 #endif
1503         register u32 *lp;
1504
1505         siz /= sizeof(u16);
1506
1507 #if TARGET_AU_BITS < 16
1508         /* pass 1: do all the bytes */
1509         i = siz;
1510         sp = (u16 *) data;
1511         do {
1512                 register u16 tmp;
1513                 tmp = *sp;
1514                 *sp++ = SWAP16BY8(tmp);
1515         } while ((i -= 1) > 0);
1516 #endif
1517
1518 #if TARGET_AU_BITS < 32
1519         /* pass 2: fixup the 32-bit words */
1520         i = siz >> 1;
1521         lp = (u32 *) data;
1522         do {
1523                 if ((bitmap & 1) == 0) {
1524                         register u32 tmp;
1525                         tmp = *lp;
1526                         *lp = SWAP32BY16(tmp);
1527                 }
1528                 lp += 1;
1529                 bitmap >>= 1;
1530         } while ((i -= 1) > 0);
1531 #endif
1532 }                               /* swap_words */
1533
1534 /*************************************************************************
1535  * Procedure copy_tgt_strings
1536  *
1537  * Parameters:
1538  *      dstp            Destination address.  Assumed to be 32-bit aligned
1539  *      srcp            Source address.  Assumed to be 32-bit aligned
1540  *      charcount       Number of characters to copy.
1541  *
1542  * Effect:
1543  *      Copies strings from the source (which is in usual .dof file order on
1544  * the loading processor) to the destination buffer (which should be in proper
1545  * target addressable unit order).  Makes sure the last string in the
1546  * buffer is NULL terminated (for safety).
1547  * Returns the first unused destination address.
1548  *********************************************************************** */
1549 static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
1550 {
1551         register tgt_au_t *src = (tgt_au_t *) srcp;
1552         register tgt_au_t *dst = (tgt_au_t *) dstp;
1553         register int cnt = charcount;
1554         do {
1555 #if TARGET_AU_BITS <= BITS_PER_AU
1556                 /* byte-swapping issues may exist for strings on target */
1557                 *dst++ = *src++;
1558 #else
1559                 *dst++ = *src++;
1560 #endif
1561         } while ((cnt -= (sizeof(tgt_au_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
1562         /*apply force to make sure that the string table has null terminator */
1563 #if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
1564         dst[-1] = 0;
1565 #else
1566         /* little endian */
1567         dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1;
1568 #endif
1569         return (char *)dst;
1570 }                               /* copy_tgt_strings */
1571
1572 /*************************************************************************
1573  * Procedure init_module_handle
1574  *
1575  * Parameters:
1576  *      none
1577  *
1578  * Effect:
1579  *      Initializes the module handle we use to enable unloading, and installs
1580  * the debug information required by the target.
1581  *
1582  * Notes:
1583  * The handle returned from dynamic_load_module needs to encapsulate all the
1584  * allocations done for the module, and enable them plus the modules symbols to
1585  * be deallocated.
1586  *
1587  *********************************************************************** */
1588 #ifndef _BIG_ENDIAN
1589 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1590         (ldr_addr)-1, DBG_LIST_PAGE, DLOAD_DATA, 0
1591 };
1592 #else
1593 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1594         (ldr_addr)-1, DLOAD_DATA, DBG_LIST_PAGE, 0
1595 };
1596 #endif
1597 static void init_module_handle(struct dload_state *dlthis)
1598 {
1599         struct my_handle *hndl;
1600         u16 curr_sect;
1601         struct ldr_section_info *asecs;
1602         struct dll_module *dbmod;
1603         struct dll_sect *dbsec;
1604         struct dbg_mirror_root *mlist;
1605         register char *cp;
1606         struct modules_header mhdr;
1607         struct ldr_section_info dllview_info;
1608         struct dynload_symbol *debug_mirror_sym;
1609         hndl = dlthis->myhandle;
1610         if (!hndl)
1611                 return;         /* must be errors detected, so forget it */
1612
1613         /*  Store the section count */
1614         hndl->secn_count = dlthis->allocated_secn_count;
1615
1616         /*  If a trampoline section was created, add it in */
1617         if (dlthis->tramp.tramp_sect_next_addr != 0)
1618                 hndl->secn_count += 1;
1619
1620         hndl->secn_count = hndl->secn_count << 1;
1621
1622         hndl->secn_count = dlthis->allocated_secn_count << 1;
1623 #ifndef TARGET_ENDIANNESS
1624         if (dlthis->big_e_target)
1625                 hndl->secn_count += 1;  /* flag for big-endian */
1626 #endif
1627         if (dlthis->dload_errcount)
1628                 return;         /* abandon if errors detected */
1629         /* Locate the symbol that names the header for the CCS debug list
1630            of modules. If not found, we just don't generate the debug record.
1631            If found, we create our modules list.  We make sure to create the
1632            loader_dllview_root even if there is no relocation info to record,
1633            just to try to put both symbols in the same symbol table and
1634            module. */
1635         debug_mirror_sym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1636                                                         loader_dllview_root);
1637         if (!debug_mirror_sym) {
1638                 struct dynload_symbol *dlmodsym;
1639                 struct dbg_mirror_root *mlst;
1640
1641                 /* our root symbol is not yet present;
1642                    check if we have DLModules defined */
1643                 dlmodsym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1644                                                         LINKER_MODULES_HEADER);
1645                 if (!dlmodsym)
1646                         return; /* no DLModules list so no debug info */
1647                 /* if we have DLModules defined, construct our header */
1648                 mlst = (struct dbg_mirror_root *)
1649                     dlthis->mysym->dload_allocate(dlthis->mysym,
1650                                                   sizeof(struct
1651                                                          dbg_mirror_root));
1652                 if (!mlst) {
1653                         DL_ERROR(err_alloc, sizeof(struct dbg_mirror_root));
1654                         return;
1655                 }
1656                 mlst->hnext = NULL;
1657                 mlst->changes = 0;
1658                 mlst->refcount = 0;
1659                 mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
1660                 /* add our root symbol */
1661                 debug_mirror_sym = dlthis->mysym->add_to_symbol_table
1662                     (dlthis->mysym, loader_dllview_root,
1663                      (unsigned)dlthis->myhandle);
1664                 if (!debug_mirror_sym) {
1665                         /* failed, recover memory */
1666                         dlthis->mysym->dload_deallocate(dlthis->mysym, mlst);
1667                         return;
1668                 }
1669                 debug_mirror_sym->value = (u32) mlst;
1670         }
1671         /* First create the DLLview record and stuff it into the buffer.
1672            Then write it to the DSP.  Record pertinent locations in our hndl,
1673            and add it to the per-processor list of handles with debug info. */
1674 #ifndef DEBUG_HEADER_IN_LOADER
1675         mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
1676         if (!mlist)
1677                 return;
1678 #else
1679         mlist = (struct dbg_mirror_root *)&debug_list_header;
1680 #endif
1681         hndl->dm.hroot = mlist; /* set pointer to root into our handle */
1682         if (!dlthis->allocated_secn_count)
1683                 return;         /* no load addresses to be recorded */
1684         /* reuse temporary symbol storage */
1685         dbmod = (struct dll_module *)dlthis->local_symtab;
1686         /* Create the DLLview record in the memory we retain for our handle */
1687         dbmod->num_sects = dlthis->allocated_secn_count;
1688         dbmod->timestamp = dlthis->verify.dv_timdat;
1689         dbmod->version = INIT_VERSION;
1690         dbmod->verification = VERIFICATION;
1691         asecs = dlthis->ldr_sections;
1692         dbsec = dbmod->sects;
1693         for (curr_sect = dlthis->allocated_secn_count;
1694              curr_sect > 0; curr_sect -= 1) {
1695                 dbsec->sect_load_adr = asecs->load_addr;
1696                 dbsec->sect_run_adr = asecs->run_addr;
1697                 dbsec += 1;
1698                 asecs += 1;
1699         }
1700
1701         /*  If a trampoline section was created go ahead and add its info */
1702         if (dlthis->tramp.tramp_sect_next_addr != 0) {
1703                 dbmod->num_sects++;
1704                 dbsec->sect_load_adr = asecs->load_addr;
1705                 dbsec->sect_run_adr = asecs->run_addr;
1706                 dbsec++;
1707                 asecs++;
1708         }
1709
1710         /* now cram in the names */
1711         cp = copy_tgt_strings(dbsec, dlthis->str_head,
1712                               dlthis->debug_string_size);
1713
1714         /* If a trampoline section was created, add its name so DLLView
1715          * can show the user the section info. */
1716         if (dlthis->tramp.tramp_sect_next_addr != 0) {
1717                 cp = copy_tgt_strings(cp,
1718                                       dlthis->tramp.final_string_table,
1719                                       strlen(dlthis->tramp.final_string_table) +
1720                                       1);
1721         }
1722
1723         /* round off the size of the debug record, and remember same */
1724         hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
1725         *cp = 0;                /* strictly to make our test harness happy */
1726         dllview_info = dllview_info_init;
1727         dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1728         /* Initialize memory context to default heap */
1729         dllview_info.context = 0;
1730         hndl->dm.context = 0;
1731         /* fill in next pointer and size */
1732         if (mlist->hnext) {
1733                 dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
1734                 dbmod->next_module_size = mlist->hnext->dm.dbsiz;
1735         } else {
1736                 dbmod->next_module_size = 0;
1737                 dbmod->next_module = 0;
1738         }
1739         /* allocate memory for on-DSP DLLview debug record */
1740         if (!dlthis->myalloc)
1741                 return;
1742         if (!dlthis->myalloc->dload_allocate(dlthis->myalloc, &dllview_info,
1743                                              HOST_TO_TADDR(sizeof(u32)))) {
1744                 return;
1745         }
1746         /* Store load address of .dllview section */
1747         hndl->dm.dbthis = dllview_info.load_addr;
1748         /* Store memory context (segid) in which .dllview section
1749          * was  allocated */
1750         hndl->dm.context = dllview_info.context;
1751         mlist->refcount += 1;
1752         /* swap bytes in the entire debug record, but not the string table */
1753         if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1754                 swap_words(dbmod, (char *)dbsec - (char *)dbmod,
1755                            DLL_MODULE_BITMAP);
1756         }
1757         /* Update the DLLview list on the DSP write new record */
1758         if (!dlthis->myio->writemem(dlthis->myio, dbmod,
1759                                     dllview_info.load_addr, &dllview_info,
1760                                     TADDR_TO_HOST(dllview_info.size))) {
1761                 return;
1762         }
1763         /* write new header */
1764         mhdr.first_module_size = hndl->dm.dbsiz;
1765         mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
1766         /* swap bytes in the module header, if needed */
1767         if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1768                 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1769                            MODULES_HEADER_BITMAP);
1770         }
1771         dllview_info = dllview_info_init;
1772         if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
1773                                     &dllview_info,
1774                                     sizeof(struct modules_header) -
1775                                     sizeof(u16))) {
1776                 return;
1777         }
1778         /* Add the module handle to this processor's list
1779            of handles with debug info */
1780         hndl->dm.hnext = mlist->hnext;
1781         if (hndl->dm.hnext)
1782                 hndl->dm.hnext->dm.hprev = hndl;
1783         hndl->dm.hprev = (struct my_handle *)mlist;
1784         mlist->hnext = hndl;    /* insert after root */
1785 }                               /* init_module_handle */
1786
1787 /*************************************************************************
1788  * Procedure dynamic_unload_module
1789  *
1790  * Parameters:
1791  *      mhandle A module handle from dynamic_load_module
1792  *      syms    Host-side symbol table and malloc/free functions
1793  *      alloc   Target-side memory allocation
1794  *
1795  * Effect:
1796  *      The module specified by mhandle is unloaded.  Unloading causes all
1797  * target memory to be deallocated, all symbols defined by the module to
1798  * be purged, and any host-side storage used by the dynamic loader for
1799  * this module to be released.
1800  *
1801  * Returns:
1802  *      Zero for success. On error, the number of errors detected is returned.
1803  * Individual errors are reported using syms->error_report().
1804  *********************************************************************** */
1805 int dynamic_unload_module(void *mhandle,
1806                           struct dynamic_loader_sym *syms,
1807                           struct dynamic_loader_allocate *alloc,
1808                           struct dynamic_loader_initialize *init)
1809 {
1810         s16 curr_sect;
1811         struct ldr_section_info *asecs;
1812         struct my_handle *hndl;
1813         struct dbg_mirror_root *root;
1814         unsigned errcount = 0;
1815         struct ldr_section_info dllview_info = dllview_info_init;
1816         struct modules_header mhdr;
1817
1818         hndl = (struct my_handle *)mhandle;
1819         if (!hndl)
1820                 return 0;       /* if handle is null, nothing to do */
1821         /* Clear out the module symbols
1822          * Note that if this is the module that defined MODULES_HEADER
1823          (the head of the target debug list)
1824          * then this operation will blow away that symbol.
1825          It will therefore be impossible for subsequent
1826          * operations to add entries to this un-referenceable list. */
1827         if (!syms)
1828                 return 1;
1829         syms->purge_symbol_table(syms, (unsigned)hndl);
1830         /* Deallocate target memory for sections
1831          * NOTE: The trampoline section, if created, gets deleted here, too */
1832
1833         asecs = hndl->secns;
1834         if (alloc)
1835                 for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
1836                      curr_sect -= 1) {
1837                         asecs->name = NULL;
1838                         alloc->dload_deallocate(alloc, asecs++);
1839                 }
1840         root = hndl->dm.hroot;
1841         if (!root) {
1842                 /* there is a debug list containing this module */
1843                 goto func_end;
1844         }
1845         if (!hndl->dm.dbthis) { /* target-side dllview record exists */
1846                 goto loop_end;
1847         }
1848         /* Retrieve memory context in which .dllview was allocated */
1849         dllview_info.context = hndl->dm.context;
1850         if (hndl->dm.hprev == hndl)
1851                 goto exitunltgt;
1852
1853         /* target-side dllview record is in list */
1854         /* dequeue this record from our GPP-side mirror list */
1855         hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
1856         if (hndl->dm.hnext)
1857                 hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
1858         /* Update next_module of previous entry in target list
1859          * We are using mhdr here as a surrogate for either a
1860          struct modules_header or a dll_module */
1861         if (hndl->dm.hnext) {
1862                 mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
1863                 mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
1864         } else {
1865                 mhdr.first_module = 0;
1866                 mhdr.first_module_size = 0;
1867         }
1868         if (!init)
1869                 goto exitunltgt;
1870
1871         if (!init->connect(init)) {
1872                 dload_syms_error(syms, iconnect);
1873                 errcount += 1;
1874                 goto exitunltgt;
1875         }
1876         /* swap bytes in the module header, if needed */
1877         if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
1878                 swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1879                            MODULES_HEADER_BITMAP);
1880         }
1881         if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
1882                             &dllview_info, sizeof(struct modules_header) -
1883                             sizeof(mhdr.update_flag))) {
1884                 dload_syms_error(syms, dlvwrite);
1885                 errcount += 1;
1886         }
1887         /* update change counter */
1888         root->changes += 1;
1889         if (!init->writemem(init, &(root->changes),
1890                             root->dbthis + HOST_TO_TADDR
1891                             (sizeof(mhdr.first_module) +
1892                              sizeof(mhdr.first_module_size)),
1893                             &dllview_info, sizeof(mhdr.update_flag))) {
1894                 dload_syms_error(syms, dlvwrite);
1895                 errcount += 1;
1896         }
1897         init->release(init);
1898 exitunltgt:
1899         /* release target storage */
1900         dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1901         dllview_info.load_addr = hndl->dm.dbthis;
1902         if (alloc)
1903                 alloc->dload_deallocate(alloc, &dllview_info);
1904         root->refcount -= 1;
1905         /* target-side dllview record exists */
1906 loop_end:
1907 #ifndef DEBUG_HEADER_IN_LOADER
1908         if (root->refcount <= 0) {
1909                 /* if all references gone, blow off the header */
1910                 /* our root symbol may be gone due to the Purge above,
1911                    but if not, do not destroy the root */
1912                 if (syms->find_matching_symbol
1913                     (syms, loader_dllview_root) == NULL)
1914                         syms->dload_deallocate(syms, root);
1915         }
1916 #endif
1917 func_end:
1918         /* there is a debug list containing this module */
1919         syms->dload_deallocate(syms, mhandle);  /* release our storage */
1920         return errcount;
1921 }                               /* dynamic_unload_module */
1922
1923 #if BITS_PER_AU > BITS_PER_BYTE
1924 /*************************************************************************
1925  * Procedure unpack_name
1926  *
1927  * Parameters:
1928  *      soffset Byte offset into the string table
1929  *
1930  * Effect:
1931  *      Returns a pointer to the string specified by the offset supplied, or
1932  * NULL for error.
1933  *
1934  *********************************************************************** */
1935 static char *unpack_name(struct dload_state *dlthis, u32 soffset)
1936 {
1937         u8 tmp, *src;
1938         char *dst;
1939
1940         if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
1941                 dload_error(dlthis, "Bad string table offset " FMT_UI32,
1942                             soffset);
1943                 return NULL;
1944         }
1945         src = (uint_least8_t *) dlthis->str_head +
1946             (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
1947         dst = dlthis->str_temp;
1948         if (soffset & 1)
1949                 *dst++ = *src++;        /* only 1 character in first word */
1950         do {
1951                 tmp = *src++;
1952                 *dst = (tmp >> BITS_PER_BYTE);
1953                 if (!(*dst++))
1954                         break;
1955         } while ((*dst++ = tmp & BYTE_MASK));
1956         dlthis->temp_len = dst - dlthis->str_temp;
1957         /* squirrel away length including terminating null */
1958         return dlthis->str_temp;
1959 }                               /* unpack_name */
1960 #endif