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  *********************************************************************** */
dload_error(struct dload_state * dlthis,const char * errtxt,...)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  *********************************************************************** */
dload_syms_error(struct dynamic_loader_sym * syms,const char * errtxt,...)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  ********************************************************************** */
dynamic_load_module(struct dynamic_loader_stream * module,struct dynamic_loader_sym * syms,struct dynamic_loader_allocate * alloc,struct dynamic_loader_initialize * init,unsigned options,void ** mhandle)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
dynamic_open_module(struct dynamic_loader_stream * module,struct dynamic_loader_sym * syms,struct dynamic_loader_allocate * alloc,struct dynamic_loader_initialize * init,unsigned options,void ** mhandle)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 
dload_headers(struct dload_state * dlthis)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  *********************************************************************** */
dload_sections(struct dload_state * dlthis)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  **************************************************************************** */
allocate_sections(struct dload_state * dlthis)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.next = hndl->dm.prev = hndl;	/* circular list */
502 	hndl->dm.root = 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  *********************************************************************** */
section_table_free(struct dload_state * dlthis)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 
dload_strings(struct dload_state * dlthis,bool sec_names_only)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  ************************************************************************ */
string_table_free(struct dload_state * dlthis)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 
dload_symbols(struct dload_state * dlthis)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 doesn'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  **************************************************************************** */
symbol_table_free(struct dload_state * dlthis)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  *********************************************************************** */
cload_cinit(struct dload_state * dlthis,struct image_packet_t * ipacket)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 */
relocate_packet(struct dload_state * dlthis,struct image_packet_t * ipacket,u32 * checks,bool * tramps_generated)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  *********************************************************************** */
dload_data(struct dload_state * dlthis)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 	u8 *dest;
1135 
1136 	struct {
1137 		struct image_packet_t ipacket;
1138 		u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
1139 	} ibuf;
1140 
1141 	/* Indicates whether CINIT processing has occurred */
1142 	bool cinit_processed = false;
1143 
1144 	/* Loop through the sections and load them one at a time.
1145 	 */
1146 	for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
1147 	     curr_sect += 1) {
1148 		if (ds_needs_download(sptr)) {
1149 			s32 nip;
1150 			ldr_addr image_offset = 0;
1151 			/* set relocation info for this section */
1152 			if (curr_sect < dlthis->allocated_secn_count)
1153 				dlthis->delta_runaddr = sptr->ds_paddr;
1154 			else {
1155 				lptr = (struct ldr_section_info *)sptr;
1156 				dlthis->delta_runaddr = 0;
1157 			}
1158 			dlthis->image_secn = lptr;
1159 #if BITS_PER_AU > BITS_PER_BYTE
1160 			lptr->name = unpack_name(dlthis, sptr->ds_offset);
1161 #endif
1162 			nip = sptr->ds_nipacks;
1163 			while ((nip -= 1) >= 0) {	/* process packets */
1164 
1165 				s32 ipsize;
1166 				u32 checks;
1167 				bool tramp_generated = false;
1168 
1169 				/* get the fixed header bits */
1170 				if (dlthis->strm->read_buffer(dlthis->strm,
1171 							      &ibuf.ipacket,
1172 							      IPH_SIZE) !=
1173 				    IPH_SIZE) {
1174 					DL_ERROR(readstrm, imagepak);
1175 					return;
1176 				}
1177 				/* reorder the header if need be */
1178 				if (dlthis->reorder_map) {
1179 					dload_reorder(&ibuf.ipacket, IPH_SIZE,
1180 						      dlthis->reorder_map);
1181 				}
1182 				/* now read the rest of the packet */
1183 				ipsize =
1184 				    BYTE_TO_HOST(DOFF_ALIGN
1185 						 (ibuf.ipacket.packet_size));
1186 				if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
1187 					DL_ERROR("Bad image packet size %d",
1188 						 ipsize);
1189 					return;
1190 				}
1191 				dest = ibuf.bufr;
1192 				/* End of determination */
1193 
1194 				if (dlthis->strm->read_buffer(dlthis->strm,
1195 							      ibuf.bufr,
1196 							      ipsize) !=
1197 				    ipsize) {
1198 					DL_ERROR(readstrm, imagepak);
1199 					return;
1200 				}
1201 				ibuf.ipacket.img_data = dest;
1202 
1203 				/* reorder the bytes if need be */
1204 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
1205 				if (dlthis->reorder_map) {
1206 					dload_reorder(dest, ipsize,
1207 						      dlthis->reorder_map);
1208 				}
1209 				checks = dload_checksum(dest, ipsize);
1210 #else
1211 				if (dlthis->dfile_hdr.df_byte_reshuffle !=
1212 				    TARGET_ORDER(REORDER_MAP
1213 						 (BYTE_RESHUFFLE_VALUE))) {
1214 					/* put image bytes in big-endian order,
1215 					 * not PC order */
1216 					dload_reorder(dest, ipsize,
1217 						      TARGET_ORDER
1218 						      (dlthis->dfile_hdr.
1219 						       df_byte_reshuffle));
1220 				}
1221 #if TARGET_AU_BITS > 8
1222 				checks = dload_reverse_checksum16(dest, ipsize);
1223 #else
1224 				checks = dload_reverse_checksum(dest, ipsize);
1225 #endif
1226 #endif
1227 
1228 				checks += dload_checksum(&ibuf.ipacket,
1229 							 IPH_SIZE);
1230 				/* relocate the image bits as needed */
1231 				if (ibuf.ipacket.num_relocs) {
1232 					dlthis->image_offset = image_offset;
1233 					if (!relocate_packet(dlthis,
1234 							     &ibuf.ipacket,
1235 							     &checks,
1236 							     &tramp_generated))
1237 						return;	/* serious error */
1238 				}
1239 				if (~checks)
1240 					DL_ERROR(err_checksum, imagepak);
1241 				/* Only write the result to the target if no
1242 				 * trampoline was generated.  Otherwise it
1243 				 *will be done during trampoline finalize. */
1244 
1245 				if (tramp_generated == false) {
1246 
1247 					/* stuff the result into target
1248 					 * memory */
1249 					if (dload_check_type(sptr,
1250 						DLOAD_CINIT)) {
1251 						cload_cinit(dlthis,
1252 							    &ibuf.ipacket);
1253 						cinit_processed = true;
1254 					} else {
1255 						/* FIXME */
1256 						if (!dlthis->myio->
1257 						    writemem(dlthis->
1258 							myio,
1259 							ibuf.bufr,
1260 							lptr->
1261 							load_addr +
1262 							image_offset,
1263 							lptr,
1264 							BYTE_TO_HOST
1265 							(ibuf.
1266 							ipacket.
1267 							packet_size))) {
1268 							DL_ERROR
1269 							  ("Write to "
1270 							  FMT_UI32
1271 							  " failed",
1272 							  lptr->
1273 							  load_addr +
1274 							  image_offset);
1275 						}
1276 					}
1277 				}
1278 				image_offset +=
1279 				    BYTE_TO_TADDR(ibuf.ipacket.packet_size);
1280 			}	/* process packets */
1281 			/* if this is a BSS section, we may want to fill it */
1282 			if (!dload_check_type(sptr, DLOAD_BSS))
1283 				goto loop_cont;
1284 
1285 			if (!(dlthis->myoptions & DLOAD_INITBSS))
1286 				goto loop_cont;
1287 
1288 			if (cinit_processed) {
1289 				/* Don't clear BSS after load-time
1290 				 * initialization */
1291 				DL_ERROR
1292 				    ("Zero-initialization at " FMT_UI32
1293 				     " after " "load-time initialization!",
1294 				     lptr->load_addr);
1295 				goto loop_cont;
1296 			}
1297 			/* fill the .bss area */
1298 			dlthis->myio->fillmem(dlthis->myio,
1299 					      TADDR_TO_HOST(lptr->load_addr),
1300 					      lptr, TADDR_TO_HOST(lptr->size),
1301 					      DLOAD_FILL_BSS);
1302 			goto loop_cont;
1303 		}
1304 		/* if DS_DOWNLOAD_MASK */
1305 		/* If not loading, but BSS, zero initialize */
1306 		if (!dload_check_type(sptr, DLOAD_BSS))
1307 			goto loop_cont;
1308 
1309 		if (!(dlthis->myoptions & DLOAD_INITBSS))
1310 			goto loop_cont;
1311 
1312 		if (curr_sect >= dlthis->allocated_secn_count)
1313 			lptr = (struct ldr_section_info *)sptr;
1314 
1315 		if (cinit_processed) {
1316 			/*Don't clear BSS after load-time initialization */
1317 			DL_ERROR("Zero-initialization at " FMT_UI32
1318 				 " attempted after "
1319 				 "load-time initialization!", lptr->load_addr);
1320 			goto loop_cont;
1321 		}
1322 		/* fill the .bss area */
1323 		dlthis->myio->fillmem(dlthis->myio,
1324 				      TADDR_TO_HOST(lptr->load_addr), lptr,
1325 				      TADDR_TO_HOST(lptr->size),
1326 				      DLOAD_FILL_BSS);
1327 loop_cont:
1328 		sptr += 1;
1329 		lptr += 1;
1330 	}			/* load sections */
1331 
1332 	/*  Finalize any trampolines that were created during the load */
1333 	if (dload_tramp_finalize(dlthis) == 0) {
1334 		DL_ERROR("Finalization of auto-trampolines (size = " FMT_UI32
1335 			 ") failed", dlthis->tramp.tramp_sect_next_addr);
1336 	}
1337 }				/* dload_data */
1338 
1339 /*************************************************************************
1340  * Procedure dload_reorder
1341  *
1342  * Parameters:
1343  *	data	32-bit aligned pointer to data to be byte-swapped
1344  *	dsiz	size of the data to be reordered in sizeof() units.
1345  *	map		32-bit map defining how to reorder the data.  Value
1346  *			must be REORDER_MAP() of some permutation
1347  *			of 0x00 01 02 03
1348  *
1349  * Effect:
1350  *	Re-arranges the bytes in each word according to the map specified.
1351  *
1352  *********************************************************************** */
1353 /* mask for byte shift count */
1354 #define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
1355 
dload_reorder(void * data,int dsiz,unsigned int map)1356 void dload_reorder(void *data, int dsiz, unsigned int map)
1357 {
1358 	register u32 tmp, tmap, datv;
1359 	u32 *dp = (u32 *) data;
1360 
1361 	map <<= LOG_BITS_PER_BYTE;	/* align map with SHIFT_COUNT_MASK */
1362 	do {
1363 		tmp = 0;
1364 		datv = *dp;
1365 		tmap = map;
1366 		do {
1367 			tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
1368 			tmap >>= BITS_PER_BYTE;
1369 		} while (datv >>= BITS_PER_BYTE);
1370 		*dp++ = tmp;
1371 	} while ((dsiz -= sizeof(u32)) > 0);
1372 }				/* dload_reorder */
1373 
1374 /*************************************************************************
1375  * Procedure dload_checksum
1376  *
1377  * Parameters:
1378  *	data	32-bit aligned pointer to data to be checksummed
1379  *	siz		size of the data to be checksummed in sizeof() units.
1380  *
1381  * Effect:
1382  *	Returns a checksum of the specified block
1383  *
1384  *********************************************************************** */
dload_checksum(void * data,unsigned siz)1385 u32 dload_checksum(void *data, unsigned siz)
1386 {
1387 	u32 sum;
1388 	u32 *dp;
1389 	int left;
1390 
1391 	sum = 0;
1392 	dp = (u32 *) data;
1393 	for (left = siz; left > 0; left -= sizeof(u32))
1394 		sum += *dp++;
1395 	return sum;
1396 }				/* dload_checksum */
1397 
1398 #if HOST_ENDIANNESS
1399 /*************************************************************************
1400  * Procedure dload_reverse_checksum
1401  *
1402  * Parameters:
1403  *	data	32-bit aligned pointer to data to be checksummed
1404  *	siz		size of the data to be checksummed in sizeof() units.
1405  *
1406  * Effect:
1407  *	Returns a checksum of the specified block, which is assumed to be bytes
1408  * in big-endian order.
1409  *
1410  * Notes:
1411  *	In a big-endian host, things like the string table are stored as bytes
1412  * in host order. But dllcreate always checksums in little-endian order.
1413  * It is most efficient to just handle the difference a word at a time.
1414  *
1415  ********************************************************************** */
dload_reverse_checksum(void * data,unsigned siz)1416 u32 dload_reverse_checksum(void *data, unsigned siz)
1417 {
1418 	u32 sum, temp;
1419 	u32 *dp;
1420 	int left;
1421 
1422 	sum = 0;
1423 	dp = (u32 *) data;
1424 
1425 	for (left = siz; left > 0; left -= sizeof(u32)) {
1426 		temp = *dp++;
1427 		sum += temp << BITS_PER_BYTE * 3;
1428 		sum += temp >> BITS_PER_BYTE * 3;
1429 		sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
1430 		sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
1431 	}
1432 
1433 	return sum;
1434 }				/* dload_reverse_checksum */
1435 
1436 #if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
dload_reverse_checksum16(void * data,unsigned siz)1437 u32 dload_reverse_checksum16(void *data, unsigned siz)
1438 {
1439 	uint_fast32_t sum, temp;
1440 	u32 *dp;
1441 	int left;
1442 
1443 	sum = 0;
1444 	dp = (u32 *) data;
1445 
1446 	for (left = siz; left > 0; left -= sizeof(u32)) {
1447 		temp = *dp++;
1448 		sum += temp << BITS_PER_BYTE * 2;
1449 		sum += temp >> BITS_PER_BYTE * 2;
1450 	}
1451 
1452 	return sum;
1453 }				/* dload_reverse_checksum16 */
1454 #endif
1455 #endif
1456 
1457 /*************************************************************************
1458  * Procedure swap_words
1459  *
1460  * Parameters:
1461  *	data	32-bit aligned pointer to data to be swapped
1462  *	siz	size of the data to be swapped.
1463  *	bitmap	Bit map of how to swap each 32-bit word; 1 => 2 shorts,
1464  *		0 => 1 long
1465  *
1466  * Effect:
1467  *	Swaps the specified data according to the specified map
1468  *
1469  *********************************************************************** */
swap_words(void * data,unsigned siz,unsigned bitmap)1470 static void swap_words(void *data, unsigned siz, unsigned bitmap)
1471 {
1472 	register int i;
1473 #if TARGET_AU_BITS < 16
1474 	register u16 *sp;
1475 #endif
1476 	register u32 *lp;
1477 
1478 	siz /= sizeof(u16);
1479 
1480 #if TARGET_AU_BITS < 16
1481 	/* pass 1: do all the bytes */
1482 	i = siz;
1483 	sp = (u16 *) data;
1484 	do {
1485 		register u16 tmp;
1486 		tmp = *sp;
1487 		*sp++ = SWAP16BY8(tmp);
1488 	} while ((i -= 1) > 0);
1489 #endif
1490 
1491 #if TARGET_AU_BITS < 32
1492 	/* pass 2: fixup the 32-bit words */
1493 	i = siz >> 1;
1494 	lp = (u32 *) data;
1495 	do {
1496 		if ((bitmap & 1) == 0) {
1497 			register u32 tmp;
1498 			tmp = *lp;
1499 			*lp = SWAP32BY16(tmp);
1500 		}
1501 		lp += 1;
1502 		bitmap >>= 1;
1503 	} while ((i -= 1) > 0);
1504 #endif
1505 }				/* swap_words */
1506 
1507 /*************************************************************************
1508  * Procedure copy_tgt_strings
1509  *
1510  * Parameters:
1511  *	dstp		Destination address.  Assumed to be 32-bit aligned
1512  *	srcp		Source address.  Assumed to be 32-bit aligned
1513  *	charcount	Number of characters to copy.
1514  *
1515  * Effect:
1516  *	Copies strings from the source (which is in usual .dof file order on
1517  * the loading processor) to the destination buffer (which should be in proper
1518  * target addressable unit order).  Makes sure the last string in the
1519  * buffer is NULL terminated (for safety).
1520  * Returns the first unused destination address.
1521  *********************************************************************** */
copy_tgt_strings(void * dstp,void * srcp,unsigned charcount)1522 static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
1523 {
1524 	register tgt_au_t *src = (tgt_au_t *) srcp;
1525 	register tgt_au_t *dst = (tgt_au_t *) dstp;
1526 	register int cnt = charcount;
1527 	do {
1528 #if TARGET_AU_BITS <= BITS_PER_AU
1529 		/* byte-swapping issues may exist for strings on target */
1530 		*dst++ = *src++;
1531 #else
1532 		*dst++ = *src++;
1533 #endif
1534 	} while ((cnt -= (sizeof(tgt_au_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
1535 	/*apply force to make sure that the string table has null terminator */
1536 #if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
1537 	dst[-1] = 0;
1538 #else
1539 	/* little endian */
1540 	dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1;
1541 #endif
1542 	return (char *)dst;
1543 }				/* copy_tgt_strings */
1544 
1545 /*************************************************************************
1546  * Procedure init_module_handle
1547  *
1548  * Parameters:
1549  *	none
1550  *
1551  * Effect:
1552  *	Initializes the module handle we use to enable unloading, and installs
1553  * the debug information required by the target.
1554  *
1555  * Notes:
1556  * The handle returned from dynamic_load_module needs to encapsulate all the
1557  * allocations done for the module, and enable them plus the modules symbols to
1558  * be deallocated.
1559  *
1560  *********************************************************************** */
1561 #ifndef _BIG_ENDIAN
1562 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1563 	(ldr_addr)-1, DBG_LIST_PAGE, DLOAD_DATA, 0
1564 };
1565 #else
1566 static const struct ldr_section_info dllview_info_init = { ".dllview", 0, 0,
1567 	(ldr_addr)-1, DLOAD_DATA, DBG_LIST_PAGE, 0
1568 };
1569 #endif
init_module_handle(struct dload_state * dlthis)1570 static void init_module_handle(struct dload_state *dlthis)
1571 {
1572 	struct my_handle *hndl;
1573 	u16 curr_sect;
1574 	struct ldr_section_info *asecs;
1575 	struct dll_module *dbmod;
1576 	struct dll_sect *dbsec;
1577 	struct dbg_mirror_root *mlist;
1578 	register char *cp;
1579 	struct modules_header mhdr;
1580 	struct ldr_section_info dllview_info;
1581 	struct dynload_symbol *debug_mirror_sym;
1582 	hndl = dlthis->myhandle;
1583 	if (!hndl)
1584 		return;		/* must be errors detected, so forget it */
1585 
1586 	/*  Store the section count */
1587 	hndl->secn_count = dlthis->allocated_secn_count;
1588 
1589 	/*  If a trampoline section was created, add it in */
1590 	if (dlthis->tramp.tramp_sect_next_addr != 0)
1591 		hndl->secn_count += 1;
1592 
1593 	hndl->secn_count = hndl->secn_count << 1;
1594 
1595 	hndl->secn_count = dlthis->allocated_secn_count << 1;
1596 #ifndef TARGET_ENDIANNESS
1597 	if (dlthis->big_e_target)
1598 		hndl->secn_count += 1;	/* flag for big-endian */
1599 #endif
1600 	if (dlthis->dload_errcount)
1601 		return;		/* abandon if errors detected */
1602 	/* Locate the symbol that names the header for the CCS debug list
1603 	   of modules. If not found, we just don't generate the debug record.
1604 	   If found, we create our modules list.  We make sure to create the
1605 	   loader_dllview_root even if there is no relocation info to record,
1606 	   just to try to put both symbols in the same symbol table and
1607 	   module. */
1608 	debug_mirror_sym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1609 							loader_dllview_root);
1610 	if (!debug_mirror_sym) {
1611 		struct dynload_symbol *dlmodsym;
1612 		struct dbg_mirror_root *mlst;
1613 
1614 		/* our root symbol is not yet present;
1615 		   check if we have DLModules defined */
1616 		dlmodsym = dlthis->mysym->find_matching_symbol(dlthis->mysym,
1617 							LINKER_MODULES_HEADER);
1618 		if (!dlmodsym)
1619 			return;	/* no DLModules list so no debug info */
1620 		/* if we have DLModules defined, construct our header */
1621 		mlst = (struct dbg_mirror_root *)
1622 		    dlthis->mysym->dload_allocate(dlthis->mysym,
1623 						  sizeof(struct
1624 							 dbg_mirror_root));
1625 		if (!mlst) {
1626 			DL_ERROR(err_alloc, sizeof(struct dbg_mirror_root));
1627 			return;
1628 		}
1629 		mlst->next = NULL;
1630 		mlst->changes = 0;
1631 		mlst->refcount = 0;
1632 		mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
1633 		/* add our root symbol */
1634 		debug_mirror_sym = dlthis->mysym->add_to_symbol_table
1635 		    (dlthis->mysym, loader_dllview_root,
1636 		     (unsigned)dlthis->myhandle);
1637 		if (!debug_mirror_sym) {
1638 			/* failed, recover memory */
1639 			dlthis->mysym->dload_deallocate(dlthis->mysym, mlst);
1640 			return;
1641 		}
1642 		debug_mirror_sym->value = (u32) mlst;
1643 	}
1644 	/* First create the DLLview record and stuff it into the buffer.
1645 	   Then write it to the DSP.  Record pertinent locations in our hndl,
1646 	   and add it to the per-processor list of handles with debug info. */
1647 #ifndef DEBUG_HEADER_IN_LOADER
1648 	mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
1649 	if (!mlist)
1650 		return;
1651 #else
1652 	mlist = (struct dbg_mirror_root *)&debug_list_header;
1653 #endif
1654 	hndl->dm.root = mlist;	/* set pointer to root into our handle */
1655 	if (!dlthis->allocated_secn_count)
1656 		return;		/* no load addresses to be recorded */
1657 	/* reuse temporary symbol storage */
1658 	dbmod = (struct dll_module *)dlthis->local_symtab;
1659 	/* Create the DLLview record in the memory we retain for our handle */
1660 	dbmod->num_sects = dlthis->allocated_secn_count;
1661 	dbmod->timestamp = dlthis->verify.dv_timdat;
1662 	dbmod->version = INIT_VERSION;
1663 	dbmod->verification = VERIFICATION;
1664 	asecs = dlthis->ldr_sections;
1665 	dbsec = dbmod->sects;
1666 	for (curr_sect = dlthis->allocated_secn_count;
1667 	     curr_sect > 0; curr_sect -= 1) {
1668 		dbsec->sect_load_adr = asecs->load_addr;
1669 		dbsec->sect_run_adr = asecs->run_addr;
1670 		dbsec += 1;
1671 		asecs += 1;
1672 	}
1673 
1674 	/*  If a trampoline section was created go ahead and add its info */
1675 	if (dlthis->tramp.tramp_sect_next_addr != 0) {
1676 		dbmod->num_sects++;
1677 		dbsec->sect_load_adr = asecs->load_addr;
1678 		dbsec->sect_run_adr = asecs->run_addr;
1679 		dbsec++;
1680 		asecs++;
1681 	}
1682 
1683 	/* now cram in the names */
1684 	cp = copy_tgt_strings(dbsec, dlthis->str_head,
1685 			      dlthis->debug_string_size);
1686 
1687 	/* If a trampoline section was created, add its name so DLLView
1688 	 * can show the user the section info. */
1689 	if (dlthis->tramp.tramp_sect_next_addr != 0) {
1690 		cp = copy_tgt_strings(cp,
1691 				      dlthis->tramp.final_string_table,
1692 				      strlen(dlthis->tramp.final_string_table) +
1693 				      1);
1694 	}
1695 
1696 	/* round off the size of the debug record, and remember same */
1697 	hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
1698 	*cp = 0;		/* strictly to make our test harness happy */
1699 	dllview_info = dllview_info_init;
1700 	dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1701 	/* Initialize memory context to default heap */
1702 	dllview_info.context = 0;
1703 	hndl->dm.context = 0;
1704 	/* fill in next pointer and size */
1705 	if (mlist->next) {
1706 		dbmod->next_module = TADDR_TO_TDATA(mlist->next->dm.dbthis);
1707 		dbmod->next_module_size = mlist->next->dm.dbsiz;
1708 	} else {
1709 		dbmod->next_module_size = 0;
1710 		dbmod->next_module = 0;
1711 	}
1712 	/* allocate memory for on-DSP DLLview debug record */
1713 	if (!dlthis->myalloc)
1714 		return;
1715 	if (!dlthis->myalloc->dload_allocate(dlthis->myalloc, &dllview_info,
1716 					     HOST_TO_TADDR(sizeof(u32)))) {
1717 		return;
1718 	}
1719 	/* Store load address of .dllview section */
1720 	hndl->dm.dbthis = dllview_info.load_addr;
1721 	/* Store memory context (segid) in which .dllview section
1722 	 * was  allocated */
1723 	hndl->dm.context = dllview_info.context;
1724 	mlist->refcount += 1;
1725 	/* swap bytes in the entire debug record, but not the string table */
1726 	if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1727 		swap_words(dbmod, (char *)dbsec - (char *)dbmod,
1728 			   DLL_MODULE_BITMAP);
1729 	}
1730 	/* Update the DLLview list on the DSP write new record */
1731 	if (!dlthis->myio->writemem(dlthis->myio, dbmod,
1732 				    dllview_info.load_addr, &dllview_info,
1733 				    TADDR_TO_HOST(dllview_info.size))) {
1734 		return;
1735 	}
1736 	/* write new header */
1737 	mhdr.first_module_size = hndl->dm.dbsiz;
1738 	mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
1739 	/* swap bytes in the module header, if needed */
1740 	if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
1741 		swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1742 			   MODULES_HEADER_BITMAP);
1743 	}
1744 	dllview_info = dllview_info_init;
1745 	if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
1746 				    &dllview_info,
1747 				    sizeof(struct modules_header) -
1748 				    sizeof(u16))) {
1749 		return;
1750 	}
1751 	/* Add the module handle to this processor's list
1752 	   of handles with debug info */
1753 	hndl->dm.next = mlist->next;
1754 	if (hndl->dm.next)
1755 		hndl->dm.next->dm.prev = hndl;
1756 	hndl->dm.prev = (struct my_handle *)mlist;
1757 	mlist->next = hndl;	/* insert after root */
1758 }				/* init_module_handle */
1759 
1760 /*************************************************************************
1761  * Procedure dynamic_unload_module
1762  *
1763  * Parameters:
1764  *	mhandle	A module handle from dynamic_load_module
1765  *	syms	Host-side symbol table and malloc/free functions
1766  *	alloc	Target-side memory allocation
1767  *
1768  * Effect:
1769  *	The module specified by mhandle is unloaded.  Unloading causes all
1770  * target memory to be deallocated, all symbols defined by the module to
1771  * be purged, and any host-side storage used by the dynamic loader for
1772  * this module to be released.
1773  *
1774  * Returns:
1775  *	Zero for success. On error, the number of errors detected is returned.
1776  * Individual errors are reported using syms->error_report().
1777  *********************************************************************** */
dynamic_unload_module(void * mhandle,struct dynamic_loader_sym * syms,struct dynamic_loader_allocate * alloc,struct dynamic_loader_initialize * init)1778 int dynamic_unload_module(void *mhandle,
1779 			  struct dynamic_loader_sym *syms,
1780 			  struct dynamic_loader_allocate *alloc,
1781 			  struct dynamic_loader_initialize *init)
1782 {
1783 	s16 curr_sect;
1784 	struct ldr_section_info *asecs;
1785 	struct my_handle *hndl;
1786 	struct dbg_mirror_root *root;
1787 	unsigned errcount = 0;
1788 	struct ldr_section_info dllview_info = dllview_info_init;
1789 	struct modules_header mhdr;
1790 
1791 	hndl = (struct my_handle *)mhandle;
1792 	if (!hndl)
1793 		return 0;	/* if handle is null, nothing to do */
1794 	/* Clear out the module symbols
1795 	 * Note that if this is the module that defined MODULES_HEADER
1796 	 (the head of the target debug list)
1797 	 * then this operation will blow away that symbol.
1798 	 It will therefore be impossible for subsequent
1799 	 * operations to add entries to this un-referenceable list. */
1800 	if (!syms)
1801 		return 1;
1802 	syms->purge_symbol_table(syms, (unsigned)hndl);
1803 	/* Deallocate target memory for sections
1804 	 * NOTE: The trampoline section, if created, gets deleted here, too */
1805 
1806 	asecs = hndl->secns;
1807 	if (alloc)
1808 		for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
1809 		     curr_sect -= 1) {
1810 			asecs->name = NULL;
1811 			alloc->dload_deallocate(alloc, asecs++);
1812 		}
1813 	root = hndl->dm.root;
1814 	if (!root) {
1815 		/* there is a debug list containing this module */
1816 		goto func_end;
1817 	}
1818 	if (!hndl->dm.dbthis) {	/* target-side dllview record exists */
1819 		goto loop_end;
1820 	}
1821 	/* Retrieve memory context in which .dllview was allocated */
1822 	dllview_info.context = hndl->dm.context;
1823 	if (hndl->dm.prev == hndl)
1824 		goto exitunltgt;
1825 
1826 	/* target-side dllview record is in list */
1827 	/* dequeue this record from our GPP-side mirror list */
1828 	hndl->dm.prev->dm.next = hndl->dm.next;
1829 	if (hndl->dm.next)
1830 		hndl->dm.next->dm.prev = hndl->dm.prev;
1831 	/* Update next_module of previous entry in target list
1832 	 * We are using mhdr here as a surrogate for either a
1833 	 struct modules_header or a dll_module */
1834 	if (hndl->dm.next) {
1835 		mhdr.first_module = TADDR_TO_TDATA(hndl->dm.next->dm.dbthis);
1836 		mhdr.first_module_size = hndl->dm.next->dm.dbsiz;
1837 	} else {
1838 		mhdr.first_module = 0;
1839 		mhdr.first_module_size = 0;
1840 	}
1841 	if (!init)
1842 		goto exitunltgt;
1843 
1844 	if (!init->connect(init)) {
1845 		dload_syms_error(syms, iconnect);
1846 		errcount += 1;
1847 		goto exitunltgt;
1848 	}
1849 	/* swap bytes in the module header, if needed */
1850 	if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
1851 		swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
1852 			   MODULES_HEADER_BITMAP);
1853 	}
1854 	if (!init->writemem(init, &mhdr, hndl->dm.prev->dm.dbthis,
1855 			    &dllview_info, sizeof(struct modules_header) -
1856 			    sizeof(mhdr.update_flag))) {
1857 		dload_syms_error(syms, dlvwrite);
1858 		errcount += 1;
1859 	}
1860 	/* update change counter */
1861 	root->changes += 1;
1862 	if (!init->writemem(init, &(root->changes),
1863 			    root->dbthis + HOST_TO_TADDR
1864 			    (sizeof(mhdr.first_module) +
1865 			     sizeof(mhdr.first_module_size)),
1866 			    &dllview_info, sizeof(mhdr.update_flag))) {
1867 		dload_syms_error(syms, dlvwrite);
1868 		errcount += 1;
1869 	}
1870 	init->release(init);
1871 exitunltgt:
1872 	/* release target storage */
1873 	dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
1874 	dllview_info.load_addr = hndl->dm.dbthis;
1875 	if (alloc)
1876 		alloc->dload_deallocate(alloc, &dllview_info);
1877 	root->refcount -= 1;
1878 	/* target-side dllview record exists */
1879 loop_end:
1880 #ifndef DEBUG_HEADER_IN_LOADER
1881 	if (root->refcount <= 0) {
1882 		/* if all references gone, blow off the header */
1883 		/* our root symbol may be gone due to the Purge above,
1884 		   but if not, do not destroy the root */
1885 		if (syms->find_matching_symbol
1886 		    (syms, loader_dllview_root) == NULL)
1887 			syms->dload_deallocate(syms, root);
1888 	}
1889 #endif
1890 func_end:
1891 	/* there is a debug list containing this module */
1892 	syms->dload_deallocate(syms, mhandle);	/* release our storage */
1893 	return errcount;
1894 }				/* dynamic_unload_module */
1895 
1896 #if BITS_PER_AU > BITS_PER_BYTE
1897 /*************************************************************************
1898  * Procedure unpack_name
1899  *
1900  * Parameters:
1901  *	soffset	Byte offset into the string table
1902  *
1903  * Effect:
1904  *	Returns a pointer to the string specified by the offset supplied, or
1905  * NULL for error.
1906  *
1907  *********************************************************************** */
unpack_name(struct dload_state * dlthis,u32 soffset)1908 static char *unpack_name(struct dload_state *dlthis, u32 soffset)
1909 {
1910 	u8 tmp, *src;
1911 	char *dst;
1912 
1913 	if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
1914 		dload_error(dlthis, "Bad string table offset " FMT_UI32,
1915 			    soffset);
1916 		return NULL;
1917 	}
1918 	src = (uint_least8_t *) dlthis->str_head +
1919 	    (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
1920 	dst = dlthis->str_temp;
1921 	if (soffset & 1)
1922 		*dst++ = *src++;	/* only 1 character in first word */
1923 	do {
1924 		tmp = *src++;
1925 		*dst = (tmp >> BITS_PER_BYTE);
1926 		if (!(*dst++))
1927 			break;
1928 	} while ((*dst++ = tmp & BYTE_MASK));
1929 	dlthis->temp_len = dst - dlthis->str_temp;
1930 	/* squirrel away length including terminating null */
1931 	return dlthis->str_temp;
1932 }				/* unpack_name */
1933 #endif
1934