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