diff options
author | Mark Harmstone <mark@harmstone.com> | 2022-10-17 00:24:18 +0100 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2022-10-20 15:22:37 +1030 |
commit | f6f30f347bb97898a74e59a841982170e42bb265 (patch) | |
tree | 966ab495055389361fb61cc34836818bc7890bc1 /ld | |
parent | 97df7412a183b73a1bfaeed55a4d951c2aede7d4 (diff) | |
download | gdb-f6f30f347bb97898a74e59a841982170e42bb265.zip gdb-f6f30f347bb97898a74e59a841982170e42bb265.tar.gz gdb-f6f30f347bb97898a74e59a841982170e42bb265.tar.bz2 |
ld: Add --pdb option
Second patch incorporates fixes for endian and UB issues in calc_hash, as per
https://sourceware.org/pipermail/binutils/2022-October/123514.html.
Diffstat (limited to 'ld')
-rw-r--r-- | ld/emultempl/pe.em | 50 | ||||
-rw-r--r-- | ld/emultempl/pep.em | 48 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb.exp | 53 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb1.s | 5 |
4 files changed, 147 insertions, 9 deletions
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index c018296..db90679 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -146,6 +146,8 @@ static lang_assignment_statement_type *image_base_statement = 0; static unsigned short pe_dll_characteristics = DEFAULT_DLL_CHARACTERISTICS; static bool insert_timestamp = true; static const char *emit_build_id; +static int pdb; +static char *pdb_name; #ifdef DLL_SUPPORT static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */ @@ -285,7 +287,8 @@ fragment <<EOF #define OPTION_INSERT_TIMESTAMP (OPTION_TERMINAL_SERVER_AWARE + 1) #define OPTION_NO_INSERT_TIMESTAMP (OPTION_INSERT_TIMESTAMP + 1) #define OPTION_BUILD_ID (OPTION_NO_INSERT_TIMESTAMP + 1) -#define OPTION_ENABLE_RELOC_SECTION (OPTION_BUILD_ID + 1) +#define OPTION_PDB (OPTION_BUILD_ID + 1) +#define OPTION_ENABLE_RELOC_SECTION (OPTION_PDB + 1) #define OPTION_DISABLE_RELOC_SECTION (OPTION_ENABLE_RELOC_SECTION + 1) /* DLL Characteristics flags. */ #define OPTION_DISABLE_DYNAMIC_BASE (OPTION_DISABLE_RELOC_SECTION + 1) @@ -384,6 +387,7 @@ gld${EMULATION_NAME}_add_options {"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE}, {"disable-tsaware", no_argument, NULL, OPTION_DISABLE_TERMINAL_SERVER_AWARE}, {"build-id", optional_argument, NULL, OPTION_BUILD_ID}, + {"pdb", required_argument, NULL, OPTION_PDB}, {"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION}, {"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION}, {NULL, no_argument, NULL, 0} @@ -533,6 +537,7 @@ gld${EMULATION_NAME}_list_options (FILE *file) fprintf (file, _(" --[disable-]wdmdriver Driver uses the WDM model\n")); fprintf (file, _(" --[disable-]tsaware Image is Terminal Server aware\n")); fprintf (file, _(" --build-id[=STYLE] Generate build ID\n")); + fprintf (file, _(" --pdb=[FILENAME] Generate PDB file\n")); } /* A case insensitive comparison, regardless of the host platform, used for @@ -973,6 +978,11 @@ gld${EMULATION_NAME}_handle_option (int optc) if (strcmp (optarg, "none")) emit_build_id = xstrdup (optarg); break; + case OPTION_PDB: + pdb = 1; + if (optarg && optarg[0]) + pdb_name = xstrdup (optarg); + break; } /* Set DLLCharacteristics bits */ @@ -1095,6 +1105,9 @@ gld${EMULATION_NAME}_after_parse (void) einfo (_("%P: warning: --export-dynamic is not supported for PE " "targets, did you mean --export-all-symbols?\n")); + if (pdb && emit_build_id == NULL) + emit_build_id = xstrdup (DEFAULT_BUILD_ID_STYLE); + set_entry_point (); after_parse_default (); @@ -1274,6 +1287,7 @@ write_build_id (bfd *abfd) bfd_size_type size; bfd_size_type build_id_size; unsigned char *build_id; + const char *pdb_base_name = NULL; /* Find the section the .buildid output section has been merged info. */ for (asec = abfd->sections; asec != NULL; asec = asec->next) @@ -1313,6 +1327,9 @@ write_build_id (bfd *abfd) bfd_vma ib = pe_data (link_info.output_bfd)->pe_opthdr.ImageBase; + if (pdb_name) + pdb_base_name = lbasename (pdb_name); + /* Construct a debug directory entry which points to an immediately following CodeView record. */ struct internal_IMAGE_DEBUG_DIRECTORY idd; idd.Characteristics = 0; @@ -1320,7 +1337,7 @@ write_build_id (bfd *abfd) idd.MajorVersion = 0; idd.MinorVersion = 0; idd.Type = PE_IMAGE_DEBUG_TYPE_CODEVIEW; - idd.SizeOfData = sizeof (CV_INFO_PDB70) + 1; + idd.SizeOfData = sizeof (CV_INFO_PDB70) + (pdb_base_name ? strlen (pdb_base_name) : 0) + 1; idd.AddressOfRawData = asec->vma - ib + link_order->offset + sizeof (struct external_IMAGE_DEBUG_DIRECTORY); idd.PointerToRawData = asec->filepos + link_order->offset @@ -1349,7 +1366,8 @@ write_build_id (bfd *abfd) free (build_id); /* Write the codeview record. */ - if (_bfd_XXi_write_codeview_record (abfd, idd.PointerToRawData, &cvinfo) == 0) + if (_bfd_XXi_write_codeview_record (abfd, idd.PointerToRawData, &cvinfo, + pdb_base_name) == 0) return 0; /* Record the location of the debug directory in the data directory. */ @@ -1386,11 +1404,14 @@ setup_build_id (bfd *ibfd) /* Section is a fixed size: One IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW, - pointing at a CV_INFO_PDB70 record containing the build-id, with a - null byte for PdbFileName. */ + pointing at a CV_INFO_PDB70 record containing the build-id, followed by + PdbFileName if relevant. */ s->size = sizeof (struct external_IMAGE_DEBUG_DIRECTORY) + sizeof (CV_INFO_PDB70) + 1; + if (pdb_name) + s->size += strlen (pdb_name); + return true; } @@ -1421,6 +1442,25 @@ gld${EMULATION_NAME}_after_open (void) } #endif + if (pdb && !pdb_name) + { + const char *base = lbasename (bfd_get_filename (link_info.output_bfd)); + size_t len = strlen (base); + static const char suffix[] = ".pdb"; + + while (len > 0 && base[len] != '.') + { + len--; + } + + if (len == 0) + len = strlen (base); + + pdb_name = xmalloc (len + sizeof (suffix)); + memcpy (pdb_name, base, len); + memcpy (pdb_name + len, suffix, sizeof (suffix)); + } + if (emit_build_id != NULL) { bfd *abfd; diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 7a390e7..66cc61e 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -165,6 +165,8 @@ static lang_assignment_statement_type *image_base_statement = 0; static unsigned short pe_dll_characteristics = DEFAULT_DLL_CHARACTERISTICS; static bool insert_timestamp = true; static const char *emit_build_id; +static int pdb; +static char *pdb_name; #ifdef DLL_SUPPORT static int pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default). */ @@ -281,6 +283,7 @@ enum options OPTION_NO_INSERT_TIMESTAMP, OPTION_TERMINAL_SERVER_AWARE, OPTION_BUILD_ID, + OPTION_PDB, OPTION_ENABLE_RELOC_SECTION, OPTION_DISABLE_RELOC_SECTION, OPTION_DISABLE_HIGH_ENTROPY_VA, @@ -369,6 +372,7 @@ gld${EMULATION_NAME}_add_options {"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP}, {"no-insert-timestamp", no_argument, NULL, OPTION_NO_INSERT_TIMESTAMP}, {"build-id", optional_argument, NULL, OPTION_BUILD_ID}, + {"pdb", required_argument, NULL, OPTION_PDB}, {"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION}, {"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION}, {"disable-high-entropy-va", no_argument, NULL, OPTION_DISABLE_HIGH_ENTROPY_VA}, @@ -516,6 +520,7 @@ gld${EMULATION_NAME}_list_options (FILE *file) fprintf (file, _(" --[disable-]wdmdriver Driver uses the WDM model\n")); fprintf (file, _(" --[disable-]tsaware Image is Terminal Server aware\n")); fprintf (file, _(" --build-id[=STYLE] Generate build ID\n")); + fprintf (file, _(" --pdb=[FILENAME] Generate PDB file\n")); #endif } @@ -924,6 +929,11 @@ gld${EMULATION_NAME}_handle_option (int optc) if (strcmp (optarg, "none")) emit_build_id = xstrdup (optarg); break; + case OPTION_PDB: + pdb = 1; + if (optarg && optarg[0]) + pdb_name = xstrdup (optarg); + break; } /* Set DLLCharacteristics bits */ @@ -1046,6 +1056,9 @@ gld${EMULATION_NAME}_after_parse (void) einfo (_("%P: warning: --export-dynamic is not supported for PE+ " "targets, did you mean --export-all-symbols?\n")); + if (pdb && emit_build_id == NULL) + emit_build_id = xstrdup (DEFAULT_BUILD_ID_STYLE); + set_entry_point (); after_parse_default (); @@ -1266,6 +1279,7 @@ write_build_id (bfd *abfd) bfd_size_type size; bfd_size_type build_id_size; unsigned char *build_id; + const char *pdb_base_name = NULL; /* Find the section the .buildid output section has been merged info. */ for (asec = abfd->sections; asec != NULL; asec = asec->next) @@ -1305,6 +1319,9 @@ write_build_id (bfd *abfd) bfd_vma ib = pe_data (link_info.output_bfd)->pe_opthdr.ImageBase; + if (pdb_name) + pdb_base_name = lbasename (pdb_name); + /* Construct a debug directory entry which points to an immediately following CodeView record. */ struct internal_IMAGE_DEBUG_DIRECTORY idd; idd.Characteristics = 0; @@ -1312,7 +1329,7 @@ write_build_id (bfd *abfd) idd.MajorVersion = 0; idd.MinorVersion = 0; idd.Type = PE_IMAGE_DEBUG_TYPE_CODEVIEW; - idd.SizeOfData = sizeof (CV_INFO_PDB70) + 1; + idd.SizeOfData = sizeof (CV_INFO_PDB70) + (pdb_base_name ? strlen (pdb_base_name) : 0) + 1; idd.AddressOfRawData = asec->vma - ib + link_order->offset + sizeof (struct external_IMAGE_DEBUG_DIRECTORY); idd.PointerToRawData = asec->filepos + link_order->offset @@ -1341,7 +1358,8 @@ write_build_id (bfd *abfd) free (build_id); /* Write the codeview record. */ - if (_bfd_XXi_write_codeview_record (abfd, idd.PointerToRawData, &cvinfo) == 0) + if (_bfd_XXi_write_codeview_record (abfd, idd.PointerToRawData, &cvinfo, + pdb_base_name) == 0) return 0; /* Record the location of the debug directory in the data directory. */ @@ -1378,11 +1396,14 @@ setup_build_id (bfd *ibfd) /* Section is a fixed size: One IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW, - pointing at a CV_INFO_PDB70 record containing the build-id, with a - null byte for PdbFileName. */ + pointing at a CV_INFO_PDB70 record containing the build-id, followed by + PdbFileName if relevant. */ s->size = sizeof (struct external_IMAGE_DEBUG_DIRECTORY) + sizeof (CV_INFO_PDB70) + 1; + if (pdb_name) + s->size += strlen (pdb_name); + return true; } @@ -1414,6 +1435,25 @@ gld${EMULATION_NAME}_after_open (void) } #endif + if (pdb && !pdb_name) + { + const char *base = lbasename (bfd_get_filename (link_info.output_bfd)); + size_t len = strlen (base); + static const char suffix[] = ".pdb"; + + while (len > 0 && base[len] != '.') + { + len--; + } + + if (len == 0) + len = strlen (base); + + pdb_name = xmalloc (len + sizeof (suffix)); + memcpy (pdb_name, base, len); + memcpy (pdb_name + len, suffix, sizeof (suffix)); + } + if (emit_build_id != NULL) { bfd *abfd; diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp new file mode 100644 index 0000000..1560241 --- /dev/null +++ b/ld/testsuite/ld-pe/pdb.exp @@ -0,0 +1,53 @@ +# Expect script for creating PDB files when linking. +# Copyright (C) 2022 Free Software Foundation, Inc. +# +# 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. + +if {![istarget i*86-*-mingw*] + && ![istarget x86_64-*-mingw*]} { + return +} + +proc get_pdb_name { pe } { + global OBJDUMP + + set exec_output [run_host_cmd "$OBJDUMP" "-p $pe"] + + if ![regexp -line "^\\(format RSDS signature (\[0-9a-fA-F\]{32}) age 1 pdb (.*)\\)$" $exec_output full sig pdb] { + return "" + } + + return $pdb +} + +if ![ld_assemble $as $srcdir/$subdir/pdb1.s tmpdir/pdb1.o] { + unsupported "Build pdb1.o" + return +} + +if ![ld_link $ld "tmpdir/pdb1.exe" "--pdb=tmpdir/pdb1.pdb tmpdir/pdb1.o"] { + fail "Could not create a PE image with a PDB file" + return +} + +if ![string equal [get_pdb_name "tmpdir/pdb1.exe"] "pdb1.pdb"] { + fail "PDB filename not found in CodeView debug info" + return +} + +pass "PDB filename present in CodeView debug info" diff --git a/ld/testsuite/ld-pe/pdb1.s b/ld/testsuite/ld-pe/pdb1.s new file mode 100644 index 0000000..30a8cfc --- /dev/null +++ b/ld/testsuite/ld-pe/pdb1.s @@ -0,0 +1,5 @@ +.text + +.global foo +foo: + .long 0x12345678 |