pe-dll.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,946 行 · 第 1/4 页
C
1,946 行
if (! exp->flag_data) { bfd_set_section_size (abfd, tx, jmp_byte_count); td = (unsigned char *) xmalloc (jmp_byte_count); tx->contents = td; memcpy (td, jmp_bytes, jmp_byte_count); switch (pe_details->pe_arch) { case PE_ARCH_i386: quick_reloc (abfd, 2, BFD_RELOC_32, 2); break; case PE_ARCH_sh: quick_reloc (abfd, 8, BFD_RELOC_32, 2); break; case PE_ARCH_mips: quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2); quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */ quick_reloc (abfd, 4, BFD_RELOC_LO16, 2); break; } save_relocs (tx); } bfd_set_section_size (abfd, id7, 4); d7 = (unsigned char *) xmalloc (4); id7->contents = d7; memset (d7, 0, 4); quick_reloc (abfd, 0, BFD_RELOC_RVA, 6); save_relocs (id7); bfd_set_section_size (abfd, id5, 4); d5 = (unsigned char *) xmalloc (4); id5->contents = d5; memset (d5, 0, 4); if (exp->flag_noname) { d5[0] = exp->ordinal; d5[1] = exp->ordinal >> 8; d5[3] = 0x80; } else { quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); save_relocs (id5); } bfd_set_section_size (abfd, id4, 4); d4 = (unsigned char *) xmalloc (4); id4->contents = d4; memset (d4, 0, 4); if (exp->flag_noname) { d4[0] = exp->ordinal; d4[1] = exp->ordinal >> 8; d4[3] = 0x80; } else { quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); save_relocs (id4); } if (exp->flag_noname) { len = 0; bfd_set_section_size (abfd, id6, 0); } else { len = strlen (exp->name) + 3; if (len & 1) len++; bfd_set_section_size (abfd, id6, len); d6 = (unsigned char *) xmalloc (len); id6->contents = d6; memset (d6, 0, len); d6[0] = exp->hint & 0xff; d6[1] = exp->hint >> 8; strcpy (d6 + 2, exp->name); } bfd_set_symtab (abfd, symtab, symptr); bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count); bfd_set_section_contents (abfd, id7, d7, 0, 4); bfd_set_section_contents (abfd, id5, d5, 0, 4); bfd_set_section_contents (abfd, id4, d4, 0, 4); if (!exp->flag_noname) bfd_set_section_contents (abfd, id6, d6, 0, len); bfd_make_readable (abfd); return abfd;}voidpe_dll_generate_implib (def, impfilename) def_file *def; const char *impfilename;{ int i; bfd *ar_head; bfd *ar_tail; bfd *outarch; bfd *head = 0; dll_filename = (def->name) ? def->name : dll_name; dll_symname = xstrdup (dll_filename); for (i = 0; dll_symname[i]; i++) if (!isalnum ((unsigned char) dll_symname[i])) dll_symname[i] = '_'; unlink (impfilename); outarch = bfd_openw (impfilename, 0); if (!outarch) { /* xgettext:c-format */ einfo (_("%XCan't open .lib file: %s\n"), impfilename); return; } /* xgettext:c-format */ einfo (_("Creating library file: %s\n"), impfilename); bfd_set_format (outarch, bfd_archive); outarch->has_armap = 1; /* Work out a reasonable size of things to put onto one line. */ ar_head = make_head (outarch); for (i = 0; i < def->num_exports; i++) { /* The import library doesn't know about the internal name. */ char *internal = def->exports[i].internal_name; bfd *n; def->exports[i].internal_name = def->exports[i].name; n = make_one (def->exports + i, outarch); n->next = head; head = n; def->exports[i].internal_name = internal; } ar_tail = make_tail (outarch); if (ar_head == NULL || ar_tail == NULL) return; /* Now stick them all into the archive. */ ar_head->next = head; ar_tail->next = ar_head; head = ar_tail; if (! bfd_set_archive_head (outarch, head)) einfo ("%Xbfd_set_archive_head: %s\n", bfd_errmsg (bfd_get_error ())); if (! bfd_close (outarch)) einfo ("%Xbfd_close %s: %s\n", impfilename, bfd_errmsg (bfd_get_error ())); while (head != NULL) { bfd *n = head->next; bfd_close (head); head = n; }}static voidadd_bfd_to_link (abfd, name, link_info) bfd *abfd; char *name; struct bfd_link_info *link_info;{ lang_input_statement_type *fake_file; fake_file = lang_add_input_file (name, lang_input_file_is_fake_enum, NULL); fake_file->the_bfd = abfd; ldlang_add_file (fake_file); if (!bfd_link_add_symbols (abfd, link_info)) einfo ("%Xaddsym %s: %s\n", name, bfd_errmsg (bfd_get_error ()));}voidpe_process_import_defs (output_bfd, link_info) bfd *output_bfd; struct bfd_link_info *link_info;{ def_file_module *module; pe_dll_id_target (bfd_get_target (output_bfd)); if (!pe_def_file) return; for (module = pe_def_file->modules; module; module = module->next) { int i, do_this_dll; dll_filename = module->name; dll_symname = xstrdup (module->name); for (i = 0; dll_symname[i]; i++) if (!isalnum (dll_symname[i])) dll_symname[i] = '_'; do_this_dll = 0; for (i = 0; i < pe_def_file->num_imports; i++) if (pe_def_file->imports[i].module == module) { def_file_export exp; struct bfd_link_hash_entry *blhe; /* See if we need this import. */ char *name = (char *) xmalloc (strlen (pe_def_file->imports[i].internal_name) + 2 + 6); sprintf (name, "%s%s", U (""), pe_def_file->imports[i].internal_name); blhe = bfd_link_hash_lookup (link_info->hash, name, false, false, false); if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)) { sprintf (name, "%s%s", U ("_imp__"), pe_def_file->imports[i].internal_name); blhe = bfd_link_hash_lookup (link_info->hash, name, false, false, false); } free (name); if (blhe && blhe->type == bfd_link_hash_undefined) { bfd *one; /* We do. */ if (!do_this_dll) { bfd *ar_head = make_head (output_bfd); add_bfd_to_link (ar_head, ar_head->filename, link_info); do_this_dll = 1; } exp.internal_name = pe_def_file->imports[i].internal_name; exp.name = pe_def_file->imports[i].name; exp.ordinal = pe_def_file->imports[i].ordinal; exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0; exp.flag_private = 0; exp.flag_constant = 0; exp.flag_data = 0; exp.flag_noname = exp.name ? 0 : 1; one = make_one (&exp, output_bfd); add_bfd_to_link (one, one->filename, link_info); } } if (do_this_dll) { bfd *ar_tail = make_tail (output_bfd); add_bfd_to_link (ar_tail, ar_tail->filename, link_info); } free (dll_symname); }}/************************************************************************ We were handed a *.DLL file. Parse it and turn it into a set of IMPORTS directives in the def file. Return true if the file was handled, false if not. ************************************************************************/static unsigned intpe_get16 (abfd, where) bfd *abfd; int where;{ unsigned char b[2]; bfd_seek (abfd, where, SEEK_SET); bfd_read (b, 1, 2, abfd); return b[0] + (b[1] << 8);}static unsigned intpe_get32 (abfd, where) bfd *abfd; int where;{ unsigned char b[4]; bfd_seek (abfd, where, SEEK_SET); bfd_read (b, 1, 4, abfd); return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);}#if 0 /* This is not currently used. */static unsigned intpe_as16 (ptr) void *ptr;{ unsigned char *b = ptr; return b[0] + (b[1] << 8);}#endifstatic unsigned intpe_as32 (ptr) void *ptr;{ unsigned char *b = ptr; return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);}booleanpe_implied_import_dll (filename) const char *filename;{ bfd *dll; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; const char *dll_name; /* No, I can't use bfd here. kernel32.dll puts its export table in the middle of the .rdata section. */ dll = bfd_openr (filename, pe_details->target_name); if (!dll) { einfo ("%Xopen %s: %s\n", filename, bfd_errmsg (bfd_get_error ())); return false; } /* PEI dlls seem to be bfd_objects. */ if (!bfd_check_format (dll, bfd_object)) { einfo ("%X%s: this doesn't appear to be a DLL\n", filename); return false; } dll_name = filename; for (i = 0; filename[i]; i++) if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') dll_name = filename + i + 1; pe_header_offset = pe_get32 (dll, 0x3c); opthdr_ofs = pe_header_offset + 4 + 20; num_entries = pe_get32 (dll, opthdr_ofs + 92); if (num_entries < 1) /* no exports */ return false; export_rva = pe_get32 (dll, opthdr_ofs + 96); export_size = pe_get32 (dll, opthdr_ofs + 100); nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; for (i = 0; i < nsections; i++) { char sname[8]; unsigned long secptr1 = secptr + 40 * i; unsigned long vaddr = pe_get32 (dll, secptr1 + 12); unsigned long vsize = pe_get32 (dll, secptr1 + 16); unsigned long fptr = pe_get32 (dll, secptr1 + 20); bfd_seek (dll, secptr1, SEEK_SET); bfd_read (sname, 1, 8, dll); if (vaddr <= export_rva && vaddr + vsize > export_rva) { expptr = fptr + (export_rva - vaddr); if (export_rva + export_size > vaddr + vsize) export_size = vsize - (export_rva - vaddr); break; } } expdata = (unsigned char *) xmalloc (export_size); bfd_seek (dll, expptr, SEEK_SET); bfd_read (expdata, 1, export_size, dll); erva = expdata - export_rva; if (pe_def_file == 0) pe_def_file = def_file_empty (); nexp = pe_as32 (expdata + 24); name_rvas = pe_as32 (expdata + 32); ordinals = pe_as32 (expdata + 36); ordbase = pe_as32 (expdata + 16); for (i = 0; i < nexp; i++) { unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); def_file_import *imp; imp = def_file_add_import (pe_def_file, erva + name_rva, dll_name, i, 0); } return true;}/************************************************************************ These are the main functions, called from the emulation. The first is called after the bfds are read, so we can guess at how much space we need. The second is called after everything is placed, so we can put the right values in place. ************************************************************************/voidpe_dll_build_sections (abfd, info) bfd *abfd; struct bfd_link_info *info;{ pe_dll_id_target (bfd_get_target (abfd)); process_def_file (abfd, info); generate_edata (abfd, info); build_filler_bfd (1);}voidpe_exe_build_sections (abfd, info) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED;{ pe_dll_id_target (bfd_get_target (abfd)); build_filler_bfd (0);}voidpe_dll_fill_sections (abfd, info) bfd *abfd; struct bfd_link_info *info;{ pe_dll_id_target (bfd_get_target (abfd)); image_base = pe_data (abfd)->pe_opthdr.ImageBase; generate_reloc (abfd, info); if (reloc_sz > 0) { bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); /* Resize the sections. */ lang_size_sections (stat_ptr->head, abs_output_section, &stat_ptr->head, 0, (bfd_vma) 0, false); /* Redo special stuff. */ ldemul_after_allocation (); /* Do the assignments again. */ lang_do_assignments (stat_ptr->head, abs_output_section, (fill_type) 0, (bfd_vma) 0); } fill_edata (abfd, info); pe_data (abfd)->dll = 1; edata_s->contents = edata_d; reloc_s->contents = reloc_d;}voidpe_exe_fill_sections (abfd, info) bfd *abfd; struct bfd_link_info *info;{ pe_dll_id_target (bfd_get_target (abfd)); image_base = pe_data (abfd)->pe_opthdr.ImageBase; generate_reloc (abfd, info); if (reloc_sz > 0) { bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); /* Resize the sections. */ lang_size_sections (stat_ptr->head, abs_output_section, &stat_ptr->head, 0, (bfd_vma) 0, false); /* Redo special stuff. */ ldemul_after_allocation (); /* Do the assignments again. */ lang_do_assignments (stat_ptr->head, abs_output_section, (fill_type) 0, (bfd_vma) 0); } reloc_s->contents = reloc_d;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?