From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by sourceware.org (Postfix) with ESMTPS id BB7A3384B13A for ; Thu, 27 Oct 2022 19:01:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org BB7A3384B13A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=harmstone.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-x332.google.com with SMTP id m29-20020a05600c3b1d00b003c6bf423c71so4886717wms.0 for ; Thu, 27 Oct 2022 12:01:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:sender:from:to:cc:subject:date:message-id:reply-to; bh=pCjvzwlgO/oKkaz16fk1iSJ3hiMZoNTY2uT4hRNpffI=; b=RACN6xPtUmqxOFP+x3sv1N8guYYEuznoJ30A0z4mOL0rCJUSwNVdul2Lf8Bu5gXdcx +MJBQGiIpz/9XR4B5X4lakoVGX3K9Fdj19J3pzUiaA17wtIhBYtIx6gS1kLkXqeLHZud 5WsWzabUsFx8U3qYqbwv/TEDpgEmXf0uKVbjHxDtyxzHviQmFDvkenUrFTvVjmIVVZqf aQgNjkki0mpd+vNrwHZFXTnoF34DA9bkbLFIDdF9qQLJozS0eOc2JTUhpGixLo3YbyXU U2xjJuGEbz0rV683BDaaWK3FdF1MCqeaC7zL04JNFG8nLBAkZsHvXT2F4jbO58GOflqc Vvkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:sender:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=pCjvzwlgO/oKkaz16fk1iSJ3hiMZoNTY2uT4hRNpffI=; b=WMLxIBsQCQ+/icOiSq4Tn4pD3ZkN9nGLUSPMZsKQ1wS2J420LKilNP9amHk4FK8xAt AU7tAqQeHpUtzpydfy0GY0AAXVXguhaT49fVQYrB4PtbdSIg0Vvk6rolO6x5isOrqB4a ThGoBTDEHc94RuWc0zBCH0nPKvBquUFUSb1fcnb/o9c9v+yXNxwTUzZq0qjziEjY5e6u ryiNP/1KBeKeqBYzn2mBRHgFJvGSYidpoigQXz5sQ2ztmNBPLoY9KlWz228C2LlRVqRH lzxuCHN2Nm6Y28UI4iWCE+HxJ2ZjK6iYH11oAfLef5WxlaA8ewo2BxhIw4NL+9LC3ga1 DEFw== X-Gm-Message-State: ACrzQf3QuMnSZze+BjiotAAdh8Qk8qMf8BTlqUQEeiF1h2MR4IH4b1PK V/QgvCa7IPCJgZ/Vlr/IMrm2Vp+nvfw= X-Google-Smtp-Source: AMsMyM704SG+8j7UNnQDZoZ29AV2fYh3mPbvELPEnKa8L3rlCJkkBqZqgseJdt3+mmPCcs0bulbBkg== X-Received: by 2002:a05:600c:6019:b0:3c6:e21e:4e9d with SMTP id az25-20020a05600c601900b003c6e21e4e9dmr7010745wmb.53.1666897278995; Thu, 27 Oct 2022 12:01:18 -0700 (PDT) Received: from beren.harmstone.com ([2a02:8010:64ea:0:8eb8:7eff:fe53:9d5f]) by smtp.gmail.com with ESMTPSA id d1-20020adfe2c1000000b002366eb01e07sm1740199wrj.114.2022.10.27.12.01.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Oct 2022 12:01:18 -0700 (PDT) Sender: Mark Harmstone From: Mark Harmstone To: binutils@sourceware.org Cc: Mark Harmstone Subject: [PATCH 1/2] ld: Add section header stream to PDB files Date: Thu, 27 Oct 2022 20:00:51 +0100 Message-Id: <20221027190052.10536-1-mark@harmstone.com> X-Mailer: git-send-email 2.37.4 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,GIT_PATCH_0,HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: These patches add S_PUB32 records to PDB files, allowing Microsoft debuggers to resolve mangled symbol names. --- ld/pdb.c | 69 ++++++++++++++++++++- ld/testsuite/ld-pe/pdb.exp | 123 +++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 3 deletions(-) diff --git a/ld/pdb.c b/ld/pdb.c index 3452e2cbe5b..a82370701e8 100644 --- a/ld/pdb.c +++ b/ld/pdb.c @@ -385,7 +385,8 @@ get_arch_number (bfd *abfd) /* Stream 4 is the debug information (DBI) stream. */ static bool -populate_dbi_stream (bfd *stream, bfd *abfd) +populate_dbi_stream (bfd *stream, bfd *abfd, + uint16_t section_header_stream_num) { struct pdb_dbi_stream_header h; struct optional_dbg_header opt; @@ -419,7 +420,7 @@ populate_dbi_stream (bfd *stream, bfd *abfd) bfd_putl16 (0xffff, &opt.fixup_stream); bfd_putl16 (0xffff, &opt.omap_to_src_stream); bfd_putl16 (0xffff, &opt.omap_from_src_stream); - bfd_putl16 (0xffff, &opt.section_header_stream); + bfd_putl16 (section_header_stream_num, &opt.section_header_stream); bfd_putl16 (0xffff, &opt.token_map_stream); bfd_putl16 (0xffff, &opt.xdata_stream); bfd_putl16 (0xffff, &opt.pdata_stream); @@ -432,6 +433,60 @@ populate_dbi_stream (bfd *stream, bfd *abfd) return true; } +/* The section header stream contains a copy of the section headers + from the PE file, in the same format. */ +static bool +create_section_header_stream (bfd *pdb, bfd *abfd, uint16_t *num) +{ + bfd *stream; + unsigned int section_count; + file_ptr scn_base; + size_t len; + char *buf; + + stream = add_stream (pdb, NULL, num); + if (!stream) + return false; + + section_count = abfd->section_count; + + /* Empty sections aren't output. */ + for (asection *sect = abfd->sections; sect; sect = sect->next) + { + if (sect->size == 0) + section_count--; + } + + if (section_count == 0) + return true; + + /* Copy section table from output - it's already been written at this + point. */ + + scn_base = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd); + + bfd_seek (abfd, scn_base, SEEK_SET); + + len = section_count * sizeof (struct external_scnhdr); + buf = xmalloc (len); + + if (bfd_bread (buf, len, abfd) != len) + { + free (buf); + return false; + } + + if (bfd_bwrite (buf, len, stream) != len) + { + free (buf); + return false; + } + + free (buf); + + return true; +} + /* Create a PDB debugging file for the PE image file abfd with the build ID guid, stored at pdb_name. */ bool @@ -440,6 +495,7 @@ create_pdb_file (bfd *abfd, const char *pdb_name, const unsigned char *guid) bfd *pdb; bool ret = false; bfd *info_stream, *dbi_stream, *names_stream; + uint16_t section_header_stream_num; pdb = bfd_openw (pdb_name, "pdb"); if (!pdb) @@ -499,7 +555,14 @@ create_pdb_file (bfd *abfd, const char *pdb_name, const unsigned char *guid) goto end; } - if (!populate_dbi_stream (dbi_stream, abfd)) + if (!create_section_header_stream (pdb, abfd, §ion_header_stream_num)) + { + einfo (_("%P: warning: cannot create section header stream " + "in PDB file: %s\n"), bfd_errmsg (bfd_get_error ())); + goto end; + } + + if (!populate_dbi_stream (dbi_stream, abfd, section_header_stream_num)) { einfo (_("%P: warning: cannot populate DBI stream " "in PDB file: %s\n"), bfd_errmsg (bfd_get_error ())); diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp index b62ce6da6f8..cee072187de 100644 --- a/ld/testsuite/ld-pe/pdb.exp +++ b/ld/testsuite/ld-pe/pdb.exp @@ -278,6 +278,123 @@ proc check_dbi_stream { pdb } { return 1 } +proc get_section_stream_index { pdb } { + global ar + + set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0003"] + + if ![string match "" $exec_output] { + return -1 + } + + set fi [open tmpdir/0003] + fconfigure $fi -translation binary + + # skip fields + seek $fi 24 + + # read substream sizes + + set data [read $fi 4] + binary scan $data i mod_info_size + + set data [read $fi 4] + binary scan $data i section_contribution_size + + set data [read $fi 4] + binary scan $data i section_map_size + + set data [read $fi 4] + binary scan $data i source_info_size + + set data [read $fi 4] + binary scan $data i type_server_map_size + + # skip type server index + seek $fi 4 current + + set data [read $fi 4] + binary scan $data i optional_dbg_header_size + + if { $optional_dbg_header_size < 12 } { + close $fi + return -1 + } + + # skip data + seek $fi [expr 12 + $mod_info_size + $section_contribution_size + $section_map_size + $source_info_size + $type_server_map_size + 10] current + + set data [read $fi 2] + binary scan $data s section_stream_index + + close $fi + + return $section_stream_index +} + +proc check_section_stream { img pdb } { + global ar + + # read sections stream + + set index [get_section_stream_index $pdb] + + if { $index == -1 } { + return 0 + } + + set index_str [format "%04x" $index] + + set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb $index_str"] + + if ![string match "" $exec_output] { + return 0 + } + + set stream_length [file size tmpdir/$index_str] + + set fi [open tmpdir/$index_str] + fconfigure $fi -translation binary + + set stream_data [read $fi $stream_length] + + close $fi + + # read sections from PE file + + set fi [open $img] + fconfigure $fi -translation binary + + # read PE offset + read $fi 0x3c + set data [read $fi 4] + binary scan $data i pe_offset + + # read number of sections + seek $fi [expr $pe_offset + 6] + set data [read $fi 2] + binary scan $data s num_sections + + # read size of optional header + seek $fi 12 current + set data [read $fi 2] + binary scan $data s opt_header_size + + # read section headers + seek $fi [expr $opt_header_size + 2] current + set section_data [read $fi [expr $num_sections * 40]] + + close $fi + + # compare + + if { $stream_data ne $section_data} { + return 0 + } + + return 1 +} + if ![ld_assemble $as $srcdir/$subdir/pdb1.s tmpdir/pdb1.o] { unsupported "Build pdb1.o" return @@ -318,3 +435,9 @@ if [check_dbi_stream tmpdir/pdb1.pdb] { } else { fail "Invalid DBI stream" } + +if [check_section_stream tmpdir/pdb1.exe tmpdir/pdb1.pdb] { + pass "Valid section stream" +} else { + fail "Invalid section stream" +} -- 2.37.4