diff options
author | Nick Clifton <nickc@redhat.com> | 2013-11-22 15:04:23 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2013-11-22 15:04:23 +0000 |
commit | 15b6cd19e80a8e6b9fc86c178fdb03c3bd0ac2fe (patch) | |
tree | 8174a893cc8aa0064af82fe87116006c689648d6 | |
parent | 579cbc8d100dc37627e0562319387755de8626ad (diff) | |
download | binutils-15b6cd19e80a8e6b9fc86c178fdb03c3bd0ac2fe.zip binutils-15b6cd19e80a8e6b9fc86c178fdb03c3bd0ac2fe.tar.gz binutils-15b6cd19e80a8e6b9fc86c178fdb03c3bd0ac2fe.tar.bz2 |
* windres.c (define_resource): Use zero for timestamp, making
output deterministic. time.h include is no longer needed.
* resres.c (res_append_resource): Likewise.
* libcoff-in.h: Add insert_timestamp flag to the pe_data struct.
* libcoff.h: Regenerate.
* peXXigen.c (_bfd_XXi_only_swap_filehdr_out): Only use a real
timestamp if --insert-timestamp was used.
* pe-dll.c (fill_edata): Only use a real timestamp if
--insert-timestamp was used.
* emultempl/pe.em: Add the --insert-timestamp option.
* emultempl/pep.em: Likewise for 64bit.
* ld.texinfo: Document the --insert-timestamp option.
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/libcoff-in.h | 5 | ||||
-rw-r--r-- | bfd/libcoff.h | 5 | ||||
-rw-r--r-- | bfd/peXXigen.c | 8 | ||||
-rw-r--r-- | binutils/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/ChangeLog.orig | 579 | ||||
-rw-r--r-- | binutils/ChangeLog.rej | 12 | ||||
-rw-r--r-- | binutils/resres.c | 16 | ||||
-rw-r--r-- | binutils/windres.c | 15 | ||||
-rw-r--r-- | ld/ChangeLog | 7 | ||||
-rw-r--r-- | ld/ChangeLog.orig | 755 | ||||
-rw-r--r-- | ld/ChangeLog.rej | 14 | ||||
-rw-r--r-- | ld/emultempl/pe.em | 21 | ||||
-rw-r--r-- | ld/emultempl/pep.em | 12 | ||||
-rw-r--r-- | ld/ld.texinfo | 5 | ||||
-rw-r--r-- | ld/pe-dll.c | 8 | ||||
-rw-r--r-- | ld/pe-dll.c.orig | 3452 |
17 files changed, 4883 insertions, 44 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 11a0586..60b769b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2013-11-22 Cory Fields <cory@coryfields.com> + + * libcoff-in.h: Add insert_timestamp flag to the pe_data struct. + * libcoff.h: Regenerate. + * peXXigen.c (_bfd_XXi_only_swap_filehdr_out): Only use a real + timestamp if --insert-timestamp was used. + 2013-11-19 Roland McGrath <mcgrathr@google.com> * elf-nacl.c (nacl_modify_segment_map): Calculate SIZEOF_HEADERS diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h index 6efbc52..49b5f10 100644 --- a/bfd/libcoff-in.h +++ b/bfd/libcoff-in.h @@ -1,7 +1,5 @@ /* BFD COFF object file private structure. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright 1990-2013 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -118,6 +116,7 @@ typedef struct pe_tdata int dll; int has_reloc_section; int dont_strip_reloc; + bfd_boolean insert_timestamp; bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *); flagword real_flags; } pe_data_type; diff --git a/bfd/libcoff.h b/bfd/libcoff.h index 6270bab..19b6d9c 100644 --- a/bfd/libcoff.h +++ b/bfd/libcoff.h @@ -3,9 +3,7 @@ Run "make headers" in your build bfd/ to regenerate. */ /* BFD COFF object file private structure. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright 1990-2013 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -122,6 +120,7 @@ typedef struct pe_tdata int dll; int has_reloc_section; int dont_strip_reloc; + bfd_boolean insert_timestamp; bfd_boolean (*in_reloc_p) (bfd *, reloc_howto_type *); flagword real_flags; } pe_data_type; diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index d0f7a96..287e4a2 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -1,6 +1,5 @@ /* Support for the generic parts of PE/PEI; the common executable parts. - Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright 1995-2013 Free Software Foundation, Inc. Written by Cygnus Solutions. This file is part of BFD, the Binary File Descriptor library. @@ -793,7 +792,10 @@ _bfd_XXi_only_swap_filehdr_out (bfd * abfd, void * in, void * out) H_PUT_16 (abfd, filehdr_in->f_magic, filehdr_out->f_magic); H_PUT_16 (abfd, filehdr_in->f_nscns, filehdr_out->f_nscns); - H_PUT_32 (abfd, time (0), filehdr_out->f_timdat); + /* Only use a real timestamp if the option was chosen. */ + if ((pe_data (abfd)->insert_timestamp)) + H_PUT_32 (abfd, time(0), filehdr_out->f_timdat); + PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr, filehdr_out->f_symptr); H_PUT_32 (abfd, filehdr_in->f_nsyms, filehdr_out->f_nsyms); diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 1b851ab..f9014b5 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2013-11-22 Cory Fields <cory@coryfields.com> + + * windres.c (define_resource): Use zero for timestamp, making + output deterministic. time.h include is no longer needed. + * resres.c (res_append_resource): Likewise. + 2013-11-15 Alan Modra <amodra@gmail.com> Apply changes from mainline to 2.24 diff --git a/binutils/ChangeLog.orig b/binutils/ChangeLog.orig new file mode 100644 index 0000000..1b851ab --- /dev/null +++ b/binutils/ChangeLog.orig @@ -0,0 +1,579 @@ +2013-11-15 Alan Modra <amodra@gmail.com> + + Apply changes from mainline to 2.24 + 2013-10-30 Alan Modra <amodra@gmail.com> + * readelf.c (get_ppc_dynamic_type): Replace PPC_TLSOPT with PPC_OPT. + (get_ppc64_dynamic_type): Replace PPC64_TLSOPT with PPC64_OPT. + + 2013-10-30 Ulrich Weigand <uweigand@de.ibm.com> + * readelf.c (get_ppc64_symbol_other): New function. + (get_symbol_other): Use it for EM_PPC64. + + 2013-10-30 Alan Modra <amodra@gmail.com> + * readelf.c (get_machine_flags): Display ABI version for EM_PPC64. + +2013-11-07 Roland McGrath <mcgrathr@google.com> + + * objdump.c (dump_dwarf): Grok bfd_mach_x86_64_nacl and + bfd_mach_x64_32_nacl as equivalent to bfd_mach_x86_64. + +2013-10-31 Nick Clifton <nickc@redhat.com> + + * nm.c (display_rel_file): Treat bfd_error_no_symbols as + non-fatal. + +2013-10-12 H.J. Lu <hongjiu.lu@intel.com> + + * dwarf.c (display_debug_frames): Pass offset_size to + print_dwarf_vma for cie_id. + +2013-10-11 Roland McGrath <mcgrathr@google.com> + + * winduni.c (languages): Use \345 (octal syntax) rather than + literal non-ASCII/non-UTF8 character in string literal. + +2013-10-11 Roland McGrath <mcgrathr@google.com> + + * readelf.c (print_dynamic_symbol): Use array subscript syntax + rather than addition syntax with string literal. + +2013-10-09 Nick Clifton <nickc@redhat.com> + + * dwarf.c (add64): New function. + (read_and_display_attr_value): Add CU offset in to the value + displayed for a DW_AT_ref8 attribute. + +2013-09-20 Alan Modra <amodra@gmail.com> + + * configure: Regenerate. + +2013-09-18 Tristan Gingold <gingold@adacore.com> + + * NEWS: Add marker for 2.24. + +2013-09-18 Tristan Gingold <gingold@adacore.com> + + * Makefile.am (LEXLIB): Define. Replase references to @LEXLIB@ + by $(LEXLIB). + * Makefile.in: Regenerate. + +2013-09-17 Doug Gilmore <Doug.Gilmore@imgtec.com> + + * readelf.c (get_machine_flags): Handle EF_MIPS_FP64. + +2013-09-12 Nick Clifton <nickc@redhat.com> + + * dwarf.c (dwarf_vmatoa): Rename to dwarf_vmatoa_1 and add a + precision parameter. + (dwarf_vmatoa): New wrapper for dwarf_vmatoa_1. + (print_dwarf_vma): Use dwarf_vmatoa_1. + (SAFE_BYTE_GET): Add check that VAL is big enough to contain + AMOUNT bytes. + (process_debug_info): Use an unsigned int for the offset size. + (process_debug_pubnames): Likewise. + (display_debug_aranges): Likewise. + (struct Frame_Chunk): Use dwarf_vma type for pc_begin and pc_range + fields. + (frame_display_row): Use print_dwarf_vma to display dwarf_vma + values. + (display_debug_frames): Likewise. + +2013-09-10 Nick Clifton <nickc@redhat.com> + + * dwarf.c (display_debug_frames): Check for DW64_CIE_ID when + parsing 64-bit frames. + +2013-08-27 Nick Clifton <nickc@redhat.com> + + PR binutils/15796 + * ar.c (map_over_members): Correctly handle multiple same-name + entries on the command line and in the archive. + +2013-08-23 H.J. Lu <hongjiu.lu@intel.com> + + * doc/binutils.texi: Remove the extra space. + +2013-08-23 Mikael Pettersson <mikpe@it.uu.se> + + PR binutils/15779 + * doc/binutils.texi (ranlib -D): Correct description. + PR binutils/15777 + (nm --special-syms): Fix typo. + +2013-08-23 Nick Clifton <nickc@redhat.com> + + PR binutils/15798 + * doc/binutils.texi (ar cmdline): Update description of 'q' + command. + + PR binutils/14136 + (nm): Add description of 'I' symbol type. + +2013-08-23 Yuri Chornoivan <yurchor@ukr.net> + + PR binutils/15834 + * od-xcoff.c: Fix typos. + +2013-08-19 Tristan Gingold <gingold@adacore.com> + + * nm.c (print_size_symbols): Directly get symbol size. + +2013-08-12 Andreas Schwab <schwab@suse.de> + + PR binutils/15818 + * objdump.c (disassemble_section): Return early if nothing from + this section needs to be disassembled. + +2013-08-09 Nick Clifton <nickc@redhat.com> + + * readelf.c (get_machine_flags): Handle RL78 G10 flag. + +2013-07-26 Sergey Guriev <sergey.s.guriev@intel.com> + Alexander Ivchenko <alexander.ivchenko@intel.com> + Maxim Kuznetsov <maxim.kuznetsov@intel.com> + Sergey Lega <sergey.s.lega@intel.com> + Anna Tikhonova <anna.tikhonova@intel.com> + Ilya Tocar <ilya.tocar@intel.com> + Andrey Turetskiy <andrey.turetskiy@intel.com> + Ilya Verbin <ilya.verbin@intel.com> + Kirill Yukhin <kirill.yukhin@intel.com> + Michael Zolotukhin <michael.v.zolotukhin@intel.com> + + * dwarf.c (dwarf_regnames_i386): Add k0-k7 registers and + numeration in comments. + (dwarf_regnames_x86_64): Add xmm16-31 and k0-k7 registers to + dwarf table. + +2013-07-19 Nick Clifton <nickc@redhat.com> + + PR binutils/15745 + * readelf.c (get_unwind_section_word): Whilst searching for a + reloc section associated with an unwind section, check the type as + well as the section number. + +2013-07-18 Jim Thomas <thomas@cfht.hawaii.edu> + + * ar.c (usage): Fix C conformance issue. + +2013-07-18 Nick Clifton <nickc@redhat.com> + + * doc/binutils.texi (nm, objdump): Remove bogus links to STABS + documentation. + + * readelf.c (process_unwind): Do not return the result of a void + function. + +2013-07-15 Maciej W. Rozycki <macro@codesourcery.com> + + * readelf.c (display_mips_gnu_attribute): Replace hardcoded magic + numbers with enum values. + +2013-07-12 Maciej W. Rozycki <macro@codesourcery.com> + + * readelf.c (get_machine_flags): Handle EF_MIPS_NAN2008. + +2013-07-10 Tristan Gingold <gingold@adacore.com> + + * od-xcoff.c (OPT_LDINFO): Define. + (options): Add ldinfo. + (xcoff_help): Mention ldinfo. + (xcoff_dump): Rename to ... + (xcoff_dump_obj): ... this. Add a break. + (dump_dumpx_core): New function. + (xcoff_dump_core): Likewise. + (xcoff_dump): Likewise. + * doc/binutils.texi (objdump): Mention ldinfo. + +2013-07-09 Tristan Gingold <gingold@adacore.com> + + * configure.com: Add new defines to match changes in configure. + +2013-05-28 Cary Coutant <ccoutant@google.com> + + * dwarf.c (display_debug_lines_raw): Print section offsets. + +2013-05-15 Cary Coutant <ccoutant@google.com> + + * dwarf.c (SAFE_BYTE_GET64): Correct end-of-buffer check; + don't increment PTR. + (decode_location_expression): DW_OP_const2u should read 2 bytes. + (display_debug_lines_decoded): Adjust formatting. + * elfcomm.c (byte_get_little_endian): Add cases for 5-, 6-, and + 7-byte reads. + (byte_get_big_endian): Likewise. + (byte_get_signed): Likewise. + +2013-05-09 Andrew Pinski <apinski@cavium.com> + + * doc/binutils.texi: Document -Mvirt disassembler option. + +2013-05-02 Nick Clifton <nickc@redhat.com> + + * readelf.c: Add support for MSP430X architecture. + +2013-05-02 Nick Clifton <nickc@redhat.com> + + * dwarf.c (display_debug_lines_raw): Do not treat .debug_line.dwo + sections as if they were fragmentary .debug_line sections. + (display_debug_lines_decoded): Likewise. + +2013-04-29 Nick Clifton <nickc@redhat.com> + + * dwarf.c (read_debug_line_header): New function. Reads in a + header in a .debug_line section. + (display_debug_lines_raw): Use new function. Handle fragmentary + .debug_line sections. + (display_debug_lines_decoded): Likewise. + * readelf.c (process_section_headers): Handle fragmenatry + .debug_line sections. + (display_debug_section): Likewise. + +2013-04-26 Ian Lance Taylor <iant@google.com> + + * MAINTAINERS: Add myself and Cary as gold maintainers. + +2013-04-08 Tom Tromey <tromey@redhat.com> + + * dwarf.c (process_debug_info): Check dwarf_cutoff_level. + +2013-04-08 Tom Tromey <tromey@redhat.com> + + * dwarf-mode.el: Bump version number. + (dwarf-mode): Remove autoload. + (dwarf-die-reference): Relax regexp. + +2013-04-05 Alan Modra <amodra@gmail.com> + + PR binutils/15324 + * configure.in: Add strnlen to AC_CHECK_DECLS, sort. + * dwarf.c (strnlen): Provide fallback decl. + * config.in: Regnerate. + * configure: Regenerate. + +2013-03-29 H.J. Lu <hongjiu.lu@intel.com> + + * dwarf.c (process_debug_info): Increment hdrptr by 8 after + SAFE_BYTE_GET64. + +2013-03-27 Phil Krylov <phil.krylov@gmail.com> + + PR binutils/13409 + * winduni.c (codepages[]): Use UTF-16LE. + (wind_MultiByteToWideChar): Likewise. + (wind_WideCharToMultiByte): Likewise. + +2013-03-27 Alan Modra <amodra@gmail.com> + + PR binutils/15206 + * dwarf.c (read_and_display_attr_value): Cast format '*' arg to int. + +2013-03-26 Nick Clifton <nickc@redhat.com> + + PR binutils/15206 + * dwarf.c (SAFE_BYTE_GET): New macro - checks remaining buffer + space before calling byte_get. + (SAFE_BYTE_GET_AND_INC): New macro. + (SAFE_SIGNED_BYTE_GET): New macro. + (SAFE_SIGNED_BYTE_GET_AND_INC): New macro. + (SAFE_BYTE_GET64): New macro. + (process_extened_line_op): Use new macros. Use strnlen when + appropriate. + (fetch_indirect_string): Likewise. + (get_FORM_name): Likewise. + (decode_location_expression): Likewise. + (read_and_display_attr_value): Likewise. + (process_debug_info): Likewise. + (display_debug_lines_raw): Likewise. + (display_debug_lines_decoded): Likewise. + (display_debug_pubnames): Likewise. + (display_debug_macinfo): Likewise. + (get_line_filename_and_dirname): Likewise. + (display_debug_macro): Likewise. + (display_loc_list): Likewise. + (display_loc_list_dwo): Likewise. + (display_debug_aranges): Likewise. + (display_debug_ranges): Likewise. + (frame_display_row): Likewise. + (display_debug_frames): Likewise. + +2013-03-25 Nick Clifton <nickc@redhat.com> + + PR binutils/15202 + * dwarf.c (read_leb128): Add END parameter. Do not read at or + beyond end. + (read_sleb128): Add END parameter. + (read_uleb128): New function. + (process_extended_line_op): Pass END to leb128 functions. + (process_abbrev_section): Likewise. + (decode_location_expression): Likewise. + (read_and_display_attr_value): Likewise. + (read_and_display_attr): Likewise. + (process_debug_info): Likewise. + (display_debug_lines_raw): Likewise. + (display_debug_lines_decoded): Likewise. + (display_debug_macinfo): Likewise. + (get_line_filename_and_dirname): Likewise. + (display_debug_macro): Likewise. + (display_loc_list_dwo): Likewise. + (display_debug_ranges): Likewise. + * dwarf.h (read_leb128): Update prototype. + * readelf.c (read_uleb128): Add END parameter. + (decode_arm_unwind_bytecode): Pass END to read_uleb128. + (decode_tic6x_unwind_bytecode): Likewise. + (display_tag_value): New function. + (display_arm_attribute): Add END parameter. Pass END to + read_uleb128. Use display_tag_value. + (display_gnu_attribute): Likewise. + (display_power_gnu_attribute): Likewise. + (display_sparc_gnu_attribute): Likewise. + (display_mips_gnu_attribute): Likewise. + (display_tic6x_attribute): Likewise. + (process_attributes): Likewise. + (display_raw_attribute): New function. + +2013-03-22 Nick Clifton <nickc@redhat.com> + + PR binutils/15201 + * dwarf.c (display_debug_ranges): Add checks for reading beyond + the end of the section. + + PR binutils/15157 + * readelf.c (apply_relocations): Catch relocations with negative + offsets. + +2013-03-15 Nick Clifton <nickc@redhat.com> + + * addr2line.c (slurp_symtab): If canonicalization reveals that + there were no ordinary symbols, try loading the dynamic symbols + instead. + +2013-03-14 Markos Chandras <markos.chandras@imgtec.com> + + * MAINTAINERS: Add myself as Meta maintainer. + +2013-03-08 Andreas Arnez <arnez@linux.vnet.ibm.com> + + * readelf.c (get_note_type): Add NT_S390_TDB. + +2013-03-07 Alan Modra <amodra@gmail.com> + + * strings.c (get_char): Dispense with buf[]. Instead shift + chars into big-endian value and byte-swap later if + little-endian. Don't EOF check value read from object. + +2013-03-05 Corinna Vinschen <vinschen@redhat.com> + + * configure.in: Build DLL tools on x86_64-*-cygwin* as well. + * configure: Regenerate. + +2013-03-04 Nick Clifton <nickc@redhat.com> + + * elfcomm.c (error): Flush stdout before emitting the error + message. + (warn): Likewise. + +2013-03-01 Cary Coutant <ccoutant@google.com> + + * dwarf.c (cu_tu_indexes_read, shndx_pool, shndx_pool_size) + (shndx_pool_used): Move to top of file. + (struct cu_tu_set): New type. + (cu_count, tu_count, cu_sets, tu_sets): New file scope variables. + (fetch_indexed_string): Add "this_set" parameter. Update all callers. + (find_cu_tu_set_v2): New function. + (read_and_display_attr_value): Add "this_set" parameter. + (read_and_display_attr): Likewise. + (process_debug_info): Track base offsets for DWARF package files. + (load_debug_info): Call load_cu_tu_indexes. + (get_DW_SECT_short_name): New function. + (process_cu_tu_index): Add support for version 2 DWARF package files. + +2013-02-27 Alan Modra <amodra@gmail.com> + + PR binutils/15191 + * readelf.c (offsetof): Define. + (CHECK_ENTSIZE_VALUES): Remove extraneous indefinite article. + (process_corefile_note_segment): Allow notes without name or + desc. Combine out-of-range checks. Disallow "negative" + notesz or descsz. + +2013-02-26 Nick Clifton <nickc@redhat.com> + + PR binutils/15191 + * readelf.c (process_corefile_note_segment): Prevent attempts to + read beyond the end of the note buffer. + +2013-02-15 Kai Tietz <ktietz@redhat.com> + + * objcopy.c (copy_main): Initialize context variable. + +2013-02-15 Nick Clifton <nickc@redhat.com> + + PR binutils/15140 + * ar.c (open_inarch): Fail on attempts to convert a normal archive + to a thin archive or vice versa. + * elfcomm.c (make_qualified_name): Handle corrupted thin + archives. + * readelf.c (process_archive): Likewise. + * doc/binutils.texi: Clarify documentation describing thin + archives. + +2013-02-15 Nick Clifton <nickc@redhat.com> + + PR binutils/15033 + * objcopy.c (enum change_action): Delete. + (struct section_list): Delete remove, copy, change_vma, change_lma + and set_flags fields. Add context field. + (find_section_list): Add a context parameter. Add support for + wildcard characters in section names. + (is_strip_section): Check for sections being both copied and + removed. + (copy_object): Pass context to find_section_list. + (setup_section): Likewise. + (copy_section): Likewise. + (copy_main): Likewise. + * doc/binutils: Document the new behaviour. + * NEWS: Mention the new feature + +2013-02-14 Nick Clifton <nickc@redhat.com> + + PR binutils/15125 + * objcopy.c (copy_object): Provide a helpful warning message when + adding a gnu_debuglink section to an object which already contains + one. + +2013-02-07 Nick Clifton <nickc@redhat.com> + + * elfcomm.c (get_archive_member_name): Prevent seg-fault if a + corrupt archive uses long names but has no long name table. + +2013-02-06 Sandra Loosemore <sandra@codesourcery.com> + Andrew Jenner <andrew@codesourcery.com> + + Based on patches from Altera Corporation. + + * readelf.c: Include elf/nios2.h. + (dump_relocations): Add case for EM_ALTERA_NIOS2. + (get_nios2_dynamic_type): New. + (get_dynamic_type): Add case for EM_ALTERA_NIOS2. + (is_32bit_abs_reloc): Fix EM_ALTERA_NIOS2 case. + (is_16bit_abs_reloc): Likewise. + (is_none_reloc): Add EM_ALTERA_NIOS2 and EM_NIOS32 cases. + * NEWS: Note Altera Nios II support. + * MAINTAINERS: Add Nios II maintainers. + +2013-01-29 Xi Wang <xi.wang@gmail.com> + + * readelf.c (process_version_sections): Fix overflow checks to + avoid undefined behaviour. + +2013-01-28 Doug Evans <dje@google.com> + + * dwarf.c (display_gdb_index): Handle .gdb_index version 8. + +2013-01-28 Robert Schiele <rschiele@gmail.com> + + * objcopy.c (parse_flags): Add merge and strings section flags. + +2013-01-25 Cary Coutant <ccoutant@google.com> + + * dwarf.c (display_loc_list): Update offset for each line + printed. + (print_addr_index): New function. + (display_loc_list_dwo): Update offset for each line printed. + Fix problems displaying loclists in .dwo files. Add support + for type 4 entries. + (display_debug_loc): Remove custom header for .dwo files. + (display_debug_addr): Adjust formatting. + +2013-01-25 Marco Atzeri <marco.atzeri@gmail.com> + + * objcopy.c : Enable long section names for OPTION_ADD_GNU_DEBUGLINK. + +2013-01-24 Doug Evans <dje@google.com> + + * dwarf.c (display_debug_addr): Add missing parentheses to expression. + +2013-01-24 Nick Clifton <nickc@redhat.com> + + * readelf.c (get_machine_flags): Decode E_V850E3V5_ARCH. + +2013-01-23 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + + * readelf.c: Add strings for NT_S390_LAST_BREAK and + NT_S390_SYSTEM_CALL. + +2013-01-18 Nick Clifton <nickc@redhat.com> + + PR binutils/15026 + * addr2line.c (translate_addresses): When pretty printing, print + unknown function names on the same line as unknown symbol names. + +2013-01-17 Nickolai Zeldovich <nickolai@csail.mit.edu> + + * objdump.c (dump_target_specific): Fix NULL pointer test. + +2013-01-16 Alan Modra <amodra@gmail.com> + + PR binutils/15018 + * stabs.c (parse_stab_members): Always set physname here to avoid + gcc warning.. + (parse_stab_argtypes): ..and don't duplicate the init here. + +2013-01-10 Will Newton <will.newton@imgtec.com> + + * binutils/readelf.c: (guess_is_rela): Add EM_METAG. + (dump_relocations): Add EM_METAG. + (get_machine_name): Correct case for Meta. + (is_32bit_abs_reloc): Add support for Meta ADDR32 reloc. + (is_none_reloc): Add support for Meta NONE reloc. + +2013-01-08 Yufeng Zhang <yufeng.zhang@arm.com> + + * readelf.c (get_note_type): Handle NT_ARM_TLS, NT_ARM_HW_BREAK + and NT_ARM_HW_WATCH. + +2013-01-07 Roland McGrath <mcgrathr@google.com> + + * objcopy.c (deterministic): Make int rather than bfd_boolean, + initialize to -1. + (strip_options, copy_options): Add -U/--disable-deterministic-archives. + (default_deterministic): New function. + (strip_main, copy_main): Handle -U. Call default_deterministic. + (copy_usage, strip_usage): Describe -U. Cite whether -D or -U is + the default based on DEFAULT_AR_DETERMINISTIC. + * doc/binutils.texi (objcopy, strip): Describe -U and effect of + configure options on -D. + + * ar.c (default_deterministic): Comment fix. + +2013-01-07 Patrice Dumas <pertusus@free.fr> + + * doc/binutils.texi: Fix ordering of top level nodes. + Replace erroneous uses of @itemx with @item. + +2013-01-04 Andreas Schwab <schwab@linux-m68k.org> + + * doc/binutils.texi (elfedit): Fix use of @itemx in @table. + +2013-01-03 Marcus Shawcroft <marcus.shawcroft@arm.com> + + * MAINTAINERS: Add myself as AArch64 co-maintainer. + +2013-01-02 H.J. Lu <hongjiu.lu@intel.com> + + * version.c (print_version): Update copyright year to 2013. + +For older changes see ChangeLog-2012 + +Copyright (C) 2013 Free Software Foundation, Inc. + +Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/binutils/ChangeLog.rej b/binutils/ChangeLog.rej new file mode 100644 index 0000000..19df888 --- /dev/null +++ b/binutils/ChangeLog.rej @@ -0,0 +1,12 @@ +--- binutils/ChangeLog ++++ binutils/ChangeLog +@@ -1,3 +1,9 @@ ++2013-11-22 Cory Fields <cory@coryfields.com> ++ ++ * windres.c (define_resource): Use zero for timestamp, making ++ output deterministic. time.h include is no longer needed. ++ * resres.c (res_append_resource): Likewise. ++ + 2013-11-13 Martin Mitas <mity@morous.org> + + * rescoff.c (write_coff_file): Use 64-bit alignment for resource diff --git a/binutils/resres.c b/binutils/resres.c index ff95cb5..84f956f 100644 --- a/binutils/resres.c +++ b/binutils/resres.c @@ -1,6 +1,5 @@ /* resres.c: read_res_file and write_res_file implementation for windres. - Copyright 1998, 1999, 2001, 2002, 2005, 2007, 2008, 2011 - Free Software Foundation, Inc. + Copyright 1998-2013 Free Software Foundation, Inc. Written by Anders Norlander <anorland@hem2.passagen.se>. Rewritten by Kai Tietz, Onevision. @@ -32,7 +31,6 @@ #include "windres.h" #include <assert.h> -#include <time.h> static rc_uint_type write_res_directory (windres_bfd *, rc_uint_type, const rc_res_directory *, const rc_res_id *, @@ -660,17 +658,13 @@ res_append_resource (rc_res_directory **res_dirs, rc_res_resource *resource, if (*res_dirs == NULL) { - static unsigned long timeval; - - /* Use the same timestamp for every resource created in a - single run. */ - if (timeval == 0) - timeval = time (NULL); - *res_dirs = ((rc_res_directory *) res_alloc (sizeof (rc_res_directory))); + (*res_dirs)->characteristics = 0; - (*res_dirs)->time = timeval; + /* Using a real timestamp only serves to create non-deterministic + results. Use zero instead. */ + (*res_dirs)->time = 0; (*res_dirs)->major = 0; (*res_dirs)->minor = 0; (*res_dirs)->entries = NULL; diff --git a/binutils/windres.c b/binutils/windres.c index 7de73ef..64afb3a 100644 --- a/binutils/windres.c +++ b/binutils/windres.c @@ -1,6 +1,5 @@ /* windres.c -- a program to manipulate Windows resources - Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2011, 2012 Free Software Foundation, Inc. + Copyright 1997-2013 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. Rewritten by Kai Tietz, Onevision. @@ -37,7 +36,6 @@ #include "sysdep.h" #include <assert.h> -#include <time.h> #include "bfd.h" #include "getopt.h" #include "bucomm.h" @@ -339,17 +337,12 @@ define_resource (rc_res_directory **resources, int cids, if (*resources == NULL) { - static unsigned int timeval; - - /* Use the same timestamp for every resource created in a - single run. */ - if (timeval == 0) - timeval = time (NULL); - *resources = ((rc_res_directory *) res_alloc (sizeof (rc_res_directory))); (*resources)->characteristics = 0; - (*resources)->time = timeval; + /* Using a real timestamp only serves to create non-deterministic + results. Use zero instead. */ + (*resources)->time = 0; (*resources)->major = 0; (*resources)->minor = 0; (*resources)->entries = NULL; diff --git a/ld/ChangeLog b/ld/ChangeLog index 02e85af..ae4c08d 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2013-11-22 Cory Fields <cory@coryfields.com> + + * libcoff-in.h: Add insert_timestamp flag to the pe_data struct. + * libcoff.h: Regenerate. + * peXXigen.c (_bfd_XXi_only_swap_filehdr_out): Only use a real + timestamp if --insert-timestamp was used. + 2013-11-19 Roland McGrath <mcgrathr@google.com> Alan Modra <amodra@gmail.com> diff --git a/ld/ChangeLog.orig b/ld/ChangeLog.orig new file mode 100644 index 0000000..02e85af --- /dev/null +++ b/ld/ChangeLog.orig @@ -0,0 +1,755 @@ +2013-11-19 Roland McGrath <mcgrathr@google.com> + Alan Modra <amodra@gmail.com> + + * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): + Don't use bfd_elf_record_link_assignment to mark __ehdr_start + hidden. Instead, just do it directly here, and only if it was + referenced but not defined. + +2013-11-18 Chung-Lin Tang <cltang@codesourcery.com> + + Backport from master + 2013-11-18 Chung-Lin Tang <cltang@codesourcery.com> + * emulparams/nios2linux.sh: New emulation file. + * configure.tgt: Add nios2*-*-linux* emulation case. + * Makefile.am (enios2elf.c): Change tdir_nios2 to tdir_nios2elf. + (enios2linux.c): New emulation entry. + * Makefile.in: Regenerate. + +2013-11-15 Alan Modra <amodra@gmail.com> + + Apply mainline changes to 2.24 + 2013-09-24 Alan Modra <amodra@gmail.com> + * emulparams/elf32ppccommon.sh (LIBPATH_SUFFIX): Provide 32-bit + and cross-endian values. + * emulparams/elf64ppc.sh: Source elf32ppccomon.sh. Delete duplicate, + and unset unwanted variables. + +2013-10-10 Roland McGrath <mcgrathr@google.com> + + * ldmisc.c (vfinfo): Use Boolean ? "" : ":" in place of ":" + Boolean. + It silences some compilers' warnings and is much less bizarre to read. + +2013-10-09 Roland McGrath <mcgrathr@google.com> + + * emultempl/elf32.em (id_note_section_size): Use ATTRIBUTE_UNUSED + rather than a dummy assignment for unused parameter. + * plugin.c (get_input_file, release_input_file): Likewise. + +2013-10-04 Will Newton <will.newton@linaro.org> + + * emulparams/aarch64elf.sh: Add IREL_IN_PLT. + * emulparams/aarch64elf32.sh: Likewise. + +2013-09-20 Alan Modra <amodra@gmail.com> + + * configure: Regenerate. + +2013-09-18 Tristan Gingold <gingold@adacore.com> + + * NEWS: Add marker for 2.24. + +2013-09-17 Nick Clifton <nickc@redhat.com> + + PR ld/15957 + * deffilep.y (def_file_add_directive): Avoid readin past end of + buffer. + +2013-08-28 Nick Clifton <nickc@redhat.com> + + PR ld/15896 + * ld.texinfo: Fix uses of MB abbreviation. + +2013-08-26 Roland McGrath <mcgrathr@google.com> + + * emulparams/elf_i386_nacl.sh (ARCH): Set to i386:nacl. + * emulparams/elf_x86_64_nacl.sh (ARCH): Set to i386:x86-64:nacl. + * emulparams/elf32_x86_64_nacl.sh (ARCH): Set to i386:x64-32:nacl. + +2013-08-23 Roland McGrath <mcgrathr@google.com> + + * emulparams/elf_nacl.sh (nacl_rodata_addr): Don't add in + SIZEOF_HEADERS here; elf.sc does it already. + +2013-08-23 Nick Clifton <nickc@redhat.com> + + PR ld/15839 + * scripttempl/avr.sc: Do not include gc'able sections into general + sections during relocatable links. + +2013-08-22 Christian Franke <franke@computer.org> + + * emultempl/pe.em: Add --disable-large-address-aware option. + * ld.texinfo (--disable-large-address-aware): Add documentation. + +2013-08-14 Clemens Lang <clemens.lang@fau.de> + + * ldexp.c: Add LOG2CEIL() builtin function to linker script language + * ldgram.y: Likewise + * ldlex.l: Likewise + * NEWS: Mention the new feature. + * ld.texinfo: Document the new feature. + +2013-07-19 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * ldgram.y: Add ALIGN_WITH_INPUT output section attribute. + * ldlang.c: Likewise. + * ldlang.h: Likewise. + * ldlex.l: Likewise. + * mri.c: Likewise. + * ld.texinfo: Document new feature. + * NEWS: Mention new feature. + +2013-07-18 Roland McGrath <mcgrathr@google.com> + + * emultempl/armelf.em (elf32_arm_add_stub_section): Take third + argument ALIGNMENT_POWER, use it instead of constant 3. + +2013-07-08 Jeff Law <law@redhat.com> + + * scripttempl/elf.sc: Handle function names and other text after + .text.unlikely too. + +2013-07-08 Tristan Gingold <gingold@adacore.com> + + * scripttempl/ia64vms.sc: Add support of per data and per function + sections. + +2013-07-01 Alan Modra <amodra@gmail.com> + + * emultempl/ppc64elf.em: (ppc_layout_sections_again): Call + ppc64_elf_set_toc rather than ppc64_elf_toc/_bfd_set_gp_value. + (gld${EMULATION_NAME}_after_allocation): Likewise. + +2013-06-26 Yufeng Zhang <yufeng.zhang@arm.com> + + * emulparams/aarch64elf32.sh: New file. + +2013-06-26 Yufeng Zhang <yufeng.zhang@arm.com> + + * Makefile.am (ALL_64_EMULATION_SOURCES): Add eaarch64elf32b.c. + (eaarch64elf32b.c): New dependency and rule. + * Makefile.in: Re-generated. + * configure.tgt (aarch64-*-elf): Add aarch64elf32b. + (aarch64_be-*-elf, aarch64_be-*-linux*, aarch64-*-linux*): Likewise. + * emulparams/aarch64elf32b.sh: New file. + +2013-06-26 Yufeng Zhang <yufeng.zhang@arm.com> + + * Makefile.am (ALL_64_EMULATION_SOURCES): Add eaarch64elf32.c. + (eaarch64elf32.c): New dependency and rule. + * Makefile.in: Re-generated. + * configure.tgt (aarch64-*-elf): Add aarch64elf32. + (aarch64_be-*-elf, aarch64_be-*-linux*, aarch64-*-linux*): Likewise. + * emulparams/aarch64elf32.sh: New file. + +2013-06-25 Maciej W. Rozycki <macro@codesourcery.com> + + * emultempl/mipself.em (insn32): New variable. + (mips_create_output_section_statements): Handle insn32 mode. + (PARSE_AND_LIST_PROLOGUE): New macro. + (PARSE_AND_LIST_LONGOPTS): Likewise. + (PARSE_AND_LIST_OPTIONS): Likewise. + + * gen-doc.texi: Set MIPS. + * ld.texinfo: Likewise. + (Options specific to MIPS targets): New section. + (ld and MIPS family): New node. + (Top, Machine Dependent): List the new node. + +2013-06-24 Maciej W. Rozycki <macro@codesourcery.com> + + * emulparams/elf32btsmip.sh: Arrange for .got.plt to be placed + as close to .plt as possible. + * scripttempl/elf.sc: Handle $INITIAL_READWRITE_SECTIONS and + $PLT_NEXT_DATA variables. + +2013-06-23 Richard Sandiford <rdsandiford@googlemail.com> + + * Makefile.am (ALL_EMULATION_SOURCES): Move MIPS ELF emulations to... + (ALL_64_EMULATION_SOURCES): ...here. + * Makefile.in: Regenerate. + +2013-06-22 Richard Sandiford <rdsandiford@googlemail.com> + + * NEWS: Document the removal of MIPS ECOFF targets. + * ld.texinfo (--gpsize=@var{value}): Use MIPS ELF rather than + MIPS ECOFF as an example of a target that supports small data. + * ldmain.c (g_switch_value): Likewise. + * configure.tgt (mips*-*-pe, mips*-dec-ultrix*, mips*-dec-osf*) + (mips*-sgi-irix* [v4 and earlier], mips*el-*-ecoff*, mips*-*-ecoff*) + (mips*-*-bsd*, mips*-*-lnews*): Remove cases. + * Makefile.am (ALL_EMULATION_SOURCES): Remove emipsbig.c, emipsbsd.c, + emipsidt.c, emipsidtl.c, emipslit.c, emipslnews.c and emipspe.c. + (emipsbig.c, emipsbsd.c, emipsidt.c, emipsidtl.c, emipslit.c) + (emipslnews.c, emipspe.c): Delete rules. + * Makefile.in: Regenerate. + * emulparams/mipsbig.sh, emulparams/mipsbsd.sh, emulparams/mipsidt.sh, + emulparams/mipsidtl.sh, emulparams/mipslit.sh, emulparams/mipslnews.sh, + emulparams/mipspe.sh, emultempl/mipsecoff.em: Delete. + * emultempl/m68kcoff.em: Update comment to say that MIPS ECOFF support + has now been removed. + * emultempl/pe.em: Remove TARGET_IS_mipspe checks. + +2013-06-19 Will Newton <will.newton@linaro.org> + + * emulparams/aarch64elf.sh: Remove IREL_IN_PLT. + +2013-06-14 Yufeng Zhang <yufeng.zhang@arm.com> + + * emulparams/aarch64elf.sh: Add IREL_IN_PLT. + +2013-06-12 Nick Clifton <nickc@redhat.com> + + * ldcref.c (output_one_cref): Place common definitions after + ordinary definitions but before references. + +2013-06-10 Dilyan Palauzov <dilyan.palauzov@aegee.org> + + PR ld/15598 + * ld.texinfo (Source Code Reference): Fix typos. + +2013-06-07 Will Newton <will.newton@linaro.org> + + * emulparams/aarch64elf.sh: Add IREL_IN_PLT. + +2013-06-07 Nick Clifton <nickc@redhat.com> + + * ld.texinfo (SEGMENT_START): Rephrase to indicate that a -T + option must appear before the SEGMENT_START is encountered in + order for the default value to be overridden. + +2013-05-03 Alan Modra <amodra@gmail.com> + + PR ld/15365 + * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): + Restrict __ehdr_start's export class to no less than STV_HIDDEN. + +2013-05-03 Alan Modra <amodra@gmail.com> + + * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): + Only call lang_for_each_statement if an ELF hash table is used. + +2013-05-02 Nick Clifton <nickc@redhat.com> + + * Makefile.am: Add emsp430X.c + * Makefine.in: Regenerate. + * configure.tgt (msp430): Add msp430X emulation. + * ldmain.c (multiple_definition): Only disable relaxation if it + was enabled by the user. + * ldmain.h (RELAXATION_ENABLED_BY_USER): New macro. + * emulparams/msp430all.sh: Add support for MSP430X. + * emultempl/generic.em: (before_parse): Enable relaxation for the + MSP430. + * scripttempl/msp430.sc: Reorganize sections. Add .rodata + section. + * scripttempl/msp430_3.sc: Likewise. + * NEWS: Mention support for MSP430X. + +2013-05-01 Maciej W. Rozycki <macro@codesourcery.com> + + * configure.tgt: Replace alpha*-*-linuxecoff* pattern with + alpha*-*-linux*ecoff*. Update the `sed' pattern used to convert + from alpha*-*-linux-* to alpha*-*-linux*ecoff*. + +2013-05-01 Maciej W. Rozycki <macro@codesourcery.com> + + * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): + Use is_elf_hash_table rather than a handcoded condition. + +2013-04-30 Nick Clifton <nickc@redhat.com> + + * ld.texinfo (SORT_BY_ALIGNMENT): Fix and clarify typo - sections + are sorted by descending order of alignment. + +2013-04-29 Nick Clifton <nickc@redhat.com> + + * scripttempl/DWARF.sc: Add support for .debug_line.* and + .debug_line_end. + +2013-04-29 Yaakov Selkowitz <yselkowitz@users.sourceforge.net> + + * emultempl/pe.em [cygwin]: Do not merge rdata with v2 + psuedo-relocs. + +2013-04-28 Thomas Schwinge <thomas@codesourcery.com> + + * scripttempl/armbpabi.sc: Replace "source" usage with ".". + * scripttempl/avr.sc: Likewise. + * scripttempl/elf.sc: Likewise. + * scripttempl/elf32cr16.sc: Likewise. + * scripttempl/elf32crx.sc: Likewise. + * scripttempl/elf32msp430.sc: Likewise. + * scripttempl/elf32msp430_3.sc: Likewise. + * scripttempl/elf32sh-symbian.sc: Likewise. + * scripttempl/elf64hppa.sc: Likewise. + * scripttempl/elf_chaos.sc: Likewise. + * scripttempl/elfd10v.sc: Likewise. + * scripttempl/elfd30v.sc: Likewise. + * scripttempl/elfi370.sc: Likewise. + * scripttempl/elfm68hc11.sc: Likewise. + * scripttempl/elfm68hc12.sc: Likewise. + * scripttempl/elfxgate.sc: Likewise. + * scripttempl/elfxtensa.sc: Likewise. + * scripttempl/epiphany_4x4.sc: Likewise. + * scripttempl/i386beos.sc: Likewise. + * scripttempl/i386go32.sc: Likewise. + * scripttempl/ia64vms.sc: Likewise. + * scripttempl/ip2k.sc: Likewise. + * scripttempl/iq2000.sc: Likewise. + * scripttempl/mep.sc: Likewise. + * scripttempl/mmo.sc: Likewise. + * scripttempl/v850.sc: Likewise. + * scripttempl/v850_rh850.sc: Likewise. + * scripttempl/xstormy16.sc: Likewise. + +2013-04-26 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + * scripttempl/avr.sc: Add ALIGN directive after *(.progmem*). + +2013-04-26 Alan Modra <amodra@gmail.com> + + * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Test + unresolved_syms_in_shared_libs rather than !executable to + determine whether to load DT_NEEDED libraries. + +2013-04-25 Alan Modra <amodra@gmail.com> + + * Makefile.am (ALL_EMULATION_SOURCES): Add eelf32lppclinux.c. + (eelf32lppclinux.c): New rule. + * Makefile.in: Regenerate. + * configure.tgt: Merge powerpc-linux and other powerpc-elf targets + with corresponding little-endian targets. + * emulparams/elf32lppc.sh: Update comment. + * emulparams/elf32lppclinux.sh: New. + +2013-04-24 H.J. Lu <hongjiu.lu@intel.com> + + * configure.tgt (targ_extra_emuls): Adds elf32_x86_64 for + x86_64-*-elf*. + (targ_extra_libpath): Likewise. + (tdir_elf_i386): Replace x86_64 with i386 for x86_64-*-elf*. + +2013-04-24 Yufeng Zhang <yufeng.zhang@arm.com> + + * emulparams/aarch64elf.sh: Define ELFSIZE=64. + * emulparams/aarch64linux.sh: Ditto. + * emultempl/aarch64elf.em (aarch64_elf_before_allocation): + Replace elf64 with elf${ELFSIZE}. + (elf64_aarch64_add_stub_section): Likewise. + (build_section_lists): Likewise. + (gld${EMULATION_NAME}_after_allocation): Likewise. + (gld${EMULATION_NAME}_finish): Likewise. + (aarch64_elf_create_output_section_statements): Likewise. + +2013-04-24 Nick Clifton <nickc@redhat.com> + + PR ld/15389 + * scripttempl/avr.sc: Add .note.gnu.build-id section. + +2013-04-22 Alan Modra <amodra@gmail.com> + + * emultempl/ppc64elf.em (ppc_create_output_section_statements): + Check return from ppc64_elf_init_stub_bfd. + +2013-04-15 Nick Clifton <nickc@redhat.com> + + * Makefile.am (ELF_DEPS): Add a dependency upon + scripttempl/DWARF.sc. + (ELF_GEN_DEPS): Likewise. + (emmo.c): Likewise. + * Makefile.in: Regenerate. + + * scripttempl/armbpabi.sc: Replace DWARF sections with an + inclusion of DWARF.sc. + * scripttempl/avr.sc: Likewise. + * scripttempl/elf.sc: Likewise. + * scripttempl/elf32cr16.sc: Likewise. + * scripttempl/elf32crx.sc: Likewise. + * scripttempl/elf32msp430.sc: Likewise. + * scripttempl/elf32msp430_3.sc: Likewise. + * scripttempl/elf32sh-symbian.sc: Likewise. + * scripttempl/elf64hppa.sc: Likewise. + * scripttempl/elf_chaos.sc: Likewise. + * scripttempl/elfd10v.sc: Likewise. + * scripttempl/elfd30v.sc: Likewise. + * scripttempl/elfi370.sc: Likewise. + * scripttempl/elfm68hc11.sc: Likewise. + * scripttempl/elfm68hc12.sc: Likewise. + * scripttempl/elfxgate.sc: Likewise. + * scripttempl/elfxtensa.sc: Likewise. + * scripttempl/epiphany_4x4.sc: Likewise. + * scripttempl/i386beos.sc: Likewise. + * scripttempl/i386go32.sc: Likewise. + * scripttempl/ia64vms.sc: Likewise. + * scripttempl/ip2k.sc: Likewise. + * scripttempl/iq2000.sc: Likewise. + * scripttempl/mep.sc: Likewise. + * scripttempl/mmo.sc: Likewise. + * scripttempl/v850.sc: Likewise. + * scripttempl/v850_rh850.sc: Likewise. + * scripttempl/xstormy16.sc: Likewise. + * scripttempl/DWARF.sc: New. + +2013-04-04 Alan Modra <amodra@gmail.com> + + * ldlang.c (load_symbols): Report "error adding symbols" on + bfd_link_add_symbols failure. + * emultempl/elf32.em (gld${EMULATION_NAME}_try_needed): Likewise. + * emultempl/sunos.em (gld${EMULATION_NAME}_after_open): Likewise. + (gld${EMULATION_NAME}_try_needed): Likewise. + +2013-03-27 Georg-Johann Lay <gjl@gcc.gnu.org> + + PR ld/13812 + * scripttempl/avr.sc: Place trampolines before .progmem section. + +2013-03-25 Kai Tietz <ktietz@redhat.com> + + * ld.texinfo (--disable-runtime-pseudo-reloc): Adjust default. + +2013-03-21 Michael Schewe <michael.schewe@gmx.net> + + * ld.texinfo (H8/300): Add description of relaxation of + mov @(disp:32,ERx) to mov @(disp:16,ERx). + +2013-03-21 Kai Tietz <ktietz@redhat.com> + + * pe-dll.c (process_def_file_and_drectve): Don't handle VC + generated C++-symbols as stdcall/fastcall. + +2013-03-18 Alan Modra <amodra@gmail.com> + + * ld.texinfo (--as-needed): Update. + +2013-03-14 Jakub Jelinek <jakub@redhat.com> + + * emulparams/aarch64linux.sh (LIBPATH_SUFFIX): Set to 64 for + aarch64linux* emulations. + +2013-03-07 Alan Modra <amodra@gmail.com> + + * ldfile.c (ldfile_open_command_file_1): Return after einfo + to avoid warning. + +2013-03-05 Corinna Vinschen <vinschen@redhat.com> + + * configure.host: Add x86_64-*-cygwin* as valid host. + * configure.tgt: Add x86_64-*-cygwin* as valid target. + * emultempl/pep.em: Handle different requirements for Cygwin in terms + of start addresses for executables and DLLs, based on memory model in + http://cygwin.com/ml/cygwin-developers/2013-02/msg00027.html + +2013-03-05 Alan Modra <amodra@gmail.com> + + PR ld/15222 + * ldlang.c (lang_size_sections_1): When given an lma_region align + LMA as per VMA only if lma_region is the same as region. + +2013-02-27 Nick Clifton <nickc@redhat.com> + + * scripttempl/elf32msp430.sc: Add placement of .data.* sections. + Add alignment of .bss section. + * scripttempl/elf32msp430_3.sc: Likewise. + +2013-02-26 Nick Clifton <nickc@redhat.com> + + PR ld/15188 + * ld.texinfo: Fix typos. + +2013-02-21 Alan Modra <amodra@gmail.com> + + * scripttempl/elf.sc (.init_array, .fini_array): Don't sort all + .init_array/.fini_array input sections before .ctors/.dtors input + sections. + (CTORS_IN_INIT_ARRAY, DTORS_IN_INIT_ARRAY): Adjust to suit. + +2013-02-21 Alan Modra <amodra@gmail.com> + + * emultempl/elf32.em (write_build_id, setup_build_id): Adjust + for elf_tdata changes. + +2013-02-21 Alan Modra <amodra@gmail.com> + + * emultempl/elf-generic.em: Use newly defined elf_obj_tdata + accessor macros. + +2013-02-20 Alan Modra <amodra@gmail.com> + + * Makefile.am: Use $(ELF_DEPS) on a number of eelf*.c rules. + * Makefile.in: Regenerate. + +2013-02-19 Sandra Loosemore <sandra@codesourcery.com> + + PR ld/15146 + * plugin.c (plugin_notice): Add null check before dereferencing + pointer. + +2013-02-19 Alan Modra <amodra@gmail.com> + + * emultempl/elf32.em (emit_note_gnu_build_id): New static var. + Replace all info->emit_note_gnu_build_id refs. + (id_note_section_size): Rename from + gld${EMULATION_NAME}_id_note_section_size. + (struct build_id_info): Delete. + (write_build_id): Rename from + gld${EMULATION_NAME}_write_build_id_section. + Update elf_tdata usage. Style, formatting. + (setup_build_id): New function. + (gld${EMULATION_NAME}_after_open): Use setup_build_id. + +2013-02-16 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/15146 + * plugin.c (plugin_notice): Replace the undefined dummy bfd with + the real one. + +2013-02-16 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/15141 + * plugin.c (plugin_notice): Also trace symbol from the IR bfd. + +2013-02-15 Kai Tietz <ktietz@redhat.com> + + * scripttempl/pep.sc (.xdata): Merge .xdata* into .xdata section. + (.pdata): Merge .pdata* into .pdata section. + +2013-02-11 Alan Modra <amodra@gmail.com> + + * ldlang.c (get_init_priority): Comment typo. + (lang_finish): Free link_info.hash and lang_definedness_table. + (lang_end): Delete lang_definedness_table comment. + +2013-02-11 Alan Modra <amodra@gmail.com> + + PR ld/15130 + * ld.texinfo (-rpath-link): Typo fix. + +2013-02-08 Markos Chandras <markos.chandras@imgtec.com> + + * emultempl/metagelf.em (build_section_lists): Use sec_info_type + rather than userdata->flags.just_syms. + +2013-02-06 Sandra Loosemore <sandra@codesourcery.com> + Andrew Jenner <andrew@codesourcery.com> + + Based on patches from Altera Corporation. + + * Makefile.am (enios2elf.c): New rule. + * Makefile.in: Regenerated. + * configure.tgt: Add case for nios2*-*-*. + * emulparams/nios2elf.sh: New file. + * NEWS: Note Altera Nios II support. + +2013-02-06 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + * emultempl/avrelf.em (avr_elf_before_parse): New function. + (LDEMUL_BEFORE_PARSE): Define. + +2013-02-06 Alan Modra <amodra@gmail.com> + + PR ld/15096 + * emultempl/elf32.em: Revert 2013-02-04, 2013-01-22 and 2013-01-21. + * emultempl/alphaelf.em: Revert 2013-02-04. + * emultempl/cr16elf.em: Likewise. + * emultempl/crxelf.em: Likewise. + * emultempl/hppaelf.em: Likewise. + * emultempl/ia64elf.em: Likewise. + * emultempl/mipself.em: Likewise. + * NEWS: Revert 2013-01-21. + +2013-02-04 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/15096 + * emultempl/alphaelf.em (alpha_after_parse): Call + gld${EMULATION_NAME}_after_parse instead of after_parse_default. + * emultempl/cr16elf.em (cr16elf_after_parse): Likewise. + * emultempl/crxelf.em (crxelf_after_parse): Likewise. + * emultempl/hppaelf.em (hppaelf_after_parse): Likewise. + * emultempl/mipself.em (mips_after_parse): Likewise. + + * emultempl/ia64elf.em (gld${EMULATION_NAME}_after_parse): Renamed + to ... + (gld_${EMULATION_NAME}_after_parse): This. Call + gld${EMULATION_NAME}_after_parse instead of after_parse_default. + (LDEMUL_AFTER_PARSE): Set to gld_${EMULATION_NAME}_after_parse. + + * emultempl/elf32.em (new_dtags_set): New variable. + (gld${EMULATION_NAME}_before_parse): Don't set link_info.new_dtags + here. + (gld${EMULATION_NAME}_after_parse): New function. + (ld_${EMULATION_NAME}_emulation): Replace after_parse_default' + with gld${EMULATION_NAME}_after_parse. + (gld${EMULATION_NAME}_handle_option): Set new_dtags_set to TRUE + when setting link_info.new_dtags. + +2013-01-25 Kai Tietz <ktietz@redhat.com> + + * deffilep.y (def_image_name): Adjust type of base-address + argument. + (%union): Add new type bfd_vma as vma. + (VMA): New rule. + (opt_base): Use VMA instead of NUMBER rule to evaluate value. + (def_file_print): Use bfd's fprintf_vma to output base-address. + +2013-01-24 Nick Clifton <nickc@redhat.com> + + * NEWS: Mention support for V850E3V5 architecture. + +2013-01-23 Martin Koegler <martin.koegler@chello.at> + + PR ld/15041 + * scripttempl/pep.sc (.pdata): Only accept .pdata sections. + (.xdata): Similarly. + (.debug_frame): Similarly. + +2013-01-23 Georg-Johann Lay <avr@gjlay.de> + + PR ld/15037 + * scripttempl/avr.sc (.eeprom): Keep it. + +2013-01-23 Leif Ekblad <leif@rdos.net> + + * Makefile.am (ALL_64_EMULATION_SOURCES): Add eelf64rdos.c. + (eelf64rdos.c): New rule. + * emulparams/elf64rdos.sh: New file. + * configure.tgt (x86_64-*-rdos*): Use above. + * Makefile.in: Regenerate. + +2013-01-22 Roland McGrath <mcgrathr@google.com> + + * emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set + new_dtags to TRUE for *-*-nacl* targets. + +2013-01-21 Mike Frysinger <vapier@gentoo.org> + + * emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set + link_info.new_dtags to TRUE for linux/gnu targets. + * NEWS: Mention new dtags default. + +2013-01-19 H.J. Lu <hongjiu.lu@intel.com> + + * Makefile.am (HOSTING_SCRT0): New. + + * configure.host (HOSTING_SCRT0): New. Used for PIE. + + * configure.in (HOSTING_SCRT0): New AC_SUBST. + + * Makefile.in: Regenerated. + * configure: Likewise. + +2013-01-18 Mike Frysinger <vapier@gentoo.org> + + * NEWS: Mention change in behavior with --enable-new-dtags. + * ld.texinfo (Options): Clarify --enable-new-dtags behavior. + +2013-01-14 Leif Ekblad <leif@rdos.net> + Alan Modra <amodra@gmail.com> + + * ld.texinfo (-Tldata-segment): Describe. + * ldlex.h (OPTION_TLDATA_SEGMENT): New enum value. + * lexsup.c (ld_options): Add -Tldata-segment. + (parse_args): Handle OPTION_TLDATA_SEGMENT. + * scripttempl/elf.sc: Support LARGE_DATA_ADDR. + +2013-01-10 H.J. Lu <hongjiu.lu@intel.com> + + * deffilep.y: Remove trailing white spaces. + * elf-hints-local.h: Likewise. + * ldexp.c: Likewise. + * ldlang.h: Likewise. + * ldmisc.c: Likewise. + * ldwrite.c: Likewise. + * pe-dll.c: Likewise. + * emulparams/criself.sh: Likewise. + * emulparams/crislinux.sh: Likewise. + * emulparams/elf32_tic6x_le.sh: Likewise. + * emulparams/elf32bmipn32-defs.sh: Likewise. + * emulparams/elf32mb_linux.sh: Likewise. + * emulparams/elf32mep.sh: Likewise. + * emulparams/elf32microblaze.sh: Likewise. + * emulparams/elf32ppc.sh: Likewise. + * emulparams/elf64_s390.sh: Likewise. + * emulparams/elf64alpha.sh: Likewise. + * emulparams/elf_s390.sh: Likewise. + * emulparams/elf_x86_64.sh: Likewise. + * emulparams/tic80coff.sh: Likewise. + * emultempl/aix.em: Likewise. + * emultempl/avrelf.em: Likewise. + * emultempl/cr16elf.em: Likewise. + * emultempl/pe.em: Likewise. + * emultempl/pep.em: Likewise. + * emultempl/spuelf.em: Likewise. + * emultempl/tic6xdsbt.em: Likewise. + +2013-01-10 Will Newton <will.newton@imgtec.com> + + * Makefile.am: Add Meta. + * Makefile.in: Regenerate. + * configure.tgt: Add Meta. + * emulparams/elf32metag.sh: New file. + * emultempl/metagelf.em: New file. + +2013-01-09 Alan Modra <amodra@gmail.com> + + * emulparams/elf_x86_64.sh (LARGE_BSS_AFTER_BSS): Define. + * emulparams/elf32_x86_64.sh: Likewise. + * emulparams/elf_k1om.sh: Likewise. + * emulparams/elf_l1om.sh: Likewise. + * scripttempl/elf.sc (LARGE_BSS): Define rather than appending to + OTHER_BSS_SECTIONS. Substitute in script. + +2013-01-08 Leif Ekblad <leif@rdos.net> + + * scripttempl/elf.sc (RODATA_ADDR): Typo fix. + +2013-01-08 Alan Modra <amodra@gmail.com> + + * emultempl/elf32.em (gld${EMULATION_NAME}_check_ld_so_conf): Replace + "name" param with a bfd_link_needed_list pointer. Update caller. + (gld${EMULATION_NAME}_check_ld_elf_hints): Likewise. + +2013-01-08 Alan Modra <amodra@gmail.com> + + * Makefile.am (ALL_EMULATION_SOURCES): Correct eavrxmega entries. + * Makefile.in: Regenerate. + +2013-01-07 H.J. Lu <hongjiu.lu@intel.com> + + * lexsup.c (ld_options): Add fuse-ld= for GCC linker option + compatibility. + +2013-01-07 Patrice Dumas <pertusus@free.fr> + + * ld.texinfo: Replace @ with @@ when it is part of the text. + Correct ordering of M68HC11 entry. + +2013-01-04 Juergen Urban <JuergenUrban@gmx.de> + + * configure.tgt: Support ELF files for Sony Playstation 2 (for + ps2dev and ps2sdk). + * emulparams/elf32lr5900n32.sh: Create linker script for Sony + Playstation 2 ELF files using MIPS ABI n32. + * emulparams/elf32lr5900.sh: Create linker script for Sony + Playstation 2 ELF files using MIPS ABI o32. + * Makefile.am: Add linker scripts for Sony Playstation 2 ELF + files. + +2013-01-02 H.J. Lu <hongjiu.lu@intel.com> + + * ldver.c (ldversion): Update copyright year to 2013. + +For older changes see ChangeLog-2012 + +Copyright (C) 2013 Free Software Foundation, Inc. + +Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/ld/ChangeLog.rej b/ld/ChangeLog.rej new file mode 100644 index 0000000..b461c41 --- /dev/null +++ b/ld/ChangeLog.rej @@ -0,0 +1,14 @@ +--- ld/ChangeLog ++++ ld/ChangeLog +@@ -1,3 +1,11 @@ ++2013-11-22 Cory Fields <cory@coryfields.com> ++ ++ * pe-dll.c (fill_edata): Only use a real timestamp if ++ --insert-timestamp was used. ++ * emultempl/pe.em: Add the --insert-timestamp option. ++ * emultempl/pep.em: Likewise for 64bit. ++ * ld.texinfo: Document the --insert-timestamp option. ++ + 2013-11-22 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + * scripttempl/avr.sc: Set .data section's LMA to next available diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 4df7753..5d6da9e 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -130,6 +130,7 @@ static int support_old_code = 0; static char * thumb_entry_symbol = NULL; static lang_assignment_statement_type *image_base_statement = 0; static unsigned short pe_dll_characteristics = 0; +static bfd_boolean insert_timestamp = FALSE; #ifdef DLL_SUPPORT static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */ @@ -239,8 +240,7 @@ fragment <<EOF (OPTION_EXCLUDE_LIBS + 1) #define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC \ (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1) -#define OPTION_LARGE_ADDRESS_AWARE \ - (OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + 1) +#define OPTION_LARGE_ADDRESS_AWARE (OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + 1) #define OPTION_DISABLE_LARGE_ADDRESS_AWARE \ (OPTION_LARGE_ADDRESS_AWARE + 1) #define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 \ @@ -251,15 +251,13 @@ fragment <<EOF (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 + 1) #define OPTION_USE_NUL_PREFIXED_IMPORT_TABLES \ (OPTION_EXCLUDE_MODULES_FOR_IMPLIB + 1) -#define OPTION_NO_LEADING_UNDERSCORE \ - (OPTION_USE_NUL_PREFIXED_IMPORT_TABLES + 1) -#define OPTION_LEADING_UNDERSCORE \ - (OPTION_NO_LEADING_UNDERSCORE + 1) +#define OPTION_NO_LEADING_UNDERSCORE (OPTION_USE_NUL_PREFIXED_IMPORT_TABLES + 1) +#define OPTION_LEADING_UNDERSCORE (OPTION_NO_LEADING_UNDERSCORE + 1) #define OPTION_ENABLE_LONG_SECTION_NAMES \ (OPTION_LEADING_UNDERSCORE + 1) #define OPTION_DISABLE_LONG_SECTION_NAMES \ (OPTION_ENABLE_LONG_SECTION_NAMES + 1) -/* DLLCharacteristics flags */ +/* DLLCharacteristics flags. */ #define OPTION_DYNAMIC_BASE (OPTION_DISABLE_LONG_SECTION_NAMES + 1) #define OPTION_FORCE_INTEGRITY (OPTION_DYNAMIC_BASE + 1) #define OPTION_NX_COMPAT (OPTION_FORCE_INTEGRITY + 1) @@ -268,6 +266,8 @@ fragment <<EOF #define OPTION_NO_BIND (OPTION_NO_SEH + 1) #define OPTION_WDM_DRIVER (OPTION_NO_BIND + 1) #define OPTION_TERMINAL_SERVER_AWARE (OPTION_WDM_DRIVER + 1) +/* Determinism. */ +#define OPTION_INSERT_TIMESTAMP (OPTION_TERMINAL_SERVER_AWARE + 1) static void gld${EMULATION_NAME}_add_options @@ -301,6 +301,7 @@ gld${EMULATION_NAME}_add_options OPTION_USE_NUL_PREFIXED_IMPORT_TABLES}, {"no-leading-underscore", no_argument, NULL, OPTION_NO_LEADING_UNDERSCORE}, {"leading-underscore", no_argument, NULL, OPTION_LEADING_UNDERSCORE}, + {"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP}, #ifdef DLL_SUPPORT /* getopt allows abbreviations, so we do this to stop it from treating -o as an abbreviation for this option. */ @@ -438,6 +439,8 @@ gld_${EMULATION_NAME}_list_options (FILE *file) fprintf (file, _(" --support-old-code Support interworking with old code\n")); fprintf (file, _(" --[no-]leading-underscore Set explicit symbol underscore prefix mode\n")); fprintf (file, _(" --thumb-entry=<symbol> Set the entry point to be Thumb <symbol>\n")); + fprintf (file, _(" --insert-timestamp Use a real timestamp rather than zero.\n")); + fprintf (file, _(" This makes binaries non-deterministic\n")); #ifdef DLL_SUPPORT fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n")); @@ -754,6 +757,9 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_LEADING_UNDERSCORE: pe_leading_underscore = 1; break; + case OPTION_INSERT_TIMESTAMP: + insert_timestamp = TRUE; + break; #ifdef DLL_SUPPORT case OPTION_OUT_DEF: pe_out_def_filename = xstrdup (optarg); @@ -1255,6 +1261,7 @@ gld_${EMULATION_NAME}_after_open (void) pe_data (link_info.output_bfd)->pe_opthdr = pe; pe_data (link_info.output_bfd)->dll = init[DLLOFF].value; pe_data (link_info.output_bfd)->real_flags |= real_flags; + pe_data (link_info.output_bfd)->insert_timestamp = insert_timestamp; /* At this point we must decide whether to use long section names in the output or not. If the user hasn't explicitly specified diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 3e8b65e..b738800 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -18,8 +18,7 @@ esac rm -f e${EMULATION_NAME}.c (echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) fragment <<EOF -/* Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. +/* Copyright 2006-2013 Free Software Foundation, Inc. Written by Kai Tietz, OneVision Software GmbH&CoKg. This file is part of the GNU Binutils. @@ -146,6 +145,7 @@ static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE; static int support_old_code = 0; static lang_assignment_statement_type *image_base_statement = 0; static unsigned short pe_dll_characteristics = 0; +static bfd_boolean insert_timestamp = FALSE; #ifdef DLL_SUPPORT static int pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default). */ @@ -241,6 +241,7 @@ enum options OPTION_NO_SEH, OPTION_NO_BIND, OPTION_WDM_DRIVER, + OPTION_INSERT_TIMESTAMP, OPTION_TERMINAL_SERVER_AWARE }; @@ -316,6 +317,7 @@ gld${EMULATION_NAME}_add_options {"no-bind", no_argument, NULL, OPTION_NO_BIND}, {"wdmdriver", no_argument, NULL, OPTION_WDM_DRIVER}, {"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE}, + {"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP}, {NULL, no_argument, NULL, 0} }; @@ -402,6 +404,8 @@ gld_${EMULATION_NAME}_list_options (FILE *file) fprintf (file, _(" --subsystem <name>[:<version>] Set required OS subsystem [& version]\n")); fprintf (file, _(" --support-old-code Support interworking with old code\n")); fprintf (file, _(" --[no-]leading-underscore Set explicit symbol underscore prefix mode\n")); + fprintf (file, _(" --insert-timestamp Use a real timestamp rather than zero.\n")); + fprintf (file, _(" This makes binaries non-deterministic\n")); #ifdef DLL_SUPPORT fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n")); @@ -707,6 +711,9 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_LEADING_UNDERSCORE: pep_leading_underscore = 1; break; + case OPTION_INSERT_TIMESTAMP: + insert_timestamp = TRUE; + break; #ifdef DLL_SUPPORT case OPTION_OUT_DEF: pep_out_def_filename = xstrdup (optarg); @@ -1219,6 +1226,7 @@ gld_${EMULATION_NAME}_after_open (void) pe_data (link_info.output_bfd)->pe_opthdr = pep; pe_data (link_info.output_bfd)->dll = init[DLLOFF].value; pe_data (link_info.output_bfd)->real_flags |= real_flags; + pe_data (link_info.output_bfd)->insert_timestamp = insert_timestamp; /* At this point we must decide whether to use long section names in the output or not. If the user hasn't explicitly specified diff --git a/ld/ld.texinfo b/ld/ld.texinfo index e4788f6..c925ecb 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -2657,6 +2657,11 @@ The driver uses the MS Windows Driver Model. @item --tsaware The image is Terminal Server aware. +@kindex --insert-timestamp +@item --insert-timestamp +Insert a real timestamp into the image, rather than the default value +of zero. This will result in a slightly different results with each +invocation, which could be helpful for distributing unique images. @end table @c man end diff --git a/ld/pe-dll.c b/ld/pe-dll.c index bd3195f..e9e133b 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -1170,9 +1170,6 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) unsigned char *enameptrs; unsigned char *eordinals; char *enamestr; - time_t now; - - time (&now); edata_d = xmalloc (edata_sz); @@ -1187,7 +1184,10 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) + edata_s->output_section->vma - image_base) memset (edata_d, 0, edata_sz); - bfd_put_32 (abfd, now, edata_d + 4); + + if (pe_data (abfd)->insert_timestamp) + H_PUT_32 (abfd, time (0), edata_d + 4); + if (pe_def_file->version_major != -1) { bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8); diff --git a/ld/pe-dll.c.orig b/ld/pe-dll.c.orig new file mode 100644 index 0000000..bd3195f --- /dev/null +++ b/ld/pe-dll.c.orig @@ -0,0 +1,3452 @@ +/* Routines to help build PEI-format DLLs (Win32 etc) + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Written by DJ Delorie <dj@cygnus.com> + + This file is part of the GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "bfdlink.h" +#include "libiberty.h" +#include "filenames.h" +#include "safe-ctype.h" + +#include <time.h> + +#include "ld.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldwrite.h" +#include "ldmisc.h" +#include <ldgram.h> +#include "ldmain.h" +#include "ldfile.h" +#include "ldemul.h" +#include "coff/internal.h" +#include "../bfd/libcoff.h" +#include "deffile.h" + +#ifdef pe_use_x86_64 + +#define PE_IDATA4_SIZE 8 +#define PE_IDATA5_SIZE 8 +#include "pep-dll.h" +#undef AOUTSZ +#define AOUTSZ PEPAOUTSZ +#define PEAOUTHDR PEPAOUTHDR + +#else + +#include "pe-dll.h" + +#endif + +#ifndef PE_IDATA4_SIZE +#define PE_IDATA4_SIZE 4 +#endif + +#ifndef PE_IDATA5_SIZE +#define PE_IDATA5_SIZE 4 +#endif + +/* This file turns a regular Windows PE image into a DLL. Because of + the complexity of this operation, it has been broken down into a + number of separate modules which are all called by the main function + at the end of this file. This function is not re-entrant and is + normally only called once, so static variables are used to reduce + the number of parameters and return values required. + + See also: ld/emultempl/pe.em and ld/emultempl/pep.em. */ + +/* Auto-import feature by Paul Sokolovsky + + Quick facts: + + 1. With this feature on, DLL clients can import variables from DLL + without any concern from their side (for example, without any source + code modifications). + + 2. This is done completely in bounds of the PE specification (to be fair, + there's a place where it pokes nose out of, but in practice it works). + So, resulting module can be used with any other PE compiler/linker. + + 3. Auto-import is fully compatible with standard import method and they + can be mixed together. + + 4. Overheads: space: 8 bytes per imported symbol, plus 20 for each + reference to it; load time: negligible; virtual/physical memory: should be + less than effect of DLL relocation, and I sincerely hope it doesn't affect + DLL sharability (too much). + + Idea + + The obvious and only way to get rid of dllimport insanity is to make client + access variable directly in the DLL, bypassing extra dereference. I.e., + whenever client contains something like + + mov dll_var,%eax, + + address of dll_var in the command should be relocated to point into loaded + DLL. The aim is to make OS loader do so, and than make ld help with that. + Import section of PE made following way: there's a vector of structures + each describing imports from particular DLL. Each such structure points + to two other parallel vectors: one holding imported names, and one which + will hold address of corresponding imported name. So, the solution is + de-vectorize these structures, making import locations be sparse and + pointing directly into code. Before continuing, it is worth a note that, + while authors strives to make PE act ELF-like, there're some other people + make ELF act PE-like: elfvector, ;-) . + + Implementation + + For each reference of data symbol to be imported from DLL (to set of which + belong symbols with name <sym>, if __imp_<sym> is found in implib), the + import fixup entry is generated. That entry is of type + IMAGE_IMPORT_DESCRIPTOR and stored in .idata$2 subsection. Each + fixup entry contains pointer to symbol's address within .text section + (marked with __fuN_<sym> symbol, where N is integer), pointer to DLL name + (so, DLL name is referenced by multiple entries), and pointer to symbol + name thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>) + pointing to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly + containing imported name. Here comes that "on the edge" problem mentioned + above: PE specification rambles that name vector (OriginalFirstThunk) + should run in parallel with addresses vector (FirstThunk), i.e. that they + should have same number of elements and terminated with zero. We violate + this, since FirstThunk points directly into machine code. But in practice, + OS loader implemented the sane way: it goes thru OriginalFirstThunk and + puts addresses to FirstThunk, not something else. It once again should be + noted that dll and symbol name structures are reused across fixup entries + and should be there anyway to support standard import stuff, so sustained + overhead is 20 bytes per reference. Other question is whether having several + IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, it is + done even by native compiler/linker (libth32's functions are in fact reside + in windows9x kernel32.dll, so if you use it, you have two + IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is whether + referencing the same PE structures several times is valid. The answer is why + not, prohibiting that (detecting violation) would require more work on + behalf of loader than not doing it. + + See also: ld/emultempl/pe.em and ld/emultempl/pep.em. */ + +static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *); + +/* For emultempl/pe.em. */ + +def_file * pe_def_file = 0; +int pe_dll_export_everything = 0; +int pe_dll_exclude_all_symbols = 0; +int pe_dll_do_default_excludes = 1; +int pe_dll_kill_ats = 0; +int pe_dll_stdcall_aliases = 0; +int pe_dll_warn_dup_exports = 0; +int pe_dll_compat_implib = 0; +int pe_dll_extra_pe_debug = 0; +int pe_use_nul_prefixed_import_tables = 0; +int pe_use_coff_long_section_names = -1; +int pe_leading_underscore = -1; + +/* Static variables and types. */ + +static bfd_vma image_base; +static bfd *filler_bfd; +static struct bfd_section *edata_s, *reloc_s; +static unsigned char *edata_d, *reloc_d; +static size_t edata_sz, reloc_sz; +static int runtime_pseudo_relocs_created = 0; +static int runtime_pseudp_reloc_v2_init = 0; + +typedef struct +{ + const char *name; + int len; +} +autofilter_entry_type; + +typedef struct +{ + const char *target_name; + const char *object_target; + unsigned int imagebase_reloc; + int pe_arch; + int bfd_arch; + bfd_boolean underscored; + const autofilter_entry_type* autofilter_symbollist; +} +pe_details_type; + +static const autofilter_entry_type autofilter_symbollist_generic[] = +{ + { STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") }, + /* Entry point symbols. */ + { STRING_COMMA_LEN ("DllMain") }, + { STRING_COMMA_LEN ("DllMainCRTStartup") }, + { STRING_COMMA_LEN ("_DllMainCRTStartup") }, + /* Runtime pseudo-reloc. */ + { STRING_COMMA_LEN ("_pei386_runtime_relocator") }, + { STRING_COMMA_LEN ("do_pseudo_reloc") }, + { NULL, 0 } +}; + +static const autofilter_entry_type autofilter_symbollist_i386[] = +{ + { STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") }, + /* Entry point symbols, and entry hooks. */ + { STRING_COMMA_LEN ("cygwin_crt0") }, +#ifdef pe_use_x86_64 + { STRING_COMMA_LEN ("DllMain") }, + { STRING_COMMA_LEN ("DllEntryPoint") }, + { STRING_COMMA_LEN ("DllMainCRTStartup") }, + { STRING_COMMA_LEN ("_cygwin_dll_entry") }, + { STRING_COMMA_LEN ("_cygwin_crt0_common") }, + { STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry") }, +#else + { STRING_COMMA_LEN ("DllMain@12") }, + { STRING_COMMA_LEN ("DllEntryPoint@0") }, + { STRING_COMMA_LEN ("DllMainCRTStartup@12") }, + { STRING_COMMA_LEN ("_cygwin_dll_entry@12") }, + { STRING_COMMA_LEN ("_cygwin_crt0_common@8") }, + { STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry@12") }, + { STRING_COMMA_LEN ("cygwin_attach_dll") }, +#endif + { STRING_COMMA_LEN ("cygwin_premain0") }, + { STRING_COMMA_LEN ("cygwin_premain1") }, + { STRING_COMMA_LEN ("cygwin_premain2") }, + { STRING_COMMA_LEN ("cygwin_premain3") }, + /* Runtime pseudo-reloc. */ + { STRING_COMMA_LEN ("_pei386_runtime_relocator") }, + { STRING_COMMA_LEN ("do_pseudo_reloc") }, + /* Global vars that should not be exported. */ + { STRING_COMMA_LEN ("impure_ptr") }, + { STRING_COMMA_LEN ("_impure_ptr") }, + { STRING_COMMA_LEN ("_fmode") }, + { STRING_COMMA_LEN ("environ") }, + { NULL, 0 } +}; + +#define PE_ARCH_i386 1 +#define PE_ARCH_sh 2 +#define PE_ARCH_mips 3 +#define PE_ARCH_arm 4 +#define PE_ARCH_arm_epoc 5 +#define PE_ARCH_arm_wince 6 + +/* Don't make it constant as underscore mode gets possibly overriden + by target or -(no-)leading-underscore option. */ +static pe_details_type pe_detail_list[] = +{ + { +#ifdef pe_use_x86_64 + "pei-x86-64", + "pe-x86-64", + 3 /* R_IMAGEBASE */, +#else + "pei-i386", + "pe-i386", + 7 /* R_IMAGEBASE */, +#endif + PE_ARCH_i386, + bfd_arch_i386, +#ifdef pe_use_x86_64 + FALSE, +#else + TRUE, +#endif + autofilter_symbollist_i386 + }, + { + "pei-shl", + "pe-shl", + 16 /* R_SH_IMAGEBASE */, + PE_ARCH_sh, + bfd_arch_sh, + TRUE, + autofilter_symbollist_generic + }, + { + "pei-mips", + "pe-mips", + 34 /* MIPS_R_RVA */, + PE_ARCH_mips, + bfd_arch_mips, + FALSE, + autofilter_symbollist_generic + }, + { + "pei-arm-little", + "pe-arm-little", + 11 /* ARM_RVA32 */, + PE_ARCH_arm, + bfd_arch_arm, + TRUE, + autofilter_symbollist_generic + }, + { + "epoc-pei-arm-little", + "epoc-pe-arm-little", + 11 /* ARM_RVA32 */, + PE_ARCH_arm_epoc, + bfd_arch_arm, + FALSE, + autofilter_symbollist_generic + }, + { + "pei-arm-wince-little", + "pe-arm-wince-little", + 2, /* ARM_RVA32 on Windows CE, see bfd/coff-arm.c. */ + PE_ARCH_arm_wince, + bfd_arch_arm, + FALSE, + autofilter_symbollist_generic + }, + { NULL, NULL, 0, 0, 0, FALSE, NULL } +}; + +static const pe_details_type *pe_details; + +/* Do not specify library suffix explicitly, to allow for dllized versions. */ +static const autofilter_entry_type autofilter_liblist[] = +{ + { STRING_COMMA_LEN ("libcegcc") }, + { STRING_COMMA_LEN ("libcygwin") }, + { STRING_COMMA_LEN ("libgcc") }, + { STRING_COMMA_LEN ("libgcc_s") }, + { STRING_COMMA_LEN ("libstdc++") }, + { STRING_COMMA_LEN ("libmingw32") }, + { STRING_COMMA_LEN ("libmingwex") }, + { STRING_COMMA_LEN ("libg2c") }, + { STRING_COMMA_LEN ("libsupc++") }, + { STRING_COMMA_LEN ("libobjc") }, + { STRING_COMMA_LEN ("libgcj") }, + { NULL, 0 } +}; + +/* Regardless of the suffix issue mentioned above, we must ensure that + we do not falsely match on a leading substring, such as when libtool + builds libstdc++ as a DLL using libsupc++convenience.a as an intermediate. + This routine ensures that the leading part of the name matches and that + it is followed by only an optional version suffix and a file extension, + returning zero if so or -1 if not. */ +static int libnamencmp (const char *libname, const autofilter_entry_type *afptr) +{ + if (filename_ncmp (libname, afptr->name, afptr->len)) + return -1; + + libname += afptr->len; + + /* Be liberal in interpreting what counts as a version suffix; we + accept anything that has a dash to separate it from the name and + begins with a digit. */ + if (libname[0] == '-') + { + if (!ISDIGIT (*++libname)) + return -1; + /* Ensure the filename has an extension. */ + while (*++libname != '.') + if (!*libname) + return -1; + } + else if (libname[0] != '.') + return -1; + + return 0; +} + +static const autofilter_entry_type autofilter_objlist[] = +{ + { STRING_COMMA_LEN ("crt0.o") }, + { STRING_COMMA_LEN ("crt1.o") }, + { STRING_COMMA_LEN ("crt2.o") }, + { STRING_COMMA_LEN ("dllcrt1.o") }, + { STRING_COMMA_LEN ("dllcrt2.o") }, + { STRING_COMMA_LEN ("gcrt0.o") }, + { STRING_COMMA_LEN ("gcrt1.o") }, + { STRING_COMMA_LEN ("gcrt2.o") }, + { STRING_COMMA_LEN ("crtbegin.o") }, + { STRING_COMMA_LEN ("crtend.o") }, + { NULL, 0 } +}; + +static const autofilter_entry_type autofilter_symbolprefixlist[] = +{ + /* _imp_ is treated specially, as it is always underscored. */ + /* { STRING_COMMA_LEN ("_imp_") }, */ + /* Don't export some c++ symbols. */ + { STRING_COMMA_LEN ("__rtti_") }, + { STRING_COMMA_LEN ("__builtin_") }, + /* Don't re-export auto-imported symbols. */ + { STRING_COMMA_LEN ("__nm_") }, + /* Don't export symbols specifying internal DLL layout. */ + { STRING_COMMA_LEN ("_head_") }, + { STRING_COMMA_LEN ("_IMPORT_DESCRIPTOR_") }, + /* Don't export section labels or artificial symbols + (eg ".weak.foo". */ + { STRING_COMMA_LEN (".") }, + { NULL, 0 } +}; + +static const autofilter_entry_type autofilter_symbolsuffixlist[] = +{ + { STRING_COMMA_LEN ("_iname") }, + { STRING_COMMA_LEN ("_NULL_THUNK_DATA") }, + { NULL, 0 } +}; + +#define U(str) (pe_details->underscored ? "_" str : str) + +void +pe_dll_id_target (const char *target) +{ + int i; + + for (i = 0; pe_detail_list[i].target_name; i++) + if (strcmp (pe_detail_list[i].target_name, target) == 0 + || strcmp (pe_detail_list[i].object_target, target) == 0) + { + int u = pe_leading_underscore; /* Underscoring mode. -1 for use default. */ + if (u == -1) + bfd_get_target_info (target, NULL, NULL, &u, NULL); + if (u == -1) + abort (); + pe_detail_list[i].underscored = (u != 0 ? TRUE : FALSE); + pe_details = pe_detail_list + i; + pe_leading_underscore = (u != 0 ? 1 : 0); + return; + } + einfo (_("%XUnsupported PEI architecture: %s\n"), target); + exit (1); +} + +/* Helper functions for qsort. Relocs must be sorted so that we can write + them out by pages. */ + +typedef struct + { + bfd_vma vma; + char type; + short extra; + } +reloc_data_type; + +static int +reloc_sort (const void *va, const void *vb) +{ + bfd_vma a = ((const reloc_data_type *) va)->vma; + bfd_vma b = ((const reloc_data_type *) vb)->vma; + + return (a > b) ? 1 : ((a < b) ? -1 : 0); +} + +static int +pe_export_sort (const void *va, const void *vb) +{ + const def_file_export *a = va; + const def_file_export *b = vb; + char *an = a->name; + char *bn = b->name; + if (a->its_name) + an = a->its_name; + if (b->its_name) + bn = b->its_name; + + return strcmp (an, bn); +} + +/* Read and process the .DEF file. */ + +/* These correspond to the entries in pe_def_file->exports[]. I use + exported_symbol_sections[i] to tag whether or not the symbol was + defined, since we can't export symbols we don't have. */ + +static bfd_vma *exported_symbol_offsets; +static struct bfd_section **exported_symbol_sections; +static int export_table_size; +static int count_exported; +static int count_exported_byname; +static int count_with_ordinals; +static const char *dll_name; +static int min_ordinal, max_ordinal; +static int *exported_symbols; + +typedef struct exclude_list_struct + { + char *string; + struct exclude_list_struct *next; + exclude_type type; + } +exclude_list_struct; + +static struct exclude_list_struct *excludes = 0; + +void +pe_dll_add_excludes (const char *new_excludes, const exclude_type type) +{ + char *local_copy; + char *exclude_string; + + local_copy = xstrdup (new_excludes); + + exclude_string = strtok (local_copy, ",:"); + for (; exclude_string; exclude_string = strtok (NULL, ",:")) + { + struct exclude_list_struct *new_exclude; + + new_exclude = xmalloc (sizeof (struct exclude_list_struct)); + new_exclude->string = xmalloc (strlen (exclude_string) + 1); + strcpy (new_exclude->string, exclude_string); + new_exclude->type = type; + new_exclude->next = excludes; + excludes = new_exclude; + } + + free (local_copy); +} + +static bfd_boolean +is_import (const char* n) +{ + return (CONST_STRNEQ (n, "__imp_")); +} + +/* abfd is a bfd containing n (or NULL) + It can be used for contextual checks. */ + +static int +auto_export (bfd *abfd, def_file *d, const char *n) +{ + def_file_export key; + struct exclude_list_struct *ex; + const autofilter_entry_type *afptr; + const char * libname = NULL; + + if (abfd && abfd->my_archive) + libname = lbasename (abfd->my_archive->filename); + + key.name = key.its_name = (char *) n; + + /* Return false if n is in the d->exports table. */ + if (bsearch (&key, d->exports, d->num_exports, + sizeof (pe_def_file->exports[0]), pe_export_sort)) + return 0; + + if (pe_dll_do_default_excludes) + { + const char * p; + int len; + + if (pe_dll_extra_pe_debug) + printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n", + n, abfd, abfd->my_archive); + + /* First of all, make context checks: + Don't export anything from standard libs. */ + if (libname) + { + afptr = autofilter_liblist; + + while (afptr->name) + { + if (libnamencmp (libname, afptr) == 0 ) + return 0; + afptr++; + } + } + + /* Next, exclude symbols from certain startup objects. */ + + if (abfd && (p = lbasename (abfd->filename))) + { + afptr = autofilter_objlist; + while (afptr->name) + { + if (strcmp (p, afptr->name) == 0) + return 0; + afptr++; + } + } + + /* Don't try to blindly exclude all symbols + that begin with '__'; this was tried and + it is too restrictive. Instead we have + a target specific list to use: */ + afptr = pe_details->autofilter_symbollist; + + while (afptr->name) + { + if (strcmp (n, afptr->name) == 0) + return 0; + + afptr++; + } + + /* Next, exclude symbols starting with ... */ + afptr = autofilter_symbolprefixlist; + while (afptr->name) + { + if (strncmp (n, afptr->name, afptr->len) == 0) + return 0; + + afptr++; + } + + /* Finally, exclude symbols ending with ... */ + len = strlen (n); + afptr = autofilter_symbolsuffixlist; + while (afptr->name) + { + if ((len >= afptr->len) + /* Add 1 to insure match with trailing '\0'. */ + && strncmp (n + len - afptr->len, afptr->name, + afptr->len + 1) == 0) + return 0; + + afptr++; + } + } + + for (ex = excludes; ex; ex = ex->next) + { + if (ex->type == EXCLUDELIBS) + { + if (libname + && ((filename_cmp (libname, ex->string) == 0) + || (strcasecmp ("ALL", ex->string) == 0))) + return 0; + } + else if (ex->type == EXCLUDEFORIMPLIB) + { + if (filename_cmp (abfd->filename, ex->string) == 0) + return 0; + } + else if (strcmp (n, ex->string) == 0) + return 0; + } + + return 1; +} + +static void +process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) +{ + int i, j; + struct bfd_link_hash_entry *blhe; + bfd *b; + struct bfd_section *s; + def_file_export *e = 0; + bfd_boolean resort_needed; + + if (!pe_def_file) + pe_def_file = def_file_empty (); + + /* First, run around to all the objects looking for the .drectve + sections, and push those into the def file too. */ + for (b = info->input_bfds; b; b = b->link_next) + { + s = bfd_get_section_by_name (b, ".drectve"); + if (s) + { + long size = s->size; + char *buf = xmalloc (size); + + bfd_get_section_contents (b, s, buf, 0, size); + def_file_add_directive (pe_def_file, buf, size); + free (buf); + } + } + + /* Process aligned common symbol information from the + .drectve sections now; common symbol allocation is + done before final link, so it will be too late to + process them in process_embedded_commands() called + from _bfd_coff_link_input_bfd(). */ + if (pe_def_file->aligncomms) + { + def_file_aligncomm *ac = pe_def_file->aligncomms; + while (ac) + { + struct coff_link_hash_entry *sym_hash; + sym_hash = coff_link_hash_lookup (coff_hash_table (info), + ac->symbol_name, FALSE, FALSE, FALSE); + if (sym_hash && sym_hash->root.type == bfd_link_hash_common + && sym_hash->root.u.c.p->alignment_power < (unsigned) ac->alignment) + { + sym_hash->root.u.c.p->alignment_power = (unsigned) ac->alignment; + } + ac = ac->next; + } + } + + /* If we are building an executable and there is nothing + to export, we do not build an export table at all. */ + if (info->executable && pe_def_file->num_exports == 0 + && (!pe_dll_export_everything || pe_dll_exclude_all_symbols)) + return; + + /* Now, maybe export everything else the default way. */ + if ((pe_dll_export_everything || pe_def_file->num_exports == 0) + && !pe_dll_exclude_all_symbols) + { + for (b = info->input_bfds; b; b = b->link_next) + { + asymbol **symbols; + int nsyms; + + if (!bfd_generic_link_read_symbols (b)) + { + einfo (_("%B%F: could not read symbols: %E\n"), b); + return; + } + + symbols = bfd_get_outsymbols (b); + nsyms = bfd_get_symcount (b); + + for (j = 0; j < nsyms; j++) + { + /* We should export symbols which are either global or not + anything at all. (.bss data is the latter) + We should not export undefined symbols. */ + bfd_boolean would_export + = (symbols[j]->section != bfd_und_section_ptr + && ((symbols[j]->flags & BSF_GLOBAL) + || (symbols[j]->flags == 0))); + if (link_info.version_info && would_export) + would_export + = !bfd_hide_sym_by_version (link_info.version_info, + symbols[j]->name); + if (would_export) + { + const char *sn = symbols[j]->name; + + /* We should not re-export imported stuff. */ + { + char *name; + if (is_import (sn)) + continue; + + name = xmalloc (strlen ("__imp_") + strlen (sn) + 1); + sprintf (name, "%s%s", "__imp_", sn); + + blhe = bfd_link_hash_lookup (info->hash, name, + FALSE, FALSE, FALSE); + free (name); + + if (blhe && blhe->type == bfd_link_hash_defined) + continue; + } + + if (pe_details->underscored && *sn == '_') + sn++; + + if (auto_export (b, pe_def_file, sn)) + { + int is_dup = 0; + def_file_export *p; + + p = def_file_add_export (pe_def_file, sn, 0, -1, + NULL, &is_dup); + /* Fill data flag properly, from dlltool.c. */ + if (!is_dup) + p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); + } + } + } + } + } + +#undef NE +#define NE pe_def_file->num_exports + + /* Don't create an empty export table. */ + if (NE == 0) + return; + + resort_needed = FALSE; + + /* Canonicalize the export list. */ + if (pe_dll_kill_ats) + { + for (i = 0; i < NE; i++) + { + /* Check for fastcall/stdcall-decoration, but ignore + C++ mangled names. */ + if (pe_def_file->exports[i].name[0] != '?' + && strchr (pe_def_file->exports[i].name, '@')) + { + /* This will preserve internal_name, which may have been + pointing to the same memory as name, or might not + have. */ + int lead_at = (*pe_def_file->exports[i].name == '@'); + char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at); + char *tmp_at = strrchr (tmp, '@'); + + if (tmp_at) + *tmp_at = 0; + else + einfo (_("%XCannot export %s: invalid export name\n"), + pe_def_file->exports[i].name); + pe_def_file->exports[i].name = tmp; + resort_needed = TRUE; + } + } + } + + /* Re-sort the exports table as we have possibly changed the order + by removing leading @. */ + if (resort_needed) + qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]), + pe_export_sort); + + if (pe_dll_stdcall_aliases) + { + for (i = 0; i < NE; i++) + { + if (is_import (pe_def_file->exports[i].name)) + continue; + + if (strchr (pe_def_file->exports[i].name, '@')) + { + int is_dup = 1; + int lead_at = (*pe_def_file->exports[i].name == '@'); + char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at); + + *(strchr (tmp, '@')) = 0; + if (auto_export (NULL, pe_def_file, tmp)) + def_file_add_export (pe_def_file, tmp, + pe_def_file->exports[i].internal_name, + -1, NULL, &is_dup); + if (is_dup) + free (tmp); + } + } + } + + /* Convenience, but watch out for it changing. */ + e = pe_def_file->exports; + + for (i = 0, j = 0; i < NE; i++) + { + if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0) + { + /* This is a duplicate. */ + if (e[j - 1].ordinal != -1 + && e[i].ordinal != -1 + && e[j - 1].ordinal != e[i].ordinal) + { + if (pe_dll_warn_dup_exports) + /* xgettext:c-format */ + einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"), + e[j - 1].name, e[j - 1].ordinal, e[i].ordinal); + } + else + { + if (pe_dll_warn_dup_exports) + /* xgettext:c-format */ + einfo (_("Warning, duplicate EXPORT: %s\n"), + e[j - 1].name); + } + + if (e[i].ordinal != -1) + e[j - 1].ordinal = e[i].ordinal; + e[j - 1].flag_private |= e[i].flag_private; + e[j - 1].flag_constant |= e[i].flag_constant; + e[j - 1].flag_noname |= e[i].flag_noname; + e[j - 1].flag_data |= e[i].flag_data; + if (e[i].name) + free (e[i].name); + if (e[i].internal_name) + free (e[i].internal_name); + if (e[i].its_name) + free (e[i].its_name); + } + else + { + if (i != j) + e[j] = e[i]; + j++; + } + } + pe_def_file->num_exports = j; /* == NE */ + + exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma)); + exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *)); + + memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *)); + max_ordinal = 0; + min_ordinal = 65536; + count_exported = 0; + count_exported_byname = 0; + count_with_ordinals = 0; + + for (i = 0; i < NE; i++) + { + char *name; + name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); + if (pe_details->underscored + && (*pe_def_file->exports[i].internal_name != '@')) + { + *name = '_'; + strcpy (name + 1, pe_def_file->exports[i].internal_name); + } + else + strcpy (name, pe_def_file->exports[i].internal_name); + + blhe = bfd_link_hash_lookup (info->hash, + name, + FALSE, FALSE, TRUE); + + if (blhe + && (blhe->type == bfd_link_hash_defined + || (blhe->type == bfd_link_hash_common))) + { + count_exported++; + if (!pe_def_file->exports[i].flag_noname) + count_exported_byname++; + + /* Only fill in the sections. The actual offsets are computed + in fill_exported_offsets() after common symbols are laid + out. */ + if (blhe->type == bfd_link_hash_defined) + exported_symbol_sections[i] = blhe->u.def.section; + else + exported_symbol_sections[i] = blhe->u.c.p->section; + + if (pe_def_file->exports[i].ordinal != -1) + { + if (max_ordinal < pe_def_file->exports[i].ordinal) + max_ordinal = pe_def_file->exports[i].ordinal; + if (min_ordinal > pe_def_file->exports[i].ordinal) + min_ordinal = pe_def_file->exports[i].ordinal; + count_with_ordinals++; + } + } + /* Check for forward exports. These are indicated in DEF files by an + export directive of the form NAME1 = MODULE-NAME.EXTERNAL-NAME + but we must take care not to be fooled when the user wants to export + a symbol that actually really has a dot in it, so we only check + for them here, after real defined symbols have already been matched. */ + else if (strchr (pe_def_file->exports[i].internal_name, '.')) + { + count_exported++; + if (!pe_def_file->exports[i].flag_noname) + count_exported_byname++; + + pe_def_file->exports[i].flag_forward = 1; + + if (pe_def_file->exports[i].ordinal != -1) + { + if (max_ordinal < pe_def_file->exports[i].ordinal) + max_ordinal = pe_def_file->exports[i].ordinal; + if (min_ordinal > pe_def_file->exports[i].ordinal) + min_ordinal = pe_def_file->exports[i].ordinal; + count_with_ordinals++; + } + } + else if (blhe && blhe->type == bfd_link_hash_undefined) + { + /* xgettext:c-format */ + einfo (_("%XCannot export %s: symbol not defined\n"), + pe_def_file->exports[i].internal_name); + } + else if (blhe) + { + /* xgettext:c-format */ + einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"), + pe_def_file->exports[i].internal_name, + blhe->type, bfd_link_hash_defined); + } + else + { + /* xgettext:c-format */ + einfo (_("%XCannot export %s: symbol not found\n"), + pe_def_file->exports[i].internal_name); + } + free (name); + } +} + +/* Build the bfd that will contain .edata and .reloc sections. */ + +static void +build_filler_bfd (int include_edata) +{ + lang_input_statement_type *filler_file; + filler_file = lang_add_input_file ("dll stuff", + lang_input_file_is_fake_enum, + NULL); + filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", + link_info.output_bfd); + if (filler_bfd == NULL + || !bfd_set_arch_mach (filler_bfd, + bfd_get_arch (link_info.output_bfd), + bfd_get_mach (link_info.output_bfd))) + { + einfo ("%X%P: can not create BFD: %E\n"); + return; + } + + if (include_edata) + { + edata_s = bfd_make_section_old_way (filler_bfd, ".edata"); + if (edata_s == NULL + || !bfd_set_section_flags (filler_bfd, edata_s, + (SEC_HAS_CONTENTS + | SEC_ALLOC + | SEC_LOAD + | SEC_KEEP + | SEC_IN_MEMORY))) + { + einfo ("%X%P: can not create .edata section: %E\n"); + return; + } + bfd_set_section_size (filler_bfd, edata_s, edata_sz); + } + + reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc"); + if (reloc_s == NULL + || !bfd_set_section_flags (filler_bfd, reloc_s, + (SEC_HAS_CONTENTS + | SEC_ALLOC + | SEC_LOAD + | SEC_KEEP + | SEC_IN_MEMORY))) + { + einfo ("%X%P: can not create .reloc section: %E\n"); + return; + } + + bfd_set_section_size (filler_bfd, reloc_s, 0); + + ldlang_add_file (filler_file); +} + +/* Gather all the exported symbols and build the .edata section. */ + +static void +generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + int i, next_ordinal; + int name_table_size = 0; + const char *dlnp; + + /* First, we need to know how many exported symbols there are, + and what the range of ordinals is. */ + if (pe_def_file->name) + dll_name = pe_def_file->name; + else + { + dll_name = abfd->filename; + + for (dlnp = dll_name; *dlnp; dlnp++) + if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':') + dll_name = dlnp + 1; + } + + if (count_with_ordinals && max_ordinal > count_exported) + { + if (min_ordinal > max_ordinal - count_exported + 1) + min_ordinal = max_ordinal - count_exported + 1; + } + else + { + min_ordinal = 1; + max_ordinal = count_exported; + } + + export_table_size = max_ordinal - min_ordinal + 1; + exported_symbols = xmalloc (export_table_size * sizeof (int)); + for (i = 0; i < export_table_size; i++) + exported_symbols[i] = -1; + + /* Now we need to assign ordinals to those that don't have them. */ + for (i = 0; i < NE; i++) + { + if (exported_symbol_sections[i] || + pe_def_file->exports[i].flag_forward) + { + if (pe_def_file->exports[i].ordinal != -1) + { + int ei = pe_def_file->exports[i].ordinal - min_ordinal; + int pi = exported_symbols[ei]; + + if (pi != -1) + { + /* xgettext:c-format */ + einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"), + pe_def_file->exports[i].ordinal, + pe_def_file->exports[i].name, + pe_def_file->exports[pi].name); + } + exported_symbols[ei] = i; + } + if (pe_def_file->exports[i].its_name) + name_table_size += strlen (pe_def_file->exports[i].its_name) + 1; + else + name_table_size += strlen (pe_def_file->exports[i].name) + 1; + } + + /* Reserve space for the forward name. */ + if (pe_def_file->exports[i].flag_forward) + { + name_table_size += strlen (pe_def_file->exports[i].internal_name) + 1; + } + } + + next_ordinal = min_ordinal; + for (i = 0; i < NE; i++) + if ((exported_symbol_sections[i] || + pe_def_file->exports[i].flag_forward) && + pe_def_file->exports[i].ordinal == -1) + { + while (exported_symbols[next_ordinal - min_ordinal] != -1) + next_ordinal++; + + exported_symbols[next_ordinal - min_ordinal] = i; + pe_def_file->exports[i].ordinal = next_ordinal; + } + + /* OK, now we can allocate some memory. */ + edata_sz = (40 /* directory */ + + 4 * export_table_size /* addresses */ + + 4 * count_exported_byname /* name ptrs */ + + 2 * count_exported_byname /* ordinals */ + + name_table_size + strlen (dll_name) + 1); +} + +/* Fill the exported symbol offsets. The preliminary work has already + been done in process_def_file_and_drectve(). */ + +static void +fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) +{ + int i; + struct bfd_link_hash_entry *blhe; + + for (i = 0; i < pe_def_file->num_exports; i++) + { + char *name; + + name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); + if (pe_details->underscored + && *pe_def_file->exports[i].internal_name != '@') + { + *name = '_'; + strcpy (name + 1, pe_def_file->exports[i].internal_name); + } + else + strcpy (name, pe_def_file->exports[i].internal_name); + + blhe = bfd_link_hash_lookup (info->hash, + name, + FALSE, FALSE, TRUE); + + if (blhe && blhe->type == bfd_link_hash_defined) + exported_symbol_offsets[i] = blhe->u.def.value; + + free (name); + } +} + +static void +fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + int s, hint; + unsigned char *edirectory; + unsigned char *eaddresses; + unsigned char *enameptrs; + unsigned char *eordinals; + char *enamestr; + time_t now; + + time (&now); + + edata_d = xmalloc (edata_sz); + + /* Note use of array pointer math here. */ + edirectory = edata_d; + eaddresses = edirectory + 40; + enameptrs = eaddresses + 4 * export_table_size; + eordinals = enameptrs + 4 * count_exported_byname; + enamestr = (char *) eordinals + 2 * count_exported_byname; + +#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \ + + edata_s->output_section->vma - image_base) + + memset (edata_d, 0, edata_sz); + bfd_put_32 (abfd, now, edata_d + 4); + if (pe_def_file->version_major != -1) + { + bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8); + bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10); + } + + bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12); + strcpy (enamestr, dll_name); + enamestr += strlen (enamestr) + 1; + bfd_put_32 (abfd, min_ordinal, edata_d + 16); + bfd_put_32 (abfd, export_table_size, edata_d + 20); + bfd_put_32 (abfd, count_exported_byname, edata_d + 24); + bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28); + bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32); + bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36); + + fill_exported_offsets (abfd, info); + + /* Ok, now for the filling in part. + Scan alphabetically - ie the ordering in the exports[] table, + rather than by ordinal - the ordering in the exported_symbol[] + table. See dlltool.c and: + http://sources.redhat.com/ml/binutils/2003-04/msg00379.html + for more information. */ + hint = 0; + for (s = 0; s < NE; s++) + { + struct bfd_section *ssec = exported_symbol_sections[s]; + if (pe_def_file->exports[s].ordinal != -1 && + (pe_def_file->exports[s].flag_forward || ssec != NULL)) + { + int ord = pe_def_file->exports[s].ordinal; + + if (pe_def_file->exports[s].flag_forward) + { + bfd_put_32 (abfd, ERVA (enamestr), + eaddresses + 4 * (ord - min_ordinal)); + + strcpy (enamestr, pe_def_file->exports[s].internal_name); + enamestr += strlen (pe_def_file->exports[s].internal_name) + 1; + } + else + { + bfd_vma srva = (exported_symbol_offsets[s] + + ssec->output_section->vma + + ssec->output_offset); + + bfd_put_32 (abfd, srva - image_base, + eaddresses + 4 * (ord - min_ordinal)); + } + + if (!pe_def_file->exports[s].flag_noname) + { + char *ename = pe_def_file->exports[s].name; + if (pe_def_file->exports[s].its_name) + ename = pe_def_file->exports[s].its_name; + + bfd_put_32 (abfd, ERVA (enamestr), enameptrs); + enameptrs += 4; + strcpy (enamestr, ename); + enamestr += strlen (enamestr) + 1; + bfd_put_16 (abfd, ord - min_ordinal, eordinals); + eordinals += 2; + pe_def_file->exports[s].hint = hint++; + } + } + } +} + + +static struct bfd_section *current_sec; + +void +pe_walk_relocs_of_symbol (struct bfd_link_info *info, + const char *name, + int (*cb) (arelent *, asection *)) +{ + bfd *b; + asection *s; + + for (b = info->input_bfds; b; b = b->link_next) + { + asymbol **symbols; + + if (!bfd_generic_link_read_symbols (b)) + { + einfo (_("%B%F: could not read symbols: %E\n"), b); + return; + } + + symbols = bfd_get_outsymbols (b); + + for (s = b->sections; s; s = s->next) + { + arelent **relocs; + int relsize, nrelocs, i; + int flags = bfd_get_section_flags (b, s); + + /* Skip discarded linkonce sections. */ + if (flags & SEC_LINK_ONCE + && s->output_section == bfd_abs_section_ptr) + continue; + + current_sec = s; + + relsize = bfd_get_reloc_upper_bound (b, s); + relocs = xmalloc (relsize); + nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); + + for (i = 0; i < nrelocs; i++) + { + struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr; + + if (!strcmp (name, sym->name)) + cb (relocs[i], s); + } + + free (relocs); + + /* Warning: the allocated symbols are remembered in BFD and reused + later, so don't free them! */ + /* free (symbols); */ + } + } +} + +/* Gather all the relocations and build the .reloc section. */ + +static void +generate_reloc (bfd *abfd, struct bfd_link_info *info) +{ + + /* For .reloc stuff. */ + reloc_data_type *reloc_data; + int total_relocs = 0; + int i; + bfd_vma sec_page = (bfd_vma) -1; + bfd_vma page_ptr, page_count; + int bi; + bfd *b; + struct bfd_section *s; + + total_relocs = 0; + for (b = info->input_bfds; b; b = b->link_next) + for (s = b->sections; s; s = s->next) + total_relocs += s->reloc_count; + + reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type)); + + total_relocs = 0; + bi = 0; + for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next) + { + arelent **relocs; + int relsize, nrelocs; + + for (s = b->sections; s; s = s->next) + { + bfd_vma sec_vma = s->output_section->vma + s->output_offset; + asymbol **symbols; + + /* If it's not loaded, we don't need to relocate it this way. */ + if (!(s->output_section->flags & SEC_LOAD)) + continue; + + /* I don't know why there would be a reloc for these, but I've + seen it happen - DJ */ + if (s->output_section == bfd_abs_section_ptr) + continue; + + if (s->output_section->vma == 0) + { + /* Huh? Shouldn't happen, but punt if it does. */ + einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n", + s->output_section->name, s->output_section->index, + s->output_section->flags); + continue; + } + + if (!bfd_generic_link_read_symbols (b)) + { + einfo (_("%B%F: could not read symbols: %E\n"), b); + return; + } + + symbols = bfd_get_outsymbols (b); + relsize = bfd_get_reloc_upper_bound (b, s); + relocs = xmalloc (relsize); + nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); + + for (i = 0; i < nrelocs; i++) + { + if (pe_dll_extra_pe_debug) + { + struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr; + printf ("rel: %s\n", sym->name); + } + if (!relocs[i]->howto->pc_relative + && relocs[i]->howto->type != pe_details->imagebase_reloc) + { + struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr; + + /* Don't create relocs for undefined weak symbols. */ + if (sym->flags == BSF_WEAK) + { + struct bfd_link_hash_entry *blhe + = bfd_wrapped_link_hash_lookup (abfd, info, sym->name, + FALSE, FALSE, FALSE); + if (blhe && blhe->type == bfd_link_hash_undefweak) + { + /* Check aux sym and see if it is defined or not. */ + struct coff_link_hash_entry *h, *h2; + h = (struct coff_link_hash_entry *)blhe; + if (h->symbol_class != C_NT_WEAK || h->numaux != 1) + continue; + h2 = h->auxbfd->tdata.coff_obj_data->sym_hashes + [h->aux->x_sym.x_tagndx.l]; + /* We don't want a base reloc if the aux sym is not + found, undefined, or if it is the constant ABS + zero default value. (We broaden that slightly by + not testing the value, just the section; there's + no reason we'd want a reference to any absolute + address to get relocated during rebasing). */ + if (!h2 || h2->root.type == bfd_link_hash_undefined + || h2->root.u.def.section == bfd_abs_section_ptr) + continue; + } + else if (!blhe || blhe->type != bfd_link_hash_defined) + continue; + } + /* Nor for Dwarf FDE references to discarded sections. */ + else if (bfd_is_abs_section (sym->section->output_section)) + { + /* We only ignore relocs from .eh_frame sections, as + they are discarded by the final link rather than + resolved against the kept section. */ + if (!strcmp (s->name, ".eh_frame")) + continue; + } + + reloc_data[total_relocs].vma = sec_vma + relocs[i]->address; + +#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift) + + switch BITS_AND_SHIFT (relocs[i]->howto->bitsize, + relocs[i]->howto->rightshift) + { +#ifdef pe_use_x86_64 + case BITS_AND_SHIFT (64, 0): + reloc_data[total_relocs].type = 10; + total_relocs++; + break; +#endif + case BITS_AND_SHIFT (32, 0): + reloc_data[total_relocs].type = 3; + total_relocs++; + break; + case BITS_AND_SHIFT (16, 0): + reloc_data[total_relocs].type = 2; + total_relocs++; + break; + case BITS_AND_SHIFT (16, 16): + reloc_data[total_relocs].type = 4; + /* FIXME: we can't know the symbol's right value + yet, but we probably can safely assume that + CE will relocate us in 64k blocks, so leaving + it zero is safe. */ + reloc_data[total_relocs].extra = 0; + total_relocs++; + break; + case BITS_AND_SHIFT (26, 2): + reloc_data[total_relocs].type = 5; + total_relocs++; + break; + case BITS_AND_SHIFT (24, 2): + /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c + Those ARM_xxx definitions should go in proper + header someday. */ + if (relocs[i]->howto->type == 0 + /* Older GNU linkers used 5 instead of 0 for this reloc. */ + || relocs[i]->howto->type == 5) + /* This is an ARM_26D reloc, which is an ARM_26 reloc + that has already been fully processed during a + previous link stage, so ignore it here. */ + break; + /* Fall through. */ + default: + /* xgettext:c-format */ + einfo (_("%XError: %d-bit reloc in dll\n"), + relocs[i]->howto->bitsize); + break; + } + } + } + free (relocs); + /* Warning: the allocated symbols are remembered in BFD and + reused later, so don't free them! */ + } + } + + /* At this point, we have total_relocs relocation addresses in + reloc_addresses, which are all suitable for the .reloc section. + We must now create the new sections. */ + qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort); + + for (i = 0; i < total_relocs; i++) + { + bfd_vma this_page = (reloc_data[i].vma >> 12); + + if (this_page != sec_page) + { + reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ + reloc_sz += 8; + sec_page = this_page; + } + + reloc_sz += 2; + + if (reloc_data[i].type == 4) + reloc_sz += 2; + } + + reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ + reloc_d = xmalloc (reloc_sz); + sec_page = (bfd_vma) -1; + reloc_sz = 0; + page_ptr = (bfd_vma) -1; + page_count = 0; + + for (i = 0; i < total_relocs; i++) + { + bfd_vma rva = reloc_data[i].vma - image_base; + bfd_vma this_page = (rva & ~0xfff); + + if (this_page != sec_page) + { + while (reloc_sz & 3) + reloc_d[reloc_sz++] = 0; + + if (page_ptr != (bfd_vma) -1) + bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); + + bfd_put_32 (abfd, this_page, reloc_d + reloc_sz); + page_ptr = reloc_sz; + reloc_sz += 8; + sec_page = this_page; + page_count = 0; + } + + bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12), + reloc_d + reloc_sz); + reloc_sz += 2; + + if (reloc_data[i].type == 4) + { + bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz); + reloc_sz += 2; + } + + page_count++; + } + + while (reloc_sz & 3) + reloc_d[reloc_sz++] = 0; + + if (page_ptr != (bfd_vma) -1) + bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); + + while (reloc_sz < reloc_s->size) + reloc_d[reloc_sz++] = 0; +} + +/* Given the exiting def_file structure, print out a .DEF file that + corresponds to it. */ + +static void +quoteput (char *s, FILE *f, int needs_quotes) +{ + char *cp; + + for (cp = s; *cp; cp++) + if (*cp == '\'' + || *cp == '"' + || *cp == '\\' + || ISSPACE (*cp) + || *cp == ',' + || *cp == ';') + needs_quotes = 1; + + if (needs_quotes) + { + putc ('"', f); + + while (*s) + { + if (*s == '"' || *s == '\\') + putc ('\\', f); + + putc (*s, f); + s++; + } + + putc ('"', f); + } + else + fputs (s, f); +} + +void +pe_dll_generate_def_file (const char *pe_out_def_filename) +{ + int i; + FILE *out = fopen (pe_out_def_filename, "w"); + + if (out == NULL) + /* xgettext:c-format */ + einfo (_("%s: Can't open output def file %s\n"), + program_name, pe_out_def_filename); + + if (pe_def_file) + { + if (pe_def_file->name) + { + if (pe_def_file->is_dll) + fprintf (out, "LIBRARY "); + else + fprintf (out, "NAME "); + + quoteput (pe_def_file->name, out, 1); + + if (pe_data (link_info.output_bfd)->pe_opthdr.ImageBase) + { + fprintf (out, " BASE=0x"); + fprintf_vma (out, ((bfd_vma) pe_data (link_info.output_bfd)->pe_opthdr.ImageBase)); + } + fprintf (out, "\n"); + } + + if (pe_def_file->description) + { + fprintf (out, "DESCRIPTION "); + quoteput (pe_def_file->description, out, 1); + fprintf (out, "\n"); + } + + if (pe_def_file->version_minor != -1) + fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major, + pe_def_file->version_minor); + else if (pe_def_file->version_major != -1) + fprintf (out, "VERSION %d\n", pe_def_file->version_major); + + if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1) + fprintf (out, "\n"); + + if (pe_def_file->stack_commit != -1) + fprintf (out, "STACKSIZE 0x%x,0x%x\n", + pe_def_file->stack_reserve, pe_def_file->stack_commit); + else if (pe_def_file->stack_reserve != -1) + fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve); + + if (pe_def_file->heap_commit != -1) + fprintf (out, "HEAPSIZE 0x%x,0x%x\n", + pe_def_file->heap_reserve, pe_def_file->heap_commit); + else if (pe_def_file->heap_reserve != -1) + fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve); + + if (pe_def_file->num_section_defs > 0) + { + fprintf (out, "\nSECTIONS\n\n"); + + for (i = 0; i < pe_def_file->num_section_defs; i++) + { + fprintf (out, " "); + quoteput (pe_def_file->section_defs[i].name, out, 0); + + if (pe_def_file->section_defs[i].class) + { + fprintf (out, " CLASS "); + quoteput (pe_def_file->section_defs[i].class, out, 0); + } + + if (pe_def_file->section_defs[i].flag_read) + fprintf (out, " READ"); + + if (pe_def_file->section_defs[i].flag_write) + fprintf (out, " WRITE"); + + if (pe_def_file->section_defs[i].flag_execute) + fprintf (out, " EXECUTE"); + + if (pe_def_file->section_defs[i].flag_shared) + fprintf (out, " SHARED"); + + fprintf (out, "\n"); + } + } + + if (pe_def_file->num_exports > 0) + { + fprintf (out, "EXPORTS\n"); + + for (i = 0; i < pe_def_file->num_exports; i++) + { + def_file_export *e = pe_def_file->exports + i; + fprintf (out, " "); + quoteput (e->name, out, 0); + + if (e->internal_name && strcmp (e->internal_name, e->name)) + { + fprintf (out, " = "); + quoteput (e->internal_name, out, 0); + } + + if (e->ordinal != -1) + fprintf (out, " @%d", e->ordinal); + + if (e->flag_private) + fprintf (out, " PRIVATE"); + + if (e->flag_constant) + fprintf (out, " CONSTANT"); + + if (e->flag_noname) + fprintf (out, " NONAME"); + + if (e->flag_data) + fprintf (out, " DATA"); + + fprintf (out, "\n"); + } + } + + if (pe_def_file->num_imports > 0) + { + fprintf (out, "\nIMPORTS\n\n"); + + for (i = 0; i < pe_def_file->num_imports; i++) + { + def_file_import *im = pe_def_file->imports + i; + fprintf (out, " "); + + if (im->internal_name + && (!im->name || strcmp (im->internal_name, im->name))) + { + quoteput (im->internal_name, out, 0); + fprintf (out, " = "); + } + + quoteput (im->module->name, out, 0); + fprintf (out, "."); + + if (im->name) + quoteput (im->name, out, 0); + else + fprintf (out, "%d", im->ordinal); + + if (im->its_name) + { + fprintf (out, " == "); + quoteput (im->its_name, out, 0); + } + + fprintf (out, "\n"); + } + } + } + else + fprintf (out, _("; no contents available\n")); + + if (fclose (out) == EOF) + /* xgettext:c-format */ + einfo (_("%P: Error closing file `%s'\n"), pe_out_def_filename); +} + +/* Generate the import library. */ + +static asymbol **symtab; +static int symptr; +static int tmp_seq; +static int tmp_seq2; +static const char *dll_filename; +static char *dll_symname; + +#define UNDSEC bfd_und_section_ptr + +static asection * +quick_section (bfd *abfd, const char *name, int flags, int align) +{ + asection *sec; + asymbol *sym; + + sec = bfd_make_section_old_way (abfd, name); + bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP); + bfd_set_section_alignment (abfd, sec, align); + /* Remember to undo this before trying to link internally! */ + sec->output_section = sec; + + sym = bfd_make_empty_symbol (abfd); + symtab[symptr++] = sym; + sym->name = sec->name; + sym->section = sec; + sym->flags = BSF_LOCAL; + sym->value = 0; + + return sec; +} + +static void +quick_symbol (bfd *abfd, + const char *n1, + const char *n2, + const char *n3, + asection *sec, + int flags, + int addr) +{ + asymbol *sym; + char *name = xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1); + + strcpy (name, n1); + strcat (name, n2); + strcat (name, n3); + sym = bfd_make_empty_symbol (abfd); + sym->name = name; + sym->section = sec; + sym->flags = flags; + sym->value = addr; + symtab[symptr++] = sym; +} + +static arelent *reltab = 0; +static int relcount = 0, relsize = 0; + +static void +quick_reloc (bfd *abfd, bfd_size_type address, int which_howto, int symidx) +{ + if (relcount >= relsize - 1) + { + relsize += 10; + if (reltab) + reltab = xrealloc (reltab, relsize * sizeof (arelent)); + else + reltab = xmalloc (relsize * sizeof (arelent)); + } + reltab[relcount].address = address; + reltab[relcount].addend = 0; + reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto); + reltab[relcount].sym_ptr_ptr = symtab + symidx; + relcount++; +} + +static void +save_relocs (asection *sec) +{ + int i; + + sec->relocation = reltab; + sec->reloc_count = relcount; + sec->orelocation = xmalloc ((relcount + 1) * sizeof (arelent *)); + for (i = 0; i < relcount; i++) + sec->orelocation[i] = sec->relocation + i; + sec->orelocation[relcount] = 0; + sec->flags |= SEC_RELOC; + reltab = 0; + relcount = relsize = 0; +} + +/* .section .idata$2 + .global __head_my_dll + __head_my_dll: + .rva hname + .long 0 + .long 0 + .rva __my_dll_iname + .rva fthunk + + .section .idata$5 + .long 0 + fthunk: + + .section .idata$4 + .long 0 + hname: */ + +static bfd * +make_head (bfd *parent) +{ + asection *id2, *id5, *id4; + unsigned char *d2, *d5, *d4; + char *oname; + bfd *abfd; + + oname = xmalloc (20); + sprintf (oname, "d%06d.o", tmp_seq); + tmp_seq++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (6 * sizeof (asymbol *)); + id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2); + id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); + id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); + quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0); + quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0); + + /* OK, pay attention here. I got confused myself looking back at + it. We create a four-byte section to mark the beginning of the + list, and we include an offset of 4 in the section, so that the + pointer to the list points to the *end* of this section, which is + the start of the list of sections from other objects. */ + + bfd_set_section_size (abfd, id2, 20); + d2 = xmalloc (20); + id2->contents = d2; + memset (d2, 0, 20); + if (pe_use_nul_prefixed_import_tables) + d2[0] = d2[16] = PE_IDATA5_SIZE; /* Reloc addend. */ + quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); + quick_reloc (abfd, 12, BFD_RELOC_RVA, 4); + quick_reloc (abfd, 16, BFD_RELOC_RVA, 1); + save_relocs (id2); + + if (pe_use_nul_prefixed_import_tables) + bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE); + else + bfd_set_section_size (abfd, id5, 0); + d5 = xmalloc (PE_IDATA5_SIZE); + id5->contents = d5; + memset (d5, 0, PE_IDATA5_SIZE); + if (pe_use_nul_prefixed_import_tables) + bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE); + else + bfd_set_section_size (abfd, id4, 0); + d4 = xmalloc (PE_IDATA4_SIZE); + id4->contents = d4; + memset (d4, 0, PE_IDATA4_SIZE); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, id2, d2, 0, 20); + if (pe_use_nul_prefixed_import_tables) + { + bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE); + bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE); + } + else + { + bfd_set_section_contents (abfd, id5, d5, 0, 0); + bfd_set_section_contents (abfd, id4, d4, 0, 0); + } + + bfd_make_readable (abfd); + return abfd; +} + +/* .section .idata$4 + .long 0 + [.long 0] for PE+ + .section .idata$5 + .long 0 + [.long 0] for PE+ + .section idata$7 + .global __my_dll_iname + __my_dll_iname: + .asciz "my.dll" */ + +static bfd * +make_tail (bfd *parent) +{ + asection *id4, *id5, *id7; + unsigned char *d4, *d5, *d7; + int len; + char *oname; + bfd *abfd; + + oname = xmalloc (20); + sprintf (oname, "d%06d.o", tmp_seq); + tmp_seq++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (5 * sizeof (asymbol *)); + id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); + id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); + id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); + quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0); + + bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE); + d4 = xmalloc (PE_IDATA4_SIZE); + id4->contents = d4; + memset (d4, 0, PE_IDATA4_SIZE); + + bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE); + d5 = xmalloc (PE_IDATA5_SIZE); + id5->contents = d5; + memset (d5, 0, PE_IDATA5_SIZE); + + len = strlen (dll_filename) + 1; + if (len & 1) + len++; + bfd_set_section_size (abfd, id7, len); + d7 = xmalloc (len); + id7->contents = d7; + strcpy ((char *) d7, dll_filename); + /* If len was odd, the above + strcpy leaves behind an undefined byte. That is harmless, + but we set it to 0 just so the binary dumps are pretty. */ + d7[len - 1] = 0; + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE); + bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE); + bfd_set_section_contents (abfd, id7, d7, 0, len); + + bfd_make_readable (abfd); + return abfd; +} + +/* .text + .global _function + .global ___imp_function + .global __imp__function + _function: + jmp *__imp__function: + + .section idata$7 + .long __head_my_dll + + .section .idata$5 + ___imp_function: + __imp__function: + iat? + .section .idata$4 + iat? + .section .idata$6 + ID<ordinal>: + .short <hint> + .asciz "function" xlate? (add underscore, kill at) */ + +static const unsigned char jmp_ix86_bytes[] = +{ + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 +}; + +/* _function: + mov.l ip+8,r0 + mov.l @r0,r0 + jmp @r0 + nop + .dw __imp_function */ + +static const unsigned char jmp_sh_bytes[] = +{ + 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* _function: + lui $t0,<high:__imp_function> + lw $t0,<low:__imp_function> + jr $t0 + nop */ + +static const unsigned char jmp_mips_bytes[] = +{ + 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d, + 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char jmp_arm_bytes[] = +{ + 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */ + 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */ + 0, 0, 0, 0 +}; + + +static bfd * +make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub) +{ + asection *tx, *id7, *id5, *id4, *id6; + unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL; + int len; + char *oname; + bfd *abfd; + const unsigned char *jmp_bytes = NULL; + int jmp_byte_count = 0; + + /* Include the jump stub section only if it is needed. A jump + stub is needed if the symbol being imported <sym> is a function + symbol and there is at least one undefined reference to that + symbol. In other words, if all the import references to <sym> are + explicitly through _declspec(dllimport) then the jump stub is not + needed. */ + if (include_jmp_stub) + { + switch (pe_details->pe_arch) + { + case PE_ARCH_i386: + jmp_bytes = jmp_ix86_bytes; + jmp_byte_count = sizeof (jmp_ix86_bytes); + break; + case PE_ARCH_sh: + jmp_bytes = jmp_sh_bytes; + jmp_byte_count = sizeof (jmp_sh_bytes); + break; + case PE_ARCH_mips: + jmp_bytes = jmp_mips_bytes; + jmp_byte_count = sizeof (jmp_mips_bytes); + break; + case PE_ARCH_arm: + case PE_ARCH_arm_epoc: + case PE_ARCH_arm_wince: + jmp_bytes = jmp_arm_bytes; + jmp_byte_count = sizeof (jmp_arm_bytes); + break; + default: + abort (); + } + } + + oname = xmalloc (20); + sprintf (oname, "d%06d.o", tmp_seq); + tmp_seq++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (12 * sizeof (asymbol *)); + + tx = quick_section (abfd, ".text", SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY, 2); + id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); + id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); + id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); + id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2); + + if (*exp->internal_name == '@') + { + quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, + BSF_GLOBAL, 0); + if (include_jmp_stub) + quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0); + quick_symbol (abfd, "__imp_", exp->internal_name, "", id5, + BSF_GLOBAL, 0); + /* Fastcall applies only to functions, + so no need for auto-import symbol. */ + } + else + { + quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, + BSF_GLOBAL, 0); + if (include_jmp_stub) + quick_symbol (abfd, U (""), exp->internal_name, "", tx, + BSF_GLOBAL, 0); + quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5, + BSF_GLOBAL, 0); + /* Symbol to reference ord/name of imported + data symbol, used to implement auto-import. */ + if (exp->flag_data) + quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6, + BSF_GLOBAL,0); + } + if (pe_dll_compat_implib) + quick_symbol (abfd, "___imp_", exp->internal_name, "", id5, + BSF_GLOBAL, 0); + + if (include_jmp_stub) + { + bfd_set_section_size (abfd, tx, jmp_byte_count); + td = xmalloc (jmp_byte_count); + tx->contents = td; + memcpy (td, jmp_bytes, jmp_byte_count); + + switch (pe_details->pe_arch) + { + case PE_ARCH_i386: +#ifdef pe_use_x86_64 + quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2); +#else + /* Mark this object as SAFESEH compatible. */ + quick_symbol (abfd, "", "@feat.00", "", bfd_abs_section_ptr, + BSF_LOCAL, 1); + quick_reloc (abfd, 2, BFD_RELOC_32, 2); +#endif + 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; + case PE_ARCH_arm: + case PE_ARCH_arm_epoc: + case PE_ARCH_arm_wince: + quick_reloc (abfd, 8, BFD_RELOC_32, 2); + break; + default: + abort (); + } + save_relocs (tx); + } + else + bfd_set_section_size (abfd, tx, 0); + + bfd_set_section_size (abfd, id7, 4); + d7 = xmalloc (4); + id7->contents = d7; + memset (d7, 0, 4); + quick_reloc (abfd, 0, BFD_RELOC_RVA, 5); + save_relocs (id7); + + bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE); + d5 = xmalloc (PE_IDATA5_SIZE); + id5->contents = d5; + memset (d5, 0, PE_IDATA5_SIZE); + + if (exp->flag_noname) + { + d5[0] = exp->ordinal; + d5[1] = exp->ordinal >> 8; + d5[PE_IDATA5_SIZE - 1] = 0x80; + } + else + { + quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); + save_relocs (id5); + } + + bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE); + d4 = xmalloc (PE_IDATA4_SIZE); + id4->contents = d4; + memset (d4, 0, PE_IDATA4_SIZE); + + if (exp->flag_noname) + { + d4[0] = exp->ordinal; + d4[1] = exp->ordinal >> 8; + d4[PE_IDATA4_SIZE - 1] = 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 + { + /* { short, asciz } */ + if (exp->its_name) + len = 2 + strlen (exp->its_name) + 1; + else + len = 2 + strlen (exp->name) + 1; + if (len & 1) + len++; + bfd_set_section_size (abfd, id6, len); + d6 = xmalloc (len); + id6->contents = d6; + memset (d6, 0, len); + d6[0] = exp->hint & 0xff; + d6[1] = exp->hint >> 8; + if (exp->its_name) + strcpy ((char*) d6 + 2, exp->its_name); + else + strcpy ((char *) d6 + 2, exp->name); + } + + bfd_set_symtab (abfd, symtab, symptr); + + if (include_jmp_stub) + 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, PE_IDATA5_SIZE); + bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE); + if (!exp->flag_noname) + bfd_set_section_contents (abfd, id6, d6, 0, len); + + bfd_make_readable (abfd); + return abfd; +} + +static bfd * +make_singleton_name_imp (const char *import, bfd *parent) +{ + /* Name thunks go to idata$4. */ + asection *id5; + unsigned char *d5; + char *oname; + bfd *abfd; + + oname = xmalloc (20); + sprintf (oname, "nmimp%06d.o", tmp_seq2); + tmp_seq2++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (3 * sizeof (asymbol *)); + id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); + quick_symbol (abfd, "__imp_", import, "", id5, BSF_GLOBAL, 0); + + /* We need space for the real thunk and for the null terminator. */ + bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE * 2); + d5 = xmalloc (PE_IDATA5_SIZE * 2); + id5->contents = d5; + memset (d5, 0, PE_IDATA5_SIZE * 2); + quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); + save_relocs (id5); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA4_SIZE * 2); + + bfd_make_readable (abfd); + return abfd; +} + +static bfd * +make_singleton_name_thunk (const char *import, bfd *parent) +{ + /* Name thunks go to idata$4. */ + asection *id4; + unsigned char *d4; + char *oname; + bfd *abfd; + + oname = xmalloc (20); + sprintf (oname, "nmth%06d.o", tmp_seq); + tmp_seq++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (3 * sizeof (asymbol *)); + id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); + quick_symbol (abfd, "__nm_thnk_", import, "", id4, BSF_GLOBAL, 0); + quick_symbol (abfd, "__nm_", import, "", UNDSEC, BSF_GLOBAL, 0); + + /* We need space for the real thunk and for the null terminator. */ + bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE * 2); + d4 = xmalloc (PE_IDATA4_SIZE * 2); + id4->contents = d4; + memset (d4, 0, PE_IDATA4_SIZE * 2); + quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); + save_relocs (id4); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE * 2); + + bfd_make_readable (abfd); + return abfd; +} + +static char * +make_import_fixup_mark (arelent *rel) +{ + /* We convert reloc to symbol, for later reference. */ + static int counter; + static char *fixup_name = NULL; + static size_t buffer_len = 0; + + struct bfd_symbol *sym = *rel->sym_ptr_ptr; + + bfd *abfd = bfd_asymbol_bfd (sym); + struct bfd_link_hash_entry *bh; + + if (!fixup_name) + { + fixup_name = xmalloc (384); + buffer_len = 384; + } + + if (strlen (sym->name) + 25 > buffer_len) + /* Assume 25 chars for "__fu" + counter + "_". If counter is + bigger than 20 digits long, we've got worse problems than + overflowing this buffer... */ + { + free (fixup_name); + /* New buffer size is length of symbol, plus 25, but + then rounded up to the nearest multiple of 128. */ + buffer_len = ((strlen (sym->name) + 25) + 127) & ~127; + fixup_name = xmalloc (buffer_len); + } + + sprintf (fixup_name, "__fu%d_%s", counter++, sym->name); + + bh = NULL; + bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL, + current_sec, /* sym->section, */ + rel->address, NULL, TRUE, FALSE, &bh); + + return fixup_name; +} + +/* .section .idata$2 + .rva __nm_thnk_SYM (singleton thunk with name of func) + .long 0 + .long 0 + .rva __my_dll_iname (name of dll) + .rva __fuNN_SYM (pointer to reference (address) in text) */ + +static bfd * +make_import_fixup_entry (const char *name, + const char *fixup_name, + const char *symname, + bfd *parent) +{ + asection *id2; + unsigned char *d2; + char *oname; + bfd *abfd; + + oname = xmalloc (20); + sprintf (oname, "fu%06d.o", tmp_seq); + tmp_seq++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (6 * sizeof (asymbol *)); + id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2); + + quick_symbol (abfd, "__nm_thnk_", name, "", UNDSEC, BSF_GLOBAL, 0); + quick_symbol (abfd, U (""), symname, "_iname", UNDSEC, BSF_GLOBAL, 0); + /* For relocator v2 we have to use the .idata$5 element and not + fixup_name. */ + if (link_info.pei386_runtime_pseudo_reloc == 2) + quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0); + else + quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0); + + bfd_set_section_size (abfd, id2, 20); + d2 = xmalloc (20); + id2->contents = d2; + memset (d2, 0, 20); + + quick_reloc (abfd, 0, BFD_RELOC_RVA, 1); + quick_reloc (abfd, 12, BFD_RELOC_RVA, 2); + quick_reloc (abfd, 16, BFD_RELOC_RVA, 3); + save_relocs (id2); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, id2, d2, 0, 20); + + bfd_make_readable (abfd); + return abfd; +} + +/* .section .rdata_runtime_pseudo_reloc + .long addend + .rva __fuNN_SYM (pointer to reference (address) in text) */ + +static bfd * +make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED, + const char *fixup_name, + bfd_vma addend ATTRIBUTE_UNUSED, + bfd_vma bitsize, + bfd *parent) +{ + asection *rt_rel; + unsigned char *rt_rel_d; + char *oname; + bfd *abfd; + oname = xmalloc (20); + sprintf (oname, "rtr%06d.o", tmp_seq); + tmp_seq++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + if (link_info.pei386_runtime_pseudo_reloc == 2) + { + symtab = xmalloc ((runtime_pseudp_reloc_v2_init ? 3 : 6) * sizeof (asymbol *)); + } + else + { + symtab = xmalloc (2 * sizeof (asymbol *)); + } + rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc", + SEC_HAS_CONTENTS, 2); + + quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0); + + if (link_info.pei386_runtime_pseudo_reloc == 2) + { + size_t size = 12; + if (! runtime_pseudp_reloc_v2_init) + { + size += 12; + runtime_pseudp_reloc_v2_init = 1; + } + quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0); + + bfd_set_section_size (abfd, rt_rel, size); + rt_rel_d = xmalloc (size); + rt_rel->contents = rt_rel_d; + memset (rt_rel_d, 0, size); + quick_reloc (abfd, size - 8, BFD_RELOC_RVA, 1); + quick_reloc (abfd, size - 12, BFD_RELOC_RVA, 2); + bfd_put_32 (abfd, bitsize, rt_rel_d + (size - 4)); + if (size != 12) + bfd_put_32 (abfd, 1, rt_rel_d + 8); + save_relocs (rt_rel); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, size); + } + else + { + bfd_set_section_size (abfd, rt_rel, 8); + rt_rel_d = xmalloc (8); + rt_rel->contents = rt_rel_d; + memset (rt_rel_d, 0, 8); + + bfd_put_32 (abfd, addend, rt_rel_d); + quick_reloc (abfd, 4, BFD_RELOC_RVA, 1); + + save_relocs (rt_rel); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8); + } + bfd_make_readable (abfd); + return abfd; +} + +/* .section .rdata + .rva __pei386_runtime_relocator */ + +static bfd * +pe_create_runtime_relocator_reference (bfd *parent) +{ + asection *extern_rt_rel; + unsigned char *extern_rt_rel_d; + char *oname; + bfd *abfd; + + oname = xmalloc (20); + sprintf (oname, "ertr%06d.o", tmp_seq); + tmp_seq++; + + abfd = bfd_create (oname, parent); + bfd_find_target (pe_details->object_target, abfd); + bfd_make_writable (abfd); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); + + symptr = 0; + symtab = xmalloc (2 * sizeof (asymbol *)); + extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2); + + quick_symbol (abfd, "", U ("_pei386_runtime_relocator"), "", UNDSEC, + BSF_NO_FLAGS, 0); + + bfd_set_section_size (abfd, extern_rt_rel, PE_IDATA5_SIZE); + extern_rt_rel_d = xmalloc (PE_IDATA5_SIZE); + extern_rt_rel->contents = extern_rt_rel_d; + + quick_reloc (abfd, 0, BFD_RELOC_RVA, 1); + save_relocs (extern_rt_rel); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, PE_IDATA5_SIZE); + + bfd_make_readable (abfd); + return abfd; +} + +void +pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend) +{ + char buf[300]; + struct bfd_symbol *sym = *rel->sym_ptr_ptr; + struct bfd_link_hash_entry *name_thunk_sym; + struct bfd_link_hash_entry *name_imp_sym; + const char *name = sym->name; + char *fixup_name = make_import_fixup_mark (rel); + bfd *b; + int need_import_table = 1; + + sprintf (buf, "__imp_%s", name); + name_imp_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); + + sprintf (buf, "__nm_thnk_%s", name); + + name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); + + /* For version 2 pseudo relocation we don't need to add an import + if the import symbol is already present. */ + if (link_info.pei386_runtime_pseudo_reloc == 2 + && name_imp_sym + && name_imp_sym->type == bfd_link_hash_defined) + need_import_table = 0; + + if (need_import_table == 1 + && (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined)) + { + b = make_singleton_name_thunk (name, link_info.output_bfd); + add_bfd_to_link (b, b->filename, &link_info); + + /* If we ever use autoimport, we have to cast text section writable. + But not for version 2. */ + if (link_info.pei386_runtime_pseudo_reloc != 2) + { + config.text_read_only = FALSE; + link_info.output_bfd->flags &= ~WP_TEXT; + } + if (link_info.pei386_runtime_pseudo_reloc == 2) + { + b = make_singleton_name_imp (name, link_info.output_bfd); + add_bfd_to_link (b, b->filename, &link_info); + } + } + + if ((addend == 0 || link_info.pei386_runtime_pseudo_reloc) + && need_import_table == 1) + { + extern char * pe_data_import_dll; + char * symname = pe_data_import_dll ? pe_data_import_dll : "unknown"; + + b = make_import_fixup_entry (name, fixup_name, symname, + link_info.output_bfd); + add_bfd_to_link (b, b->filename, &link_info); + } + + if ((link_info.pei386_runtime_pseudo_reloc != 0 && addend != 0) + || link_info.pei386_runtime_pseudo_reloc == 2) + { + if (pe_dll_extra_pe_debug) + printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n", + fixup_name, (int) addend); + + b = make_runtime_pseudo_reloc (name, fixup_name, addend, rel->howto->bitsize, + link_info.output_bfd); + add_bfd_to_link (b, b->filename, &link_info); + + if (runtime_pseudo_relocs_created == 0) + { + b = pe_create_runtime_relocator_reference (link_info.output_bfd); + add_bfd_to_link (b, b->filename, &link_info); + } + runtime_pseudo_relocs_created++; + } + else if (addend != 0) + { + einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"), + s->owner, s, rel->address, sym->name); + einfo ("%X"); + } +} + + +void +pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_info *info) +{ + int i; + bfd *ar_head; + bfd *ar_tail; + bfd *outarch; + bfd *ibfd; + 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 (dll_symname[i])) + dll_symname[i] = '_'; + + unlink_if_ordinary (impfilename); + + outarch = bfd_openw (impfilename, 0); + + if (!outarch) + { + /* xgettext:c-format */ + einfo (_("%XCan't open .lib file: %s\n"), impfilename); + return; + } + + if (verbose) + /* xgettext:c-format */ + info_msg (_("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); + + /* Iterate the input BFDs, looking for exclude-modules-for-implib. */ + for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next) + { + /* Iterate the exclude list. */ + struct exclude_list_struct *ex; + char found; + for (ex = excludes, found = 0; ex && !found; ex = ex->next) + { + if (ex->type != EXCLUDEFORIMPLIB) + continue; + found = (filename_cmp (ex->string, ibfd->filename) == 0); + } + /* If it matched, we must open a fresh BFD for it (the original + input BFD is still needed for the DLL's final link) and add + it into the archive member chain. */ + if (found) + { + bfd *newbfd = bfd_openr (ibfd->my_archive + ? ibfd->my_archive->filename : ibfd->filename, NULL); + if (!newbfd) + { + einfo (_("%Xbfd_openr %s: %E\n"), ibfd->filename); + return; + } + if (ibfd->my_archive) + { + /* Must now iterate through archive until we find the + required member. A minor shame that we'll open the + archive once per member that we require from it, and + leak those archive bfds rather than reuse them. */ + bfd *arbfd = newbfd; + if (!bfd_check_format_matches (arbfd, bfd_archive, NULL)) + { + einfo (_("%X%s(%s): can't find member in non-archive file"), + ibfd->my_archive->filename, ibfd->filename); + return; + } + newbfd = NULL; + while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0) + { + if (filename_cmp (newbfd->filename, ibfd->filename) == 0) + break; + } + if (!newbfd) + { + einfo (_("%X%s(%s): can't find member in archive"), + ibfd->my_archive->filename, ibfd->filename); + return; + } + } + newbfd->archive_next = head; + head = newbfd; + } + } + + 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; + + /* Don't add PRIVATE entries to import lib. */ + if (pe_def_file->exports[i].flag_private) + continue; + def->exports[i].internal_name = def->exports[i].name; + n = make_one (def->exports + i, outarch, + ! (def->exports + i)->flag_data); + n->archive_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->archive_next = head; + ar_tail->archive_next = ar_head; + head = ar_tail; + + if (! bfd_set_archive_head (outarch, head)) + einfo ("%Xbfd_set_archive_head: %E\n"); + + if (! bfd_close (outarch)) + einfo ("%Xbfd_close %s: %E\n", impfilename); + + while (head != NULL) + { + bfd *n = head->archive_next; + bfd_close (head); + head = n; + } +} + +static int undef_count = 0; + +struct key_value +{ + char *key; + const char *oname; +}; + +static struct key_value *udef_table; + +static int undef_sort_cmp (const void *l1, const void *r1) +{ + const struct key_value *l = l1; + const struct key_value *r = r1; + + return strcmp (l->key, r->key); +} + +static struct bfd_link_hash_entry * +pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name) +{ + struct bfd_link_hash_entry *h = NULL; + struct key_value *kv; + struct key_value key; + char *at, *lname = (char *) alloca (strlen (name) + 3); + + strcpy (lname, name); + + at = strchr (lname + (lname[0] == '@'), '@'); + if (at) + at[1] = 0; + + key.key = lname; + kv = bsearch (&key, udef_table, undef_count, sizeof (struct key_value), + undef_sort_cmp); + + if (kv) + { + h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); + if (h->type == bfd_link_hash_undefined) + return h; + } + if (lname[0] == '?') + return NULL; + if (at || lname[0] == '@') + { + if (lname[0] == '@') + { + if (pe_details->underscored) + lname[0] = '_'; + else + strcpy (lname, lname + 1); + key.key = lname; + kv = bsearch (&key, udef_table, undef_count, + sizeof (struct key_value), undef_sort_cmp); + if (kv) + { + h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); + if (h->type == bfd_link_hash_undefined) + return h; + } + } + if (at) + *strchr (lname, '@') = 0; + key.key = lname; + kv = bsearch (&key, udef_table, undef_count, + sizeof (struct key_value), undef_sort_cmp); + if (kv) + { + h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); + if (h->type == bfd_link_hash_undefined) + return h; + } + return NULL; + } + + strcat (lname, "@"); + key.key = lname; + kv = bsearch (&key, udef_table, undef_count, + sizeof (struct key_value), undef_sort_cmp); + + if (kv) + { + h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); + if (h->type == bfd_link_hash_undefined) + return h; + } + + if (lname[0] == '_' && pe_details->underscored) + lname[0] = '@'; + else + { + memmove (lname + 1, lname, strlen (lname) + 1); + lname[0] = '@'; + } + key.key = lname; + + kv = bsearch (&key, udef_table, undef_count, + sizeof (struct key_value), undef_sort_cmp); + + if (kv) + { + h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE); + if (h->type == bfd_link_hash_undefined) + return h; + } + + return NULL; +} + +static bfd_boolean +pe_undef_count (struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED, + void *inf ATTRIBUTE_UNUSED) +{ + if (h->type == bfd_link_hash_undefined) + undef_count++; + return TRUE; +} + +static bfd_boolean +pe_undef_fill (struct bfd_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) +{ + if (h->type == bfd_link_hash_undefined) + { + char *at; + + udef_table[undef_count].key = xstrdup (h->root.string); + at = strchr (udef_table[undef_count].key + + (udef_table[undef_count].key[0] == '@'), '@'); + if (at) + at[1] = 0; + udef_table[undef_count].oname = h->root.string; + undef_count++; + } + return TRUE; +} + +static void +pe_create_undef_table (void) +{ + undef_count = 0; + + /* count undefined symbols */ + + bfd_link_hash_traverse (link_info.hash, pe_undef_count, ""); + + /* create and fill the corresponding table */ + udef_table = xmalloc (undef_count * sizeof (struct key_value)); + + undef_count = 0; + bfd_link_hash_traverse (link_info.hash, pe_undef_fill, ""); + + /* sort items */ + qsort (udef_table, undef_count, sizeof (struct key_value), undef_sort_cmp); +} + +static void +add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *linfo) +{ + 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, linfo)) + einfo ("%Xaddsym %s: %E\n", name); +} + +void +pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo) +{ + int i, j; + def_file_module *module; + def_file_import *imp; + + pe_dll_id_target (bfd_get_target (output_bfd)); + + if (!pe_def_file) + return; + + imp = pe_def_file->imports; + + pe_create_undef_table (); + + for (module = pe_def_file->modules; module; module = module->next) + { + int do_this_dll = 0; + + for (i = 0; i < pe_def_file->num_imports && imp[i].module != module; i++) + ; + if (i >= pe_def_file->num_imports) + continue; + + dll_filename = module->name; + dll_symname = xstrdup (module->name); + for (j = 0; dll_symname[j]; j++) + if (!ISALNUM (dll_symname[j])) + dll_symname[j] = '_'; + + for (; i < pe_def_file->num_imports && imp[i].module == module; i++) + { + def_file_export exp; + struct bfd_link_hash_entry *blhe; + int lead_at = (*imp[i].internal_name == '@'); + /* See if we need this import. */ + size_t len = strlen (imp[i].internal_name); + char *name = xmalloc (len + 2 + 6); + bfd_boolean include_jmp_stub = FALSE; + bfd_boolean is_cdecl = FALSE; + bfd_boolean is_undef = FALSE; + + if (!lead_at && strchr (imp[i].internal_name, '@') == NULL) + is_cdecl = TRUE; + + if (lead_at) + sprintf (name, "%s", imp[i].internal_name); + else + sprintf (name, "%s%s",U (""), imp[i].internal_name); + + blhe = bfd_link_hash_lookup (linfo->hash, name, + FALSE, FALSE, FALSE); + + /* Include the jump stub for <sym> only if the <sym> + is undefined. */ + if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)) + { + if (lead_at) + sprintf (name, "%s%s", "__imp_", imp[i].internal_name); + else + sprintf (name, "%s%s%s", "__imp_", U (""), + imp[i].internal_name); + + blhe = bfd_link_hash_lookup (linfo->hash, name, + FALSE, FALSE, FALSE); + if (blhe) + is_undef = (blhe->type == bfd_link_hash_undefined); + } + else + { + include_jmp_stub = TRUE; + is_undef = (blhe->type == bfd_link_hash_undefined); + } + + if (is_cdecl && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))) + { + sprintf (name, "%s%s",U (""), imp[i].internal_name); + blhe = pe_find_cdecl_alias_match (linfo, name); + include_jmp_stub = TRUE; + if (blhe) + is_undef = (blhe->type == bfd_link_hash_undefined); + } + + free (name); + + if (is_undef) + { + bfd *one; + /* We do. */ + if (!do_this_dll) + { + bfd *ar_head = make_head (output_bfd); + add_bfd_to_link (ar_head, ar_head->filename, linfo); + do_this_dll = 1; + } + exp.internal_name = imp[i].internal_name; + exp.name = imp[i].name; + exp.its_name = imp[i].its_name; + exp.ordinal = imp[i].ordinal; + exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0; + exp.flag_private = 0; + exp.flag_constant = 0; + exp.flag_data = imp[i].data; + exp.flag_noname = exp.name ? 0 : 1; + one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub); + add_bfd_to_link (one, one->filename, linfo); + } + } + if (do_this_dll) + { + bfd *ar_tail = make_tail (output_bfd); + add_bfd_to_link (ar_tail, ar_tail->filename, linfo); + } + + free (dll_symname); + } + + while (undef_count) + { + --undef_count; + free (udef_table[undef_count].key); + } + free (udef_table); +} + +/* 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 int +pe_get16 (bfd *abfd, int where) +{ + unsigned char b[2]; + + bfd_seek (abfd, (file_ptr) where, SEEK_SET); + bfd_bread (b, (bfd_size_type) 2, abfd); + return b[0] + (b[1] << 8); +} + +static unsigned int +pe_get32 (bfd *abfd, int where) +{ + unsigned char b[4]; + + bfd_seek (abfd, (file_ptr) where, SEEK_SET); + bfd_bread (b, (bfd_size_type) 4, abfd); + return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); +} + +static unsigned int +pe_as32 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); +} + +bfd_boolean +pe_implied_import_dll (const char *filename) +{ + bfd *dll; + bfd_vma pe_header_offset, opthdr_ofs, num_entries, i; + bfd_vma export_rva, export_size, nsections, secptr, expptr; + bfd_vma exp_funcbase; + unsigned char *expdata; + char *erva; + bfd_vma name_rvas, nexp; + const char *dllname; + /* Initialization with start > end guarantees that is_data + will not be set by mistake, and avoids compiler warning. */ + bfd_vma data_start = 1; + bfd_vma data_end = 0; + bfd_vma rdata_start = 1; + bfd_vma rdata_end = 0; + bfd_vma bss_start = 1; + bfd_vma bss_end = 0; + + /* 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: %E\n", filename); + 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; + } + + /* Get pe_header, optional header and numbers of directory entries. */ + pe_header_offset = pe_get32 (dll, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; +#ifdef pe_use_x86_64 + num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /* & NumberOfRvaAndSizes. */ +#else + num_entries = pe_get32 (dll, opthdr_ofs + 92); +#endif + + /* No import or export directory entry. */ + if (num_entries < 1) + return FALSE; + +#ifdef pe_use_x86_64 + export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4); + export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4); +#else + export_rva = pe_get32 (dll, opthdr_ofs + 96); + export_size = pe_get32 (dll, opthdr_ofs + 100); +#endif + + /* No export table - nothing to export. */ + if (export_size == 0) + return FALSE; + + 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; + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + bfd_vma secptr1 = secptr + 40 * i; + bfd_vma vaddr = pe_get32 (dll, secptr1 + 12); + bfd_vma vsize = pe_get32 (dll, secptr1 + 16); + bfd_vma fptr = pe_get32 (dll, secptr1 + 20); + + bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 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; + } + } + + /* Scan sections and store the base and size of the + data and bss segments in data/base_start/end. */ + for (i = 0; i < nsections; i++) + { + bfd_vma secptr1 = secptr + 40 * i; + bfd_vma vsize = pe_get32 (dll, secptr1 + 8); + bfd_vma vaddr = pe_get32 (dll, secptr1 + 12); + bfd_vma flags = pe_get32 (dll, secptr1 + 36); + char sec_name[9]; + + sec_name[8] = '\0'; + bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); + bfd_bread (sec_name, (bfd_size_type) 8, dll); + + if (strcmp(sec_name,".data") == 0) + { + data_start = vaddr; + data_end = vaddr + vsize; + + if (pe_dll_extra_pe_debug) + printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", + __FUNCTION__, sec_name, (unsigned long) vaddr, + (unsigned long) (vaddr + vsize), (unsigned long) flags); + } + else if (strcmp(sec_name,".rdata") == 0) + { + rdata_start = vaddr; + rdata_end = vaddr + vsize; + + if (pe_dll_extra_pe_debug) + printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", + __FUNCTION__, sec_name, (unsigned long) vaddr, + (unsigned long) (vaddr + vsize), (unsigned long) flags); + } + else if (strcmp (sec_name,".bss") == 0) + { + bss_start = vaddr; + bss_end = vaddr + vsize; + + if (pe_dll_extra_pe_debug) + printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", + __FUNCTION__, sec_name, (unsigned long) vaddr, + (unsigned long) (vaddr + vsize), (unsigned long) flags); + } + } + + expdata = xmalloc (export_size); + bfd_seek (dll, (file_ptr) expptr, SEEK_SET); + bfd_bread (expdata, (bfd_size_type) export_size, dll); + erva = (char *) 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); + exp_funcbase = pe_as32 (expdata + 28); + + /* Use internal dll name instead of filename + to enable symbolic dll linking. */ + dllname = erva + pe_as32 (expdata + 12); + + /* Check to see if the dll has already been added to + the definition list and if so return without error. + This avoids multiple symbol definitions. */ + if (def_get_module (pe_def_file, dllname)) + { + if (pe_dll_extra_pe_debug) + printf ("%s is already loaded\n", dllname); + return TRUE; + } + + /* Iterate through the list of symbols. */ + for (i = 0; i < nexp; i++) + { + /* Pointer to the names vector. */ + bfd_vma name_rva = pe_as32 (erva + name_rvas + i * 4); + def_file_import *imp; + /* Pointer to the function address vector. */ + bfd_vma func_rva = pe_as32 (erva + exp_funcbase + i * 4); + int is_data = 0; + + /* Skip unwanted symbols, which are + exported in buggy auto-import releases. */ + if (! CONST_STRNEQ (erva + name_rva, "__nm_")) + { + int is_dup = 0; + /* is_data is true if the address is in the data, rdata or bss + segment. */ + is_data = + (func_rva >= data_start && func_rva < data_end) + || (func_rva >= rdata_start && func_rva < rdata_end) + || (func_rva >= bss_start && func_rva < bss_end); + + imp = def_file_add_import (pe_def_file, erva + name_rva, + dllname, i, NULL, NULL, &is_dup); + /* Mark symbol type. */ + if (!is_dup) + imp->data = is_data; + + if (pe_dll_extra_pe_debug) + printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n", + __FUNCTION__, dllname, erva + name_rva, + (unsigned long) func_rva, is_data ? "(data)" : ""); + } + } + + return TRUE; +} + +void +pe_output_file_set_long_section_names (bfd *abfd) +{ + if (pe_use_coff_long_section_names < 0) + return; + if (!bfd_coff_set_long_section_names (abfd, pe_use_coff_long_section_names)) + einfo (_("%XError: can't use long section names on this arch\n")); +} + +/* 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. */ + +void +pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info) +{ + pe_dll_id_target (bfd_get_target (abfd)); + pe_output_file_set_long_section_names (abfd); + process_def_file_and_drectve (abfd, info); + + if (pe_def_file->num_exports == 0 && !info->shared) + return; + + generate_edata (abfd, info); + build_filler_bfd (1); + pe_output_file_set_long_section_names (filler_bfd); +} + +void +pe_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + pe_dll_id_target (bfd_get_target (abfd)); + pe_output_file_set_long_section_names (abfd); + build_filler_bfd (0); + pe_output_file_set_long_section_names (filler_bfd); +} + +void +pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info) +{ + pe_dll_id_target (bfd_get_target (abfd)); + pe_output_file_set_long_section_names (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_reset_memory_regions (); + lang_size_sections (NULL, TRUE); + + /* Redo special stuff. */ + ldemul_after_allocation (); + + /* Do the assignments again. */ + lang_do_assignments (lang_final_phase_enum); + } + + fill_edata (abfd, info); + + if (info->shared && !info->pie) + pe_data (abfd)->dll = 1; + + edata_s->contents = edata_d; + reloc_s->contents = reloc_d; +} + +void +pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info) +{ + pe_dll_id_target (bfd_get_target (abfd)); + pe_output_file_set_long_section_names (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_reset_memory_regions (); + lang_size_sections (NULL, TRUE); + + /* Redo special stuff. */ + ldemul_after_allocation (); + + /* Do the assignments again. */ + lang_do_assignments (lang_final_phase_enum); + } + reloc_s->contents = reloc_d; +} + +bfd_boolean +pe_bfd_is_dll (bfd *abfd) +{ + return (bfd_get_format (abfd) == bfd_object + && obj_pe (abfd) + && pe_data (abfd)->dll); +} |