📄 pe.em
字号:
if (pe_dll_extra_pe_debug) { bfd *a; struct bfd_link_hash_entry *sym; printf ("%s()\n", __FUNCTION__); for (sym = link_info.hash->undefs; sym; sym=sym->next) printf ("-%s\n", sym->root.string); bfd_hash_traverse (&link_info.hash->table, pr_sym,NULL); for (a = link_info.input_bfds; a; a = a->link_next) { printf("*%s\n",a->filename); } } /* Pass the wacky PE command line options into the output bfd. FIXME: This should be done via a function, rather than by including an internal BFD header. */ if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0) einfo (_("%F%P: PE operations on non PE file.\n")); pe_data (output_bfd)->pe_opthdr = pe; pe_data (output_bfd)->dll = init[DLLOFF].value;#ifdef DLL_SUPPORT if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ pe_fixup_stdcalls (); pe_find_data_imports (); pe_process_import_defs(output_bfd, &link_info); if (link_info.shared) pe_dll_build_sections (output_bfd, &link_info);#ifndef TARGET_IS_i386pe#ifndef TARGET_IS_armpe else pe_exe_build_sections (output_bfd, &link_info);#endif#endif#endif#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) if (strstr (bfd_get_target (output_bfd), "arm") == NULL) { /* The arm backend needs special fields in the output hash structure. These will only be created if the output format is an arm format, hence we do not support linking and changing output formats at the same time. Use a link followed by objcopy to change output formats. */ einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n"); return; } { /* Find a BFD that can hold the interworking stubs. */ LANG_FOR_EACH_INPUT_STATEMENT (is) { if (bfd_arm_pe_get_bfd_for_interworking (is->the_bfd, & link_info)) break; } }#endif { /* This next chunk of code tries to detect the case where you have two import libraries for the same DLL (specifically, symbolically linking libm.a and libc.a in cygwin to libcygwin.a). In those cases, it's possible for function thunks from the second implib to be used but without the head/tail objects, causing an improper import table. We detect those cases and rename the "other" import libraries to match the one the head/tail come from, so that the linker will sort things nicely and produce a valid import table. */ LANG_FOR_EACH_INPUT_STATEMENT (is) { if (is->the_bfd->my_archive) { int idata2 = 0, reloc_count=0, is_imp = 0; asection *sec; /* See if this is an import library thunk. */ for (sec = is->the_bfd->sections; sec; sec = sec->next) { if (strcmp (sec->name, ".idata\$2") == 0) idata2 = 1; if (strncmp (sec->name, ".idata\$", 7) == 0) is_imp = 1; reloc_count += sec->reloc_count; } if (is_imp && !idata2 && reloc_count) { /* It is, look for the reference to head and see if it's from our own library. */ for (sec = is->the_bfd->sections; sec; sec = sec->next) { int i; long symsize; long relsize; asymbol **symbols; arelent **relocs; int nrelocs; symsize = bfd_get_symtab_upper_bound (is->the_bfd); if (symsize < 1) break; relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec); if (relsize < 1) break; symbols = (asymbol **) xmalloc (symsize); symsize = bfd_canonicalize_symtab (is->the_bfd, symbols); if (symsize < 0) { einfo ("%X%P: unable to process symbols: %E"); return; } relocs = (arelent **) xmalloc ((size_t) relsize); nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec, relocs, symbols); if (nrelocs < 0) { free (relocs); einfo ("%X%P: unable to process relocs: %E"); return; } for (i = 0; i < nrelocs; i++) { struct symbol_cache_entry *s; struct bfd_link_hash_entry * blhe; bfd *other_bfd; char *n; s = (relocs[i]->sym_ptr_ptr)[0]; if (s->flags & BSF_LOCAL) continue; /* Thunk section with reloc to another bfd. */ blhe = bfd_link_hash_lookup (link_info.hash, s->name, false, false, true); if (blhe == NULL || blhe->type != bfd_link_hash_defined) continue; other_bfd = blhe->u.def.section->owner; if (strcmp (is->the_bfd->my_archive->filename, other_bfd->my_archive->filename) == 0) continue; /* Rename this implib to match the other. */ n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1); strcpy (n, other_bfd->my_archive->filename); is->the_bfd->my_archive->filename = n; } free (relocs); /* Note - we do not free the symbols, they are now cached in the BFD. */ } } } } } { int is_ms_arch = 0; bfd *cur_arch = 0; lang_input_statement_type *is2; /* Careful - this is a shell script. Watch those dollar signs! */ /* Microsoft import libraries have every member named the same, and not in the right order for us to link them correctly. We must detect these and rename the members so that they'll link correctly. There are three types of objects: the head, the thunks, and the sentinel(s). The head is easy; it's the one with idata2. We assume that the sentinels won't have relocs, and the thunks will. It's easier than checking the symbol table for external references. */ LANG_FOR_EACH_INPUT_STATEMENT (is) { if (is->the_bfd->my_archive) { bfd *arch = is->the_bfd->my_archive; if (cur_arch != arch) { cur_arch = arch; is_ms_arch = 1; for (is2 = is; is2 && is2->the_bfd->my_archive == arch; is2 = (lang_input_statement_type *)is2->next) { if (strcmp (is->the_bfd->filename, is2->the_bfd->filename)) is_ms_arch = 0; } } if (is_ms_arch) { int idata2 = 0, reloc_count=0; asection *sec; char *new_name, seq; for (sec = is->the_bfd->sections; sec; sec = sec->next) { if (strcmp (sec->name, ".idata\$2") == 0) idata2 = 1; reloc_count += sec->reloc_count; } if (idata2) /* .idata2 is the TOC */ seq = 'a'; else if (reloc_count > 0) /* thunks */ seq = 'b'; else /* sentinel */ seq = 'c'; new_name = xmalloc (strlen (is->the_bfd->filename) + 3); sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); is->the_bfd->filename = new_name; new_name = xmalloc (strlen (is->filename) + 3); sprintf (new_name, "%s.%c", is->filename, seq); is->filename = new_name; } } } }}static voidgld_${EMULATION_NAME}_before_allocation(){#ifdef TARGET_IS_ppcpe /* Here we rummage through the found bfds to collect toc information */ { LANG_FOR_EACH_INPUT_STATEMENT (is) { if (!ppc_process_before_allocation (is->the_bfd, &link_info)) { /* xgettext:c-format */ einfo (_("Errors encountered processing file %s\n"), is->filename); } } } /* We have seen it all. Allocate it, and carry on */ ppc_allocate_toc_section (&link_info);#endif /* TARGET_IS_ppcpe */#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) /* FIXME: we should be able to set the size of the interworking stub section. Here we rummage through the found bfds to collect glue information. FIXME: should this be based on a command line option? krk@cygnus.com */ { LANG_FOR_EACH_INPUT_STATEMENT (is) { if (! bfd_arm_pe_process_before_allocation (is->the_bfd, & link_info, support_old_code)) { /* xgettext:c-format */ einfo (_("Errors encountered processing file %s for interworking"), is->filename); } } } /* We have seen it all. Allocate it, and carry on */ bfd_arm_pe_allocate_interworking_sections (& link_info);#endif /* TARGET_IS_armpe */}#ifdef DLL_SUPPORT/* This is called when an input file isn't recognized as a BFD. We check here for .DEF files and pull them in automatically. */static intsaw_option(char *option){ int i; for (i=0; init[i].ptr; i++) if (strcmp (init[i].symbol, option) == 0) return init[i].inited; return 0;}#endif /* DLL_SUPPORT */static booleangld_${EMULATION_NAME}_unrecognized_file(entry) lang_input_statement_type *entry ATTRIBUTE_UNUSED;{#ifdef DLL_SUPPORT const char *ext = entry->filename + strlen (entry->filename) - 4; if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0) { if (pe_def_file == 0) pe_def_file = def_file_empty (); def_file_parse (entry->filename, pe_def_file); if (pe_def_file) { int i, buflen=0, len; char *buf; for (i=0; i<pe_def_file->num_exports; i++) { len = strlen(pe_def_file->exports[i].internal_name); if (buflen < len+2) buflen = len+2; } buf = (char *) xmalloc (buflen); for (i=0; i<pe_def_file->num_exports; i++) { struct bfd_link_hash_entry *h; sprintf(buf, "_%s", pe_def_file->exports[i].internal_name); h = bfd_link_hash_lookup (link_info.hash, buf, true, true, true); if (h == (struct bfd_link_hash_entry *) NULL) einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); if (h->type == bfd_link_hash_new) { h->type = bfd_link_hash_undefined; h->u.undef.abfd = NULL; bfd_link_add_undef (link_info.hash, h); } } free (buf); /* def_file_print (stdout, pe_def_file); */ if (pe_def_file->is_dll == 1) link_info.shared = 1; if (pe_def_file->base_address != (bfd_vma)(-1)) { pe.ImageBase = pe_data (output_bfd)->pe_opthdr.ImageBase = init[IMAGEBASEOFF].value = pe_def_file->base_address; init[IMAGEBASEOFF].inited = 1; if (image_base_statement) image_base_statement->exp = exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase)); }#if 0 /* Not sure if these *should* be set */ if (pe_def_file->version_major != -1) { pe.MajorImageVersion = pe_def_file->version_major; pe.MinorImageVersion = pe_def_file->version_minor; }#endif if (pe_def_file->stack_reserve != -1 && ! saw_option ("__size_of_stack_reserve__")) { pe.SizeOfStackReserve = pe_def_file->stack_reserve; if (pe_def_file->stack_commit != -1) pe.SizeOfStackCommit = pe_def_file->stack_commit; } if (pe_def_file->heap_reserve != -1 && ! saw_option ("__size_of_heap_reserve__")) { pe.SizeOfHeapReserve = pe_def_file->heap_reserve; if (pe_def_file->heap_commit != -1) pe.SizeOfHeapCommit = pe_def_file->heap_commit; } return true; } }#endif return false;}static booleangld_${EMULATION_NAME}_recognized_file(entry) lang_input_statement_type *entry ATTRIBUTE_UNUSED;{#ifdef DLL_SUPPORT#ifdef TARGET_IS_i386pe pe_dll_id_target ("pei-i386");#endif#ifdef TARGET_IS_shpe pe_dll_id_target ("pei-shl");#endif#ifdef TARGET_IS_mipspe pe_dll_id_target ("pei-mips");#endif#ifdef TARGET_IS_armpe pe_dll_id_target ("pei-arm-little");#endif if (bfd_get_format (entry->the_bfd) == bfd_object) { const char *ext = entry->filename + strlen (entry->filename) - 4; if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0) return pe_implied_import_dll (entry->filename); }#endif return false;}static voidgld_${EMULATION_NAME}_finish (){#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) struct bfd_link_hash_entry * h; if (thumb_entry_symbol != NULL) { h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true); if (h != (struct bfd_link_hash_entry *) NULL && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak) && h->u.def.section->output_section != NULL) { static char buffer[32]; bfd_vma val; /* Special procesing is required for a Thumb entry symbol. The bottom bit of its address must be set. */ val = (h->u.def.value + bfd_get_section_vma (output_bfd, h->u.def.section->output_section) + h->u.def.section->output_offset); val |= 1; /* Now convert this value into a string and store it in entry_symbol where the lang_finish() function will pick it up. */ buffer[0] = '0'; buffer[1] = 'x'; sprintf_vma (buffer + 2, val); if (entry_symbol.name != NULL && entry_from_cmdline) einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"), thumb_entry_symbol, entry_symbol.name); entry_symbol.name = buffer; } else einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol); }#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */#ifdef DLL_SUPPORT if (link_info.shared) { pe_dll_fill_sections (output_bfd, &link_info); if (pe_implib_filename) pe_dll_generate_implib (pe_def_file, pe_implib_filename); }#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) /* ARM doesn't need relocs. */ else { pe_exe_fill_sections (output_bfd, &link_info); }#endif if (pe_out_def_filename) pe_dll_generate_def_file (pe_out_def_filename);#endif /* DLL_SUPPORT */ /* I don't know where .idata gets set as code, but it shouldn't be */ { asection *asec = bfd_get_section_by_name (output_bfd, ".idata"); if (asec) { asec->flags &= ~SEC_CODE; asec->flags |= SEC_DATA; } }}/* Find the last output section before given output statement. Used by place_orphan. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -