aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2022-10-17 00:24:18 +0100
committerAlan Modra <amodra@gmail.com>2022-10-20 15:22:37 +1030
commitf6f30f347bb97898a74e59a841982170e42bb265 (patch)
tree966ab495055389361fb61cc34836818bc7890bc1 /ld
parent97df7412a183b73a1bfaeed55a4d951c2aede7d4 (diff)
downloadgdb-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.em50
-rw-r--r--ld/emultempl/pep.em48
-rw-r--r--ld/testsuite/ld-pe/pdb.exp53
-rw-r--r--ld/testsuite/ld-pe/pdb1.s5
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