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