17 #include <linux/slab.h>
22 #define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
27 static void dload_symbols(
struct dload_state *dlthis);
29 static void allocate_sections(
struct dload_state *dlthis);
30 static void string_table_free(
struct dload_state *dlthis);
31 static void symbol_table_free(
struct dload_state *dlthis);
32 static void section_table_free(
struct dload_state *dlthis);
33 static void init_module_handle(
struct dload_state *dlthis);
34 #if BITS_PER_AU > BITS_PER_BYTE
38 static const char cinitname[] = {
".cinit" };
39 static const char loader_dllview_root[] = {
"?DLModules?" };
44 static const char readstrm[] = {
"Error reading %s from input stream" };
45 static const char err_alloc[] = {
"Syms->dload_allocate( %d ) failed" };
46 static const char tgtalloc[] = {
47 "Target memory allocate failed, section %s size " FMT_UI32 };
48 static const char initfail[] = {
"%s to target address " FMT_UI32 " failed" };
49 static const char dlvwrite[] = {
"Write to DLLview list failed" };
50 static const char iconnect[] = {
"Connect call to init interface failed" };
51 static const char err_checksum[] = {
"Checksum failed on %s" };
68 dlthis->
mysym->error_report(dlthis->
mysym, errtxt, args);
74 #define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
124 unsigned options,
void **mhandle)
126 register unsigned *
dp, sz;
130 dp = (
unsigned *)&dl_state;
131 for (sz =
sizeof(dl_state) /
sizeof(unsigned); sz > 0; sz -= 1)
139 if (!module || !syms) {
140 dload_error(&dl_state,
"Required parameter is NULL");
142 dl_state.
strm = module;
143 dl_state.
mysym = syms;
155 allocate_sections(&dl_state);
162 unsigned sref = dl_state.
dfile_hdr.df_entry_secn - 1;
167 dload_symbols(&dl_state);
171 dload_data(&dl_state);
173 init_module_handle(&dl_state);
185 symbol_table_free(&dl_state);
186 section_table_free(&dl_state);
187 string_table_free(&dl_state);
233 unsigned options,
void **mhandle)
235 register unsigned *
dp, sz;
239 dp = (
unsigned *)&dl_state;
240 for (sz =
sizeof(dl_state) /
sizeof(unsigned); sz > 0; sz -= 1)
248 if (!module || !syms) {
249 dload_error(&dl_state,
"Required parameter is NULL");
251 dl_state.
strm = module;
252 dl_state.
mysym = syms;
264 allocate_sections(&dl_state);
271 unsigned sref = dl_state.
dfile_hdr.df_entry_secn - 1;
276 dload_symbols(&dl_state);
279 init_module_handle(&dl_state);
291 symbol_table_free(&dl_state);
292 section_table_free(&dl_state);
293 string_table_free(&dl_state);
318 #define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
319 sizeof(struct doff_verify_rec_t))
340 if ((map & 0xFCFCFCFC) == 0) {
344 if (dlthis->
dfile_hdr.df_byte_reshuffle !=
348 "Bad byte swap map " FMT_UI32 " in header",
362 DL_ERROR(err_checksum,
"header or verify record");
370 if ((dlthis->
dfile_hdr.df_target_id != TARGET_ID) &&
372 dload_error(dlthis,
"Bad target ID 0x%x and TARGET_ID 0x%x",
373 dlthis->
dfile_hdr.df_target_id, TARGET_ID);
392 dload_error(dlthis,
"Excessive section count 0x%x",
396 #ifndef TARGET_ENDIANNESS
403 "Input endianness disagrees with specified option");
417 static const char secn_errid[] = {
"section" };
446 if (dlthis->
strm->read_buffer(dlthis->
strm, shp, siz) != siz) {
457 dlthis->
verify.dv_scn_rec_checksum) {
473 static void allocate_sections(
struct dload_state *dlthis)
483 (dlthis->
dfile_hdr.df_target_scns > 0)) {
484 DL_ERROR(
"Arg 3 (alloc) required but NULL", 0);
492 siz = (dlthis->
dfile_hdr.df_target_scns + 1) *
503 hndl->
dm.next = hndl->
dm.prev = hndl;
512 for (curr_sect = 0; curr_sect <
nsecs; curr_sect++) {
514 #if BITS_PER_AU <= BITS_PER_BYTE
516 if (soffset < dlthis->dfile_hdr.df_strtab_size)
520 dload_error(dlthis,
"Bad name offset in section %d",
526 if (ds_needs_allocation(shp)) {
529 #if BITS_PER_AU > BITS_PER_BYTE
530 asecs->
name = unpack_name(dlthis, soffset);
537 dload_allocate(dlthis->
myalloc, asecs,
538 ds_alignment(asecs->
type))) {
545 shp->ds_vaddr = asecs->
load_addr - shp->ds_vaddr;
546 shp->ds_paddr = asecs->
run_addr - shp->ds_paddr;
552 #if BITS_PER_AU <= BITS_PER_BYTE
570 static void section_table_free(
struct dload_state *dlthis)
576 dlthis->
mysym->dload_deallocate(dlthis->
mysym, shp);
591 static const char stringtbl[] = {
"string table" };
598 if (sec_names_only) {
609 #if BITS_PER_AU > BITS_PER_BYTE
610 strbuf = (
char *)dlthis->
mysym->dload_allocate(dlthis->
mysym, ssiz +
614 strbuf = (
char *)dlthis->
mysym->dload_allocate(dlthis->
mysym, ssiz);
616 if (strbuf ==
NULL) {
621 #if BITS_PER_AU > BITS_PER_BYTE
622 dlthis->str_temp = strbuf + ssiz;
625 if ((
unsigned)(dlthis->
strm->read_buffer(dlthis->
strm, strbuf,
635 dlthis->
verify.dv_str_tab_checksum)) {
639 if (dlthis->
dfile_hdr.df_byte_reshuffle !=
644 dfile_hdr.df_byte_reshuffle));
646 if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
647 dlthis->
verify.dv_str_tab_checksum)) {
665 static void string_table_free(
struct dload_state *dlthis)
668 dlthis->
mysym->dload_deallocate(dlthis->
mysym,
685 #define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
687 static const char sym_errid[] = {
"symbol" };
701 #define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
702 sizeof(struct doff_syment_t))
704 static void dload_symbols(
struct dload_state *dlthis)
706 u32 sym_count, siz, dsiz, symbols_left;
713 sym_count = dlthis->
dfile_hdr.df_no_syms;
743 checks = dlthis->
verify.dv_sym_tab_checksum;
744 symbols_left = sym_count;
755 unsigned syms_in_buf;
757 input_sym = my_sym_buf;
758 syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
759 MY_SYM_BUF_SIZ : symbols_left;
761 if (dlthis->
strm->read_buffer(dlthis->
strm, input_sym, siz) !=
775 #if BITS_PER_AU <= BITS_PER_BYTE
782 "Bad name offset in symbol "
783 " %d", symbols_left);
785 sname = unpack_name(dlthis,
802 symp = dlthis->
mysym->find_matching_symbol
803 (dlthis->
mysym, sname);
806 (
"Undefined external symbol %s",
810 val = delta = symp->
value;
811 #ifdef ENABLE_TRAMP_DEBUG
813 "===> ext sym [%s] at %x",
822 if ((
unsigned)sp->
secnn <=
846 dlthis->
mysym->find_matching_symbol(dlthis->
865 "defined multiple times with "
866 "different values", sname);
881 newsym = dlthis->
mysym->add_to_symbol_table
882 (dlthis->
mysym, sname,
893 }
while ((syms_in_buf -= 1) > 0);
894 }
while (symbols_left > 0);
915 static void symbol_table_free(
struct dload_state *dlthis)
919 dlthis->
mysym->purge_symbol_table(dlthis->
mysym,
923 dlthis->
mysym->dload_deallocate(dlthis->
mysym,
954 static void cload_cinit(
struct dload_state *dlthis,
957 #if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
962 unsigned char *pktp = ipacket->
img_data;
970 left = pktend - pktp;
987 #if CINIT_ALIGN < CINIT_ADDRESS
996 #if CINIT_ALIGN < CINIT_ADDRESS
1011 #if CINIT_PAGE_BITS > 0
1013 ((1 << CINIT_PAGE_BITS) - 1);
1014 atmp >>= CINIT_PAGE_BITS;
1025 if (init_count == 0)
1027 cinit_info = cinit_info_init;
1029 if (!dlthis->
myio->writemem(dlthis->
myio, pktp,
1040 init_count = (init_count + CINIT_ALIGN - 1) &
1054 dload_error(dlthis,
"%d bytes left over in cinit packet", left);
1078 #define MY_RELOC_BUF_SIZ 8
1080 static int relocate_packet(
struct dload_state *dlthis,
1082 u32 *checks,
bool *tramps_generated)
1085 *tramps_generated =
false;
1095 if (dlthis->
strm->read_buffer(dlthis->
strm, rp, siz) != siz) {
1107 rp, tramps_generated,
false);
1110 }
while ((rinbuf -= 1) > 0);
1115 if (*tramps_generated ==
true) {
1125 #define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
1128 static const char imagepak[] = {
"image packet" };
1145 static void dload_data(
struct dload_state *dlthis)
1154 bool cinit_processed =
false;
1162 for (curr_sect = 0; curr_sect < dlthis->
dfile_hdr.df_no_scns;
1164 if (ds_needs_download(sptr)) {
1168 if (curr_sect < dlthis->allocated_secn_count)
1175 #if BITS_PER_AU > BITS_PER_BYTE
1179 while ((nip -= 1) >= 0) {
1183 bool tramp_generated =
false;
1186 if (dlthis->
strm->read_buffer(dlthis->
strm,
1203 DL_ERROR(
"Bad image packet size %d",
1210 if (dlthis->
strm->read_buffer(dlthis->
strm,
1220 #if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
1227 if (dlthis->
dfile_hdr.df_byte_reshuffle !=
1235 df_byte_reshuffle));
1237 #if TARGET_AU_BITS > 8
1238 checks = dload_reverse_checksum16(dest, ipsize);
1240 checks = dload_reverse_checksum(dest, ipsize);
1247 if (ibuf->
ipacket.num_relocs) {
1249 if (!relocate_packet(dlthis,
1261 if (tramp_generated ==
false) {
1265 if (dload_check_type(sptr,
1269 cinit_processed =
true;
1304 if (cinit_processed) {
1308 (
"Zero-initialization at " FMT_UI32
1309 " after " "load-time initialization!",
1314 dlthis->
myio->fillmem(dlthis->
myio,
1331 if (cinit_processed) {
1335 "load-time initialization!", lptr->
load_addr);
1339 dlthis->
myio->fillmem(dlthis->
myio,
1351 ") failed", dlthis->
tramp.tramp_sect_next_addr);
1373 #define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
1377 register u32 tmp, tmap, datv;
1390 }
while ((dsiz -=
sizeof(
u32)) > 0);
1412 for (left = siz; left > 0; left -=
sizeof(
u32))
1435 u32 dload_reverse_checksum(
void *
data,
unsigned siz)
1444 for (left = siz; left > 0; left -=
sizeof(
u32)) {
1447 sum += temp >> BITS_PER_BYTE * 3;
1455 #if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
1456 u32 dload_reverse_checksum16(
void *data,
unsigned siz)
1465 for (left = siz; left > 0; left -=
sizeof(
u32)) {
1468 sum += temp >> BITS_PER_BYTE * 2;
1489 static void swap_words(
void *data,
unsigned siz,
unsigned bitmap)
1492 #if TARGET_AU_BITS < 16
1499 #if TARGET_AU_BITS < 16
1507 }
while ((i -= 1) > 0);
1510 #if TARGET_AU_BITS < 32
1515 if ((bitmap & 1) == 0) {
1522 }
while ((i -= 1) > 0);
1541 static char *copy_tgt_strings(
void *dstp,
void *srcp,
unsigned charcount)
1545 register int cnt = charcount;
1547 #if TARGET_AU_BITS <= BITS_PER_AU
1555 #if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
1581 static const struct ldr_section_info dllview_info_init = {
".dllview", 0, 0,
1585 static const struct ldr_section_info dllview_info_init = {
".dllview", 0, 0,
1589 static void init_module_handle(
struct dload_state *dlthis)
1609 if (dlthis->
tramp.tramp_sect_next_addr != 0)
1615 #ifndef TARGET_ENDIANNESS
1627 debug_mirror_sym = dlthis->
mysym->find_matching_symbol(dlthis->
mysym,
1628 loader_dllview_root);
1629 if (!debug_mirror_sym) {
1635 dlmodsym = dlthis->
mysym->find_matching_symbol(dlthis->
mysym,
1653 debug_mirror_sym = dlthis->
mysym->add_to_symbol_table
1654 (dlthis->
mysym, loader_dllview_root,
1656 if (!debug_mirror_sym) {
1658 dlthis->
mysym->dload_deallocate(dlthis->
mysym, mlst);
1661 debug_mirror_sym->
value = (
u32) mlst;
1666 #ifndef DEBUG_HEADER_IN_LOADER
1673 hndl->
dm.root = mlist;
1684 dbsec = dbmod->
sects;
1686 curr_sect > 0; curr_sect -= 1) {
1694 if (dlthis->
tramp.tramp_sect_next_addr != 0) {
1703 cp = copy_tgt_strings(dbsec, dlthis->
str_head,
1708 if (dlthis->
tramp.tramp_sect_next_addr != 0) {
1709 cp = copy_tgt_strings(cp,
1710 dlthis->
tramp.final_string_table,
1718 dllview_info = dllview_info_init;
1721 dllview_info.context = 0;
1722 hndl->
dm.context = 0;
1734 if (!dlthis->
myalloc->dload_allocate(dlthis->
myalloc, &dllview_info,
1739 hndl->
dm.dbthis = dllview_info.load_addr;
1742 hndl->
dm.context = dllview_info.context;
1746 swap_words(dbmod, (
char *)dbsec - (
char *)dbmod,
1750 if (!dlthis->
myio->writemem(dlthis->
myio, dbmod,
1751 dllview_info.load_addr, &dllview_info,
1756 mhdr.first_module_size = hndl->
dm.dbsiz;
1763 dllview_info = dllview_info_init;
1772 hndl->
dm.next = mlist->
next;
1774 hndl->
dm.next->dm.prev = hndl;
1806 unsigned errcount = 0;
1825 asecs = hndl->secns;
1827 for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
1832 root = hndl->dm.root;
1837 if (!hndl->dm.dbthis) {
1841 dllview_info.
context = hndl->dm.context;
1842 if (hndl->dm.prev == hndl)
1847 hndl->dm.prev->dm.next = hndl->dm.next;
1849 hndl->dm.next->dm.prev = hndl->dm.prev;
1853 if (hndl->dm.next) {
1873 if (!init->
writemem(init, &mhdr, hndl->dm.prev->dm.dbthis,
1893 dllview_info.
load_addr = hndl->dm.dbthis;
1899 #ifndef DEBUG_HEADER_IN_LOADER
1905 (syms, loader_dllview_root) ==
NULL)
1915 #if BITS_PER_AU > BITS_PER_BYTE
1927 static char *unpack_name(
struct dload_state *dlthis,
u32 soffset)
1932 if (soffset >= dlthis->
dfile_hdr.df_strtab_size) {
1937 src = (uint_least8_t *) dlthis->
str_head +
1939 dst = dlthis->str_temp;
1948 dlthis->temp_len = dst - dlthis->str_temp;
1950 return dlthis->str_temp;