mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-19 00:59:15 +08:00
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.
This commit is contained in:

committed by
Alan Modra

parent
97df7412a1
commit
f6f30f347b
@ -423,9 +423,11 @@ void _bfd_XX_get_symbol_info (bfd *, asymbol *, symbol_info *);
|
|||||||
bool _bfd_XXi_final_link_postscript (bfd *, struct coff_final_link_info *);
|
bool _bfd_XXi_final_link_postscript (bfd *, struct coff_final_link_info *);
|
||||||
void _bfd_XXi_swap_debugdir_in (bfd *, void *, void *);
|
void _bfd_XXi_swap_debugdir_in (bfd *, void *, void *);
|
||||||
unsigned _bfd_XXi_swap_debugdir_out (bfd *, void *, void *);
|
unsigned _bfd_XXi_swap_debugdir_out (bfd *, void *, void *);
|
||||||
unsigned _bfd_XXi_write_codeview_record (bfd *, file_ptr, CODEVIEW_INFO *);
|
unsigned _bfd_XXi_write_codeview_record
|
||||||
|
(bfd *, file_ptr, CODEVIEW_INFO *, const char *);
|
||||||
CODEVIEW_INFO *_bfd_XXi_slurp_codeview_record
|
CODEVIEW_INFO *_bfd_XXi_slurp_codeview_record
|
||||||
(bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo);
|
(bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo,
|
||||||
|
char **pdb);
|
||||||
|
|
||||||
/* The following are needed only for ONE of pe or pei, but don't
|
/* The following are needed only for ONE of pe or pei, but don't
|
||||||
otherwise vary; peicode.h fixes up ifdefs but we provide the
|
otherwise vary; peicode.h fixes up ifdefs but we provide the
|
||||||
|
@ -1122,7 +1122,8 @@ _bfd_XXi_swap_debugdir_out (bfd * abfd, void * inp, void * extp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CODEVIEW_INFO *
|
CODEVIEW_INFO *
|
||||||
_bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo)
|
_bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo,
|
||||||
|
char **pdb)
|
||||||
{
|
{
|
||||||
char buffer[256+1];
|
char buffer[256+1];
|
||||||
bfd_size_type nread;
|
bfd_size_type nread;
|
||||||
@ -1162,6 +1163,9 @@ _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length
|
|||||||
cvinfo->SignatureLength = CV_INFO_SIGNATURE_LENGTH;
|
cvinfo->SignatureLength = CV_INFO_SIGNATURE_LENGTH;
|
||||||
/* cvinfo->PdbFileName = cvinfo70->PdbFileName; */
|
/* cvinfo->PdbFileName = cvinfo70->PdbFileName; */
|
||||||
|
|
||||||
|
if (pdb)
|
||||||
|
*pdb = xstrdup (cvinfo70->PdbFileName);
|
||||||
|
|
||||||
return cvinfo;
|
return cvinfo;
|
||||||
}
|
}
|
||||||
else if ((cvinfo->CVSignature == CVINFO_PDB20_CVSIGNATURE)
|
else if ((cvinfo->CVSignature == CVINFO_PDB20_CVSIGNATURE)
|
||||||
@ -1173,6 +1177,9 @@ _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length
|
|||||||
cvinfo->SignatureLength = 4;
|
cvinfo->SignatureLength = 4;
|
||||||
/* cvinfo->PdbFileName = cvinfo20->PdbFileName; */
|
/* cvinfo->PdbFileName = cvinfo20->PdbFileName; */
|
||||||
|
|
||||||
|
if (pdb)
|
||||||
|
*pdb = xstrdup (cvinfo20->PdbFileName);
|
||||||
|
|
||||||
return cvinfo;
|
return cvinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1180,9 +1187,11 @@ _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
_bfd_XXi_write_codeview_record (bfd * abfd, file_ptr where, CODEVIEW_INFO *cvinfo)
|
_bfd_XXi_write_codeview_record (bfd * abfd, file_ptr where, CODEVIEW_INFO *cvinfo,
|
||||||
|
const char *pdb)
|
||||||
{
|
{
|
||||||
const bfd_size_type size = sizeof (CV_INFO_PDB70) + 1;
|
size_t pdb_len = pdb ? strlen (pdb) : 0;
|
||||||
|
const bfd_size_type size = sizeof (CV_INFO_PDB70) + pdb_len + 1;
|
||||||
bfd_size_type written;
|
bfd_size_type written;
|
||||||
CV_INFO_PDB70 *cvinfo70;
|
CV_INFO_PDB70 *cvinfo70;
|
||||||
char * buffer;
|
char * buffer;
|
||||||
@ -1205,7 +1214,11 @@ _bfd_XXi_write_codeview_record (bfd * abfd, file_ptr where, CODEVIEW_INFO *cvinf
|
|||||||
memcpy (&(cvinfo70->Signature[8]), &(cvinfo->Signature[8]), 8);
|
memcpy (&(cvinfo70->Signature[8]), &(cvinfo->Signature[8]), 8);
|
||||||
|
|
||||||
H_PUT_32 (abfd, cvinfo->Age, cvinfo70->Age);
|
H_PUT_32 (abfd, cvinfo->Age, cvinfo70->Age);
|
||||||
cvinfo70->PdbFileName[0] = '\0';
|
|
||||||
|
if (pdb == NULL)
|
||||||
|
cvinfo70->PdbFileName[0] = '\0';
|
||||||
|
else
|
||||||
|
memcpy (cvinfo70->PdbFileName, pdb, pdb_len + 1);
|
||||||
|
|
||||||
written = bfd_bwrite (buffer, size, abfd);
|
written = bfd_bwrite (buffer, size, abfd);
|
||||||
|
|
||||||
@ -2603,22 +2616,25 @@ pe_print_debugdata (bfd * abfd, void * vfile)
|
|||||||
We need to use a 32-bit aligned buffer
|
We need to use a 32-bit aligned buffer
|
||||||
to safely read in a codeview record. */
|
to safely read in a codeview record. */
|
||||||
char buffer[256 + 1] ATTRIBUTE_ALIGNED_ALIGNOF (CODEVIEW_INFO);
|
char buffer[256 + 1] ATTRIBUTE_ALIGNED_ALIGNOF (CODEVIEW_INFO);
|
||||||
|
char *pdb;
|
||||||
|
|
||||||
CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
|
CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
|
||||||
|
|
||||||
/* The debug entry doesn't have to have to be in a section,
|
/* The debug entry doesn't have to have to be in a section,
|
||||||
in which case AddressOfRawData is 0, so always use PointerToRawData. */
|
in which case AddressOfRawData is 0, so always use PointerToRawData. */
|
||||||
if (!_bfd_XXi_slurp_codeview_record (abfd, (file_ptr) idd.PointerToRawData,
|
if (!_bfd_XXi_slurp_codeview_record (abfd, (file_ptr) idd.PointerToRawData,
|
||||||
idd.SizeOfData, cvinfo))
|
idd.SizeOfData, cvinfo, &pdb))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j = 0; j < cvinfo->SignatureLength; j++)
|
for (j = 0; j < cvinfo->SignatureLength; j++)
|
||||||
sprintf (&signature[j*2], "%02x", cvinfo->Signature[j] & 0xff);
|
sprintf (&signature[j*2], "%02x", cvinfo->Signature[j] & 0xff);
|
||||||
|
|
||||||
/* xgettext:c-format */
|
/* xgettext:c-format */
|
||||||
fprintf (file, _("(format %c%c%c%c signature %s age %ld)\n"),
|
fprintf (file, _("(format %c%c%c%c signature %s age %ld pdb %s)\n"),
|
||||||
buffer[0], buffer[1], buffer[2], buffer[3],
|
buffer[0], buffer[1], buffer[2], buffer[3],
|
||||||
signature, cvinfo->Age);
|
signature, cvinfo->Age, pdb[0] ? pdb : "(none)");
|
||||||
|
|
||||||
|
free (pdb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1402,7 +1402,7 @@ pe_bfd_read_buildid (bfd *abfd)
|
|||||||
*/
|
*/
|
||||||
if (_bfd_XXi_slurp_codeview_record (abfd,
|
if (_bfd_XXi_slurp_codeview_record (abfd,
|
||||||
(file_ptr) idd.PointerToRawData,
|
(file_ptr) idd.PointerToRawData,
|
||||||
idd.SizeOfData, cvinfo))
|
idd.SizeOfData, cvinfo, NULL))
|
||||||
{
|
{
|
||||||
struct bfd_build_id* build_id = bfd_alloc (abfd,
|
struct bfd_build_id* build_id = bfd_alloc (abfd,
|
||||||
sizeof (struct bfd_build_id) + cvinfo->SignatureLength);
|
sizeof (struct bfd_build_id) + cvinfo->SignatureLength);
|
||||||
|
@ -146,6 +146,8 @@ static lang_assignment_statement_type *image_base_statement = 0;
|
|||||||
static unsigned short pe_dll_characteristics = DEFAULT_DLL_CHARACTERISTICS;
|
static unsigned short pe_dll_characteristics = DEFAULT_DLL_CHARACTERISTICS;
|
||||||
static bool insert_timestamp = true;
|
static bool insert_timestamp = true;
|
||||||
static const char *emit_build_id;
|
static const char *emit_build_id;
|
||||||
|
static int pdb;
|
||||||
|
static char *pdb_name;
|
||||||
|
|
||||||
#ifdef DLL_SUPPORT
|
#ifdef DLL_SUPPORT
|
||||||
static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */
|
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_INSERT_TIMESTAMP (OPTION_TERMINAL_SERVER_AWARE + 1)
|
||||||
#define OPTION_NO_INSERT_TIMESTAMP (OPTION_INSERT_TIMESTAMP + 1)
|
#define OPTION_NO_INSERT_TIMESTAMP (OPTION_INSERT_TIMESTAMP + 1)
|
||||||
#define OPTION_BUILD_ID (OPTION_NO_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)
|
#define OPTION_DISABLE_RELOC_SECTION (OPTION_ENABLE_RELOC_SECTION + 1)
|
||||||
/* DLL Characteristics flags. */
|
/* DLL Characteristics flags. */
|
||||||
#define OPTION_DISABLE_DYNAMIC_BASE (OPTION_DISABLE_RELOC_SECTION + 1)
|
#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},
|
{"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
|
||||||
{"disable-tsaware", no_argument, NULL, OPTION_DISABLE_TERMINAL_SERVER_AWARE},
|
{"disable-tsaware", no_argument, NULL, OPTION_DISABLE_TERMINAL_SERVER_AWARE},
|
||||||
{"build-id", optional_argument, NULL, OPTION_BUILD_ID},
|
{"build-id", optional_argument, NULL, OPTION_BUILD_ID},
|
||||||
|
{"pdb", required_argument, NULL, OPTION_PDB},
|
||||||
{"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
|
{"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
|
||||||
{"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION},
|
{"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION},
|
||||||
{NULL, no_argument, NULL, 0}
|
{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-]wdmdriver Driver uses the WDM model\n"));
|
||||||
fprintf (file, _(" --[disable-]tsaware Image is Terminal Server aware\n"));
|
fprintf (file, _(" --[disable-]tsaware Image is Terminal Server aware\n"));
|
||||||
fprintf (file, _(" --build-id[=STYLE] Generate build ID\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
|
/* 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"))
|
if (strcmp (optarg, "none"))
|
||||||
emit_build_id = xstrdup (optarg);
|
emit_build_id = xstrdup (optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPTION_PDB:
|
||||||
|
pdb = 1;
|
||||||
|
if (optarg && optarg[0])
|
||||||
|
pdb_name = xstrdup (optarg);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set DLLCharacteristics bits */
|
/* Set DLLCharacteristics bits */
|
||||||
@ -1095,6 +1105,9 @@ gld${EMULATION_NAME}_after_parse (void)
|
|||||||
einfo (_("%P: warning: --export-dynamic is not supported for PE "
|
einfo (_("%P: warning: --export-dynamic is not supported for PE "
|
||||||
"targets, did you mean --export-all-symbols?\n"));
|
"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 ();
|
set_entry_point ();
|
||||||
|
|
||||||
after_parse_default ();
|
after_parse_default ();
|
||||||
@ -1274,6 +1287,7 @@ write_build_id (bfd *abfd)
|
|||||||
bfd_size_type size;
|
bfd_size_type size;
|
||||||
bfd_size_type build_id_size;
|
bfd_size_type build_id_size;
|
||||||
unsigned char *build_id;
|
unsigned char *build_id;
|
||||||
|
const char *pdb_base_name = NULL;
|
||||||
|
|
||||||
/* Find the section the .buildid output section has been merged info. */
|
/* Find the section the .buildid output section has been merged info. */
|
||||||
for (asec = abfd->sections; asec != NULL; asec = asec->next)
|
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;
|
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. */
|
/* Construct a debug directory entry which points to an immediately following CodeView record. */
|
||||||
struct internal_IMAGE_DEBUG_DIRECTORY idd;
|
struct internal_IMAGE_DEBUG_DIRECTORY idd;
|
||||||
idd.Characteristics = 0;
|
idd.Characteristics = 0;
|
||||||
@ -1320,7 +1337,7 @@ write_build_id (bfd *abfd)
|
|||||||
idd.MajorVersion = 0;
|
idd.MajorVersion = 0;
|
||||||
idd.MinorVersion = 0;
|
idd.MinorVersion = 0;
|
||||||
idd.Type = PE_IMAGE_DEBUG_TYPE_CODEVIEW;
|
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
|
idd.AddressOfRawData = asec->vma - ib + link_order->offset
|
||||||
+ sizeof (struct external_IMAGE_DEBUG_DIRECTORY);
|
+ sizeof (struct external_IMAGE_DEBUG_DIRECTORY);
|
||||||
idd.PointerToRawData = asec->filepos + link_order->offset
|
idd.PointerToRawData = asec->filepos + link_order->offset
|
||||||
@ -1349,7 +1366,8 @@ write_build_id (bfd *abfd)
|
|||||||
free (build_id);
|
free (build_id);
|
||||||
|
|
||||||
/* Write the codeview record. */
|
/* 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;
|
return 0;
|
||||||
|
|
||||||
/* Record the location of the debug directory in the data directory. */
|
/* 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:
|
/* Section is a fixed size:
|
||||||
One IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW,
|
One IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW,
|
||||||
pointing at a CV_INFO_PDB70 record containing the build-id, with a
|
pointing at a CV_INFO_PDB70 record containing the build-id, followed by
|
||||||
null byte for PdbFileName. */
|
PdbFileName if relevant. */
|
||||||
s->size = sizeof (struct external_IMAGE_DEBUG_DIRECTORY)
|
s->size = sizeof (struct external_IMAGE_DEBUG_DIRECTORY)
|
||||||
+ sizeof (CV_INFO_PDB70) + 1;
|
+ sizeof (CV_INFO_PDB70) + 1;
|
||||||
|
|
||||||
|
if (pdb_name)
|
||||||
|
s->size += strlen (pdb_name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1421,6 +1442,25 @@ gld${EMULATION_NAME}_after_open (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (emit_build_id != NULL)
|
||||||
{
|
{
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
|
@ -165,6 +165,8 @@ static lang_assignment_statement_type *image_base_statement = 0;
|
|||||||
static unsigned short pe_dll_characteristics = DEFAULT_DLL_CHARACTERISTICS;
|
static unsigned short pe_dll_characteristics = DEFAULT_DLL_CHARACTERISTICS;
|
||||||
static bool insert_timestamp = true;
|
static bool insert_timestamp = true;
|
||||||
static const char *emit_build_id;
|
static const char *emit_build_id;
|
||||||
|
static int pdb;
|
||||||
|
static char *pdb_name;
|
||||||
|
|
||||||
#ifdef DLL_SUPPORT
|
#ifdef DLL_SUPPORT
|
||||||
static int pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default). */
|
static int pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default). */
|
||||||
@ -281,6 +283,7 @@ enum options
|
|||||||
OPTION_NO_INSERT_TIMESTAMP,
|
OPTION_NO_INSERT_TIMESTAMP,
|
||||||
OPTION_TERMINAL_SERVER_AWARE,
|
OPTION_TERMINAL_SERVER_AWARE,
|
||||||
OPTION_BUILD_ID,
|
OPTION_BUILD_ID,
|
||||||
|
OPTION_PDB,
|
||||||
OPTION_ENABLE_RELOC_SECTION,
|
OPTION_ENABLE_RELOC_SECTION,
|
||||||
OPTION_DISABLE_RELOC_SECTION,
|
OPTION_DISABLE_RELOC_SECTION,
|
||||||
OPTION_DISABLE_HIGH_ENTROPY_VA,
|
OPTION_DISABLE_HIGH_ENTROPY_VA,
|
||||||
@ -369,6 +372,7 @@ gld${EMULATION_NAME}_add_options
|
|||||||
{"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP},
|
{"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP},
|
||||||
{"no-insert-timestamp", no_argument, NULL, OPTION_NO_INSERT_TIMESTAMP},
|
{"no-insert-timestamp", no_argument, NULL, OPTION_NO_INSERT_TIMESTAMP},
|
||||||
{"build-id", optional_argument, NULL, OPTION_BUILD_ID},
|
{"build-id", optional_argument, NULL, OPTION_BUILD_ID},
|
||||||
|
{"pdb", required_argument, NULL, OPTION_PDB},
|
||||||
{"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
|
{"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
|
||||||
{"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION},
|
{"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION},
|
||||||
{"disable-high-entropy-va", no_argument, NULL, OPTION_DISABLE_HIGH_ENTROPY_VA},
|
{"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-]wdmdriver Driver uses the WDM model\n"));
|
||||||
fprintf (file, _(" --[disable-]tsaware Image is Terminal Server aware\n"));
|
fprintf (file, _(" --[disable-]tsaware Image is Terminal Server aware\n"));
|
||||||
fprintf (file, _(" --build-id[=STYLE] Generate build ID\n"));
|
fprintf (file, _(" --build-id[=STYLE] Generate build ID\n"));
|
||||||
|
fprintf (file, _(" --pdb=[FILENAME] Generate PDB file\n"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -924,6 +929,11 @@ gld${EMULATION_NAME}_handle_option (int optc)
|
|||||||
if (strcmp (optarg, "none"))
|
if (strcmp (optarg, "none"))
|
||||||
emit_build_id = xstrdup (optarg);
|
emit_build_id = xstrdup (optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPTION_PDB:
|
||||||
|
pdb = 1;
|
||||||
|
if (optarg && optarg[0])
|
||||||
|
pdb_name = xstrdup (optarg);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set DLLCharacteristics bits */
|
/* Set DLLCharacteristics bits */
|
||||||
@ -1046,6 +1056,9 @@ gld${EMULATION_NAME}_after_parse (void)
|
|||||||
einfo (_("%P: warning: --export-dynamic is not supported for PE+ "
|
einfo (_("%P: warning: --export-dynamic is not supported for PE+ "
|
||||||
"targets, did you mean --export-all-symbols?\n"));
|
"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 ();
|
set_entry_point ();
|
||||||
|
|
||||||
after_parse_default ();
|
after_parse_default ();
|
||||||
@ -1266,6 +1279,7 @@ write_build_id (bfd *abfd)
|
|||||||
bfd_size_type size;
|
bfd_size_type size;
|
||||||
bfd_size_type build_id_size;
|
bfd_size_type build_id_size;
|
||||||
unsigned char *build_id;
|
unsigned char *build_id;
|
||||||
|
const char *pdb_base_name = NULL;
|
||||||
|
|
||||||
/* Find the section the .buildid output section has been merged info. */
|
/* Find the section the .buildid output section has been merged info. */
|
||||||
for (asec = abfd->sections; asec != NULL; asec = asec->next)
|
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;
|
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. */
|
/* Construct a debug directory entry which points to an immediately following CodeView record. */
|
||||||
struct internal_IMAGE_DEBUG_DIRECTORY idd;
|
struct internal_IMAGE_DEBUG_DIRECTORY idd;
|
||||||
idd.Characteristics = 0;
|
idd.Characteristics = 0;
|
||||||
@ -1312,7 +1329,7 @@ write_build_id (bfd *abfd)
|
|||||||
idd.MajorVersion = 0;
|
idd.MajorVersion = 0;
|
||||||
idd.MinorVersion = 0;
|
idd.MinorVersion = 0;
|
||||||
idd.Type = PE_IMAGE_DEBUG_TYPE_CODEVIEW;
|
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
|
idd.AddressOfRawData = asec->vma - ib + link_order->offset
|
||||||
+ sizeof (struct external_IMAGE_DEBUG_DIRECTORY);
|
+ sizeof (struct external_IMAGE_DEBUG_DIRECTORY);
|
||||||
idd.PointerToRawData = asec->filepos + link_order->offset
|
idd.PointerToRawData = asec->filepos + link_order->offset
|
||||||
@ -1341,7 +1358,8 @@ write_build_id (bfd *abfd)
|
|||||||
free (build_id);
|
free (build_id);
|
||||||
|
|
||||||
/* Write the codeview record. */
|
/* 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;
|
return 0;
|
||||||
|
|
||||||
/* Record the location of the debug directory in the data directory. */
|
/* 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:
|
/* Section is a fixed size:
|
||||||
One IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW,
|
One IMAGE_DEBUG_DIRECTORY entry, of type IMAGE_DEBUG_TYPE_CODEVIEW,
|
||||||
pointing at a CV_INFO_PDB70 record containing the build-id, with a
|
pointing at a CV_INFO_PDB70 record containing the build-id, followed by
|
||||||
null byte for PdbFileName. */
|
PdbFileName if relevant. */
|
||||||
s->size = sizeof (struct external_IMAGE_DEBUG_DIRECTORY)
|
s->size = sizeof (struct external_IMAGE_DEBUG_DIRECTORY)
|
||||||
+ sizeof (CV_INFO_PDB70) + 1;
|
+ sizeof (CV_INFO_PDB70) + 1;
|
||||||
|
|
||||||
|
if (pdb_name)
|
||||||
|
s->size += strlen (pdb_name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1414,6 +1435,25 @@ gld${EMULATION_NAME}_after_open (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (emit_build_id != NULL)
|
||||||
{
|
{
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
|
53
ld/testsuite/ld-pe/pdb.exp
Normal file
53
ld/testsuite/ld-pe/pdb.exp
Normal file
@ -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"
|
5
ld/testsuite/ld-pe/pdb1.s
Normal file
5
ld/testsuite/ld-pe/pdb1.s
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.text
|
||||||
|
|
||||||
|
.global foo
|
||||||
|
foo:
|
||||||
|
.long 0x12345678
|
Reference in New Issue
Block a user