From patchwork Thu Nov 3 02:46:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Harmstone X-Patchwork-Id: 14602 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp277604wru; Wed, 2 Nov 2022 19:46:50 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6QmcnTO63ABBJeG546hA/SF7WnZh8bdCsn6mW39YMNEvNT+oqpOPXXEqgRDdNeSCa1Btpd X-Received: by 2002:a05:6402:1d4e:b0:461:c7bd:7d9c with SMTP id dz14-20020a0564021d4e00b00461c7bd7d9cmr27564354edb.284.1667443610647; Wed, 02 Nov 2022 19:46:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667443610; cv=none; d=google.com; s=arc-20160816; b=Nb84KKFmVBSSolj7IK6WuQSpO/bl2CDQ5L4qRIlWTxcccP4Td+MJK/QLdRTj5vgRpu uFmdODQeXm0AhokeBoHLHabrLphaYf7R9gNSC5E7AuVtaKpRfGqMAuUhQ0mlrgmdqWki /c+SrGBo0ZF3qmgd6IXKQr+x4F6fhJkwNmm2naO4RC8ZMP5WbpGG5JwDCGbBzpltZO2j /EtXTOOauhQMCqUC3ZOjEYHH9GAlyiSyF37y0mkJuX4M+BIvTRQWCWDCHQmAm9l6vwfu 5fmjic3RtyRPy4os1Hg94cQH8/e5bUiqe/OQG66bEqGuzMz1OKUIivpYXRPIcMOezUsG Cd/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:to:from:dkim-signature :dmarc-filter:delivered-to; bh=ZT/AM/x2OD9oJt8AXTAOXClKqs3/UXtfBZRtoB50asY=; b=XP5EGKM95uDWe4OvIEH7owzdRMCZWmB9iYpHn905TzuWbpijuQivGtHNZMB5iHLFGR MX452ctzn1/gqUKn0wsrL3yFmVV12qWo94b1s1KkuwzL/ZLMAprKDP29idFJrIAN3wZs ien9gUE/GoWv8WVUuIF/7l/40xIcK46cOoncJTTQ4jGeS5opAdxaCqbAXkMEnq6UnO/o GrAIiE9K9Y3B6lBBJmBwjBDleoyYGGG6HHLXSkcaEQlsvCtIq9a9w7MbLjnYgXoM4vWO xbKRSAIKxO14aqf/W7u2CJps8XZtrAriSg4JI+AzeUxhmiBlGUXYiq8y3jOZJETtwF3b EDmQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20210112 header.b=TWekcXJl; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id be7-20020a1709070a4700b00781dbee4273si19703614ejc.514.2022.11.02.19.46.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Nov 2022 19:46:50 -0700 (PDT) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=fail header.i=@gmail.com header.s=20210112 header.b=TWekcXJl; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E1DBD385696A for ; Thu, 3 Nov 2022 02:46:20 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 62EC43857356 for ; Thu, 3 Nov 2022 02:46:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 62EC43857356 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-wr1-x42e.google.com with SMTP id w14so748534wru.8 for ; Wed, 02 Nov 2022 19:46:12 -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=ZT/AM/x2OD9oJt8AXTAOXClKqs3/UXtfBZRtoB50asY=; b=TWekcXJl70cZ5hTD3MqeCnX5/xIQCMV14TXCRVtZFiMYi9ZamdxgPzWiOBH0o/74Lu TZs8pV3BHiiFyPJ5eNEEUPcgnsgB6bHh4SOze4rZkWt0oCe2twuxdHObIh98qa33XBpp 0tB1s+y3XnOyFq9Ux5XQXRlAvrrVmuxY7FrvN9EjKQqn6wW3tN8e/2nu821x57njCf9W 96L/264muh/4cM9ckNVVxHRkmedhQ4imqNx5RFB4NWtkAwNgmYluFdoCSXR8NmRzzTq8 +eW9hRZD26GUL0ZBveW6eTfOgoup052XHqTVauGBN0LSWIVSOKGIzZ05MfebBlZT62gl xRxA== 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=ZT/AM/x2OD9oJt8AXTAOXClKqs3/UXtfBZRtoB50asY=; b=G1gItfeTH55gHikpES37c1mfHkLoLp15cgFr4QyRBDYdaMkiIeq+XfjO0GGlGGJ7Si cmNzD6KWsuc57OHU0m+B4bGTRGi5rntAbHuIdY52v6Ftz5Xy1ZDvtRnFZkIjYN5TUhBe k27G7bjtNpSoltf3evdtquCQw4e3Uouk47DGpKR+DQH0FQpBGr3FlayzF+4LHEkTWQoy sJ2lzG6aWXSci0g684lAiBzh+5k44TMZL2R+iHmk0SSR8Io4tHm1hemRN8sqpjfoOfpM T5Da3Y4nRhZbPMRfDQua0A5cMRk5upY+jG4jBcxibT7q4iJLDWTS76HnwKUn0kSzxQLI WdMg== X-Gm-Message-State: ACrzQf12DBRNMy+0jLQWqn9yG+BI2y0hDnisGqCqT/wlUZd6CGmq0ObE 3tZOZapQPXwmY3yAb85EX02o1hW5HuI= X-Received: by 2002:a5d:6d02:0:b0:236:ed2d:b3eb with SMTP id e2-20020a5d6d02000000b00236ed2db3ebmr4890918wrq.456.1667443570832; Wed, 02 Nov 2022 19:46:10 -0700 (PDT) Received: from beren.harmstone.com ([2a02:8010:64ea:0:8eb8:7eff:fe53:9d5f]) by smtp.gmail.com with ESMTPSA id n15-20020a5d420f000000b0022da3977ec5sm13918019wrq.113.2022.11.02.19.46.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Nov 2022 19:46:10 -0700 (PDT) From: Mark Harmstone To: binutils@sourceware.org Subject: [PATCH v2] ld: Add module information substream to PDB files Date: Thu, 3 Nov 2022 02:46:04 +0000 Message-Id: <20221103024604.614-1-mark@harmstone.com> X-Mailer: git-send-email 2.37.4 MIME-Version: 1.0 X-Spam-Status: No, score=-11.4 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 X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Harmstone Errors-To: binutils-bounces+ouuuleilei=gmail.com@sourceware.org Sender: "Binutils" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748348319097760382?= X-GMAIL-MSGID: =?utf-8?q?1748441351524363340?= Resubmission taking into account https://sourceware.org/pipermail/binutils/2022-November/124128.html. --- ld/pdb.c | 214 ++++++++++++++++++++++++++++++++++++- ld/pdb.h | 33 ++++++ ld/testsuite/ld-pe/pdb.exp | 214 ++++++++++++++++++++++++++++++------- ld/testsuite/ld-pe/pdb2a.s | 5 + ld/testsuite/ld-pe/pdb2b.s | 5 + 5 files changed, 427 insertions(+), 44 deletions(-) create mode 100644 ld/testsuite/ld-pe/pdb2a.s create mode 100644 ld/testsuite/ld-pe/pdb2b.s diff --git a/ld/pdb.c b/ld/pdb.c index a2cdb84e271..b560c13198a 100644 --- a/ld/pdb.c +++ b/ld/pdb.c @@ -383,6 +383,196 @@ get_arch_number (bfd *abfd) return IMAGE_FILE_MACHINE_I386; } +/* Populate the module stream, which consists of the transformed .debug$S + data for each object file. */ +static bool +populate_module_stream (bfd *stream, uint32_t *sym_byte_size) +{ + uint8_t int_buf[sizeof (uint32_t)]; + + *sym_byte_size = sizeof (uint32_t); + + /* Write the signature. */ + + bfd_putl32 (CV_SIGNATURE_C13, int_buf); + + if (bfd_bwrite (int_buf, sizeof (uint32_t), stream) != sizeof (uint32_t)) + return false; + + /* Write the global refs size. */ + + bfd_putl32 (0, int_buf); + + if (bfd_bwrite (int_buf, sizeof (uint32_t), stream) != sizeof (uint32_t)) + return false; + + return true; +} + +/* Create the module info substream within the DBI. */ +static bool +create_module_info_substream (bfd *abfd, bfd *pdb, void **data, + uint32_t *size) +{ + uint8_t *ptr; + + static const char linker_fn[] = "* Linker *"; + + *size = 0; + + for (bfd *in = coff_data (abfd)->link_info->input_bfds; in; + in = in->link.next) + { + size_t len = sizeof (struct module_info); + + if (!strcmp (bfd_get_filename (in), "dll stuff")) + { + len += sizeof (linker_fn); /* Object name. */ + len++; /* Empty module name. */ + } + else if (in->my_archive) + { + char *name = lrealpath (bfd_get_filename (in)); + + len += strlen (name) + 1; /* Object name. */ + + free (name); + + name = lrealpath (bfd_get_filename (in->my_archive)); + + len += strlen (name) + 1; /* Archive name. */ + + free (name); + } + else + { + char *name = lrealpath (bfd_get_filename (in)); + size_t name_len = strlen (name) + 1; + + len += name_len; /* Object name. */ + len += name_len; /* And again as the archive name. */ + + free (name); + } + + if (len % 4) + len += 4 - (len % 4); + + *size += len; + } + + *data = xmalloc (*size); + + ptr = *data; + + for (bfd *in = coff_data (abfd)->link_info->input_bfds; in; + in = in->link.next) + { + struct module_info *mod = (struct module_info *) ptr; + uint16_t stream_num; + bfd *stream; + uint32_t sym_byte_size; + uint8_t *start = ptr; + + stream = add_stream (pdb, NULL, &stream_num); + + if (!stream) + { + free (*data); + return false; + } + + if (!populate_module_stream (stream, &sym_byte_size)) + { + free (*data); + return false; + } + + bfd_putl32 (0, &mod->unused1); + + /* These are dummy values - MSVC copies the first section contribution + entry here, but doesn't seem to use it for anything. */ + bfd_putl16 (0xffff, &mod->sc.section); + bfd_putl16 (0, &mod->sc.padding1); + bfd_putl32 (0, &mod->sc.offset); + bfd_putl32 (0xffffffff, &mod->sc.size); + bfd_putl32 (0, &mod->sc.characteristics); + bfd_putl16 (0xffff, &mod->sc.module_index); + bfd_putl16 (0, &mod->sc.padding2); + bfd_putl32 (0, &mod->sc.data_crc); + bfd_putl32 (0, &mod->sc.reloc_crc); + + bfd_putl16 (0, &mod->flags); + bfd_putl16 (stream_num, &mod->module_sym_stream); + bfd_putl32 (sym_byte_size, &mod->sym_byte_size); + bfd_putl32 (0, &mod->c11_byte_size); + bfd_putl32 (0, &mod->c13_byte_size); + bfd_putl16 (0, &mod->source_file_count); + bfd_putl16 (0, &mod->padding); + bfd_putl32 (0, &mod->unused2); + bfd_putl32 (0, &mod->source_file_name_index); + bfd_putl32 (0, &mod->pdb_file_path_name_index); + + ptr += sizeof (struct module_info); + + if (!strcmp (bfd_get_filename (in), "dll stuff")) + { + /* Object name. */ + memcpy (ptr, linker_fn, sizeof (linker_fn)); + ptr += sizeof (linker_fn); + + /* Empty module name. */ + *ptr = 0; + ptr++; + } + else if (in->my_archive) + { + char *name = lrealpath (bfd_get_filename (in)); + size_t name_len = strlen (name) + 1; + + /* Object name. */ + memcpy (ptr, name, name_len); + ptr += name_len; + + free (name); + + name = lrealpath (bfd_get_filename (in->my_archive)); + name_len = strlen (name) + 1; + + /* Archive name. */ + memcpy (ptr, name, name_len); + ptr += name_len; + + free (name); + } + else + { + char *name = lrealpath (bfd_get_filename (in)); + size_t name_len = strlen (name) + 1; + + /* Object name. */ + memcpy (ptr, name, name_len); + ptr += name_len; + + /* Object name again as archive name. */ + memcpy (ptr, name, name_len); + ptr += name_len; + + free (name); + } + + /* Pad to next four-byte boundary. */ + + if ((ptr - start) % 4) + { + memset (ptr, 0, 4 - ((ptr - start) % 4)); + ptr += 4 - ((ptr - start) % 4); + } + } + + return true; +} + /* Return the index of a given output section. */ static uint16_t find_section_number (bfd *abfd, asection *sect) @@ -404,13 +594,18 @@ find_section_number (bfd *abfd, asection *sect) /* Stream 4 is the debug information (DBI) stream. */ static bool -populate_dbi_stream (bfd *stream, bfd *abfd, +populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb, uint16_t section_header_stream_num, uint16_t sym_rec_stream_num, uint16_t publics_stream_num) { struct pdb_dbi_stream_header h; struct optional_dbg_header opt; + void *mod_info; + uint32_t mod_info_size; + + if (!create_module_info_substream (abfd, pdb, &mod_info, &mod_info_size)) + return false; bfd_putl32 (0xffffffff, &h.version_signature); bfd_putl32 (DBI_STREAM_VERSION_70, &h.version_header); @@ -421,7 +616,7 @@ populate_dbi_stream (bfd *stream, bfd *abfd, bfd_putl16 (0, &h.pdb_dll_version); bfd_putl16 (sym_rec_stream_num, &h.sym_record_stream); bfd_putl16 (0, &h.pdb_dll_rbld); - bfd_putl32 (0, &h.mod_info_size); + bfd_putl32 (mod_info_size, &h.mod_info_size); bfd_putl32 (0, &h.section_contribution_size); bfd_putl32 (0, &h.section_map_size); bfd_putl32 (0, &h.source_info_size); @@ -434,7 +629,18 @@ populate_dbi_stream (bfd *stream, bfd *abfd, bfd_putl32 (0, &h.padding); if (bfd_bwrite (&h, sizeof (h), stream) != sizeof (h)) - return false; + { + free (mod_info); + return false; + } + + if (bfd_bwrite (mod_info, mod_info_size, stream) != mod_info_size) + { + free (mod_info); + return false; + } + + free (mod_info); bfd_putl16 (0xffff, &opt.fpo_stream); bfd_putl16 (0xffff, &opt.exception_stream); @@ -888,7 +1094,7 @@ create_pdb_file (bfd *abfd, const char *pdb_name, const unsigned char *guid) goto end; } - if (!populate_dbi_stream (dbi_stream, abfd, section_header_stream_num, + if (!populate_dbi_stream (dbi_stream, abfd, pdb, section_header_stream_num, sym_rec_stream_num, publics_stream_num)) { einfo (_("%P: warning: cannot populate DBI stream " diff --git a/ld/pdb.h b/ld/pdb.h index 1a80101d288..a44618578b7 100644 --- a/ld/pdb.h +++ b/ld/pdb.h @@ -153,6 +153,39 @@ struct optional_dbg_header uint16_t orig_section_header_stream; }; +#define CV_SIGNATURE_C13 4 + +/* SC in dbicommon.h */ +struct section_contribution +{ + uint16_t section; + uint16_t padding1; + uint32_t offset; + uint32_t size; + uint32_t characteristics; + uint16_t module_index; + uint16_t padding2; + uint32_t data_crc; + uint32_t reloc_crc; +}; + +/* MODI_60_Persist in dbi.h */ +struct module_info +{ + uint32_t unused1; + struct section_contribution sc; + uint16_t flags; + uint16_t module_sym_stream; + uint32_t sym_byte_size; + uint32_t c11_byte_size; + uint32_t c13_byte_size; + uint16_t source_file_count; + uint16_t padding; + uint32_t unused2; + uint32_t source_file_name_index; + uint32_t pdb_file_path_name_index; +}; + extern bool create_pdb_file (bfd *, const char *, const unsigned char *); #endif diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp index ee314c41f9b..ab22506d0f2 100644 --- a/ld/testsuite/ld-pe/pdb.exp +++ b/ld/testsuite/ld-pe/pdb.exp @@ -494,55 +494,189 @@ proc check_publics_stream { pdb } { return 1 } -if ![ld_assemble $as $srcdir/$subdir/pdb1.s tmpdir/pdb1.o] { - unsupported "Build pdb1.o" - return -} +proc test1 { } { + global as + global ld + global srcdir + global subdir -if ![ld_link $ld "tmpdir/pdb1.exe" "--pdb=tmpdir/pdb1.pdb --gc-sections -e foo tmpdir/pdb1.o"] { - fail "Could not create a PE image with a PDB file" - return -} + if ![ld_assemble $as $srcdir/$subdir/pdb1.s tmpdir/pdb1.o] { + unsupported "Build pdb1.o" + return + } -if ![string equal [get_pdb_name "tmpdir/pdb1.exe"] "pdb1.pdb"] { - fail "PDB filename not found in CodeView debug info" - return -} + if ![ld_link $ld "tmpdir/pdb1.exe" "--pdb=tmpdir/pdb1.pdb --gc-sections -e foo tmpdir/pdb1.o"] { + fail "Could not create a PE image with a PDB file" + return + } -pass "PDB filename present in CodeView debug info" + if ![string equal [get_pdb_name "tmpdir/pdb1.exe"] "pdb1.pdb"] { + fail "PDB filename not found in CodeView debug info" + return + } -if [check_pdb_info_stream tmpdir/pdb1.pdb [get_pdb_guid "tmpdir/pdb1.exe"]] { - pass "Valid PDB info stream" -} else { - fail "Invalid PDB info stream" -} + pass "PDB filename present in CodeView debug info" -if [check_type_stream tmpdir/pdb1.pdb "0002"] { - pass "Valid TPI stream" -} else { - fail "Invalid TPI stream" -} + if [check_pdb_info_stream tmpdir/pdb1.pdb [get_pdb_guid "tmpdir/pdb1.exe"]] { + pass "Valid PDB info stream" + } else { + fail "Invalid PDB info stream" + } -if [check_type_stream tmpdir/pdb1.pdb "0004"] { - pass "Valid IPI stream" -} else { - fail "Invalid IPI stream" -} + if [check_type_stream tmpdir/pdb1.pdb "0002"] { + pass "Valid TPI stream" + } else { + fail "Invalid TPI stream" + } + + if [check_type_stream tmpdir/pdb1.pdb "0004"] { + pass "Valid IPI stream" + } else { + fail "Invalid IPI stream" + } + + if [check_dbi_stream tmpdir/pdb1.pdb] { + pass "Valid DBI stream" + } else { + fail "Invalid DBI stream" + } -if [check_dbi_stream tmpdir/pdb1.pdb] { - pass "Valid DBI stream" -} else { - fail "Invalid DBI stream" + if [check_section_stream tmpdir/pdb1.exe tmpdir/pdb1.pdb] { + pass "Valid section stream" + } else { + fail "Invalid section stream" + } + + if [check_publics_stream tmpdir/pdb1.pdb] { + pass "Valid publics stream" + } else { + fail "Invalid publics stream" + } } -if [check_section_stream tmpdir/pdb1.exe tmpdir/pdb1.pdb] { - pass "Valid section stream" -} else { - fail "Invalid section stream" +proc test_mod_info { mod_info } { + # check filenames in mod_info + + set off 64 + + set obj1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]] + incr off [expr [string length $obj1] + 1] + + set ar1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]] + incr off [expr [string length $ar1] + 1] + + if [string match "*pdb2a.o" $obj1] { + pass "Correct name for first object file" + } else { + fail "Incorrect name for first object file" + } + + if [string equal $obj1 $ar1] { + pass "Correct archive name for first object file" + } else { + fail "Incorrect archive name for first object file" + } + + if { [expr $off % 4] != 0 } { + set off [expr $off + 4 - ($off % 4)] + } + + incr off 64 + + set obj2 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]] + incr off [expr [string length $obj2] + 1] + + set ar2 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]] + incr off [expr [string length $ar2] + 1] + + if [string match "*pdb2b.o" $obj2] { + pass "Correct name for second object file" + } else { + fail "Incorrect name for second object file" + } + + if [string match "*pdb2b.a" $ar2] { + pass "Correct archive name for second object file" + } else { + fail "Incorrect archive name for second object file" + } + + if { [expr $off % 4] != 0 } { + set off [expr $off + 4 - ($off % 4)] + } + + incr off 64 + + set obj3 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]] + incr off [expr [string length $obj3] + 1] + + set ar3 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]] + incr off [expr [string length $ar3] + 1] + + if [string equal $obj3 "* Linker *"] { + pass "Correct name for dummy object file" + } else { + fail "Incorrect name for dummy object file" + } + + if [string equal $ar3 ""] { + pass "Correct archive name for dummy object file" + } else { + fail "Incorrect archive name for dummy object file" + } } -if [check_publics_stream tmpdir/pdb1.pdb] { - pass "Valid publics stream" -} else { - fail "Invalid publics stream" +proc test2 { } { + global as + global ar + global ld + global srcdir + global subdir + + if ![ld_assemble $as $srcdir/$subdir/pdb2a.s tmpdir/pdb2a.o] { + unsupported "Build pdb2a.o" + return + } + + if ![ld_assemble $as $srcdir/$subdir/pdb2b.s tmpdir/pdb2b.o] { + unsupported "Build pdb2b.o" + return + } + + set exec_output [run_host_cmd "$ar" "cr tmpdir/pdb2b.a tmpdir/pdb2b.o"] + + if ![string match "" $exec_output] { + unsupported "Create pdb2b.a" + return + } + + if ![ld_link $ld "tmpdir/pdb2.exe" "--pdb=tmpdir/pdb2.pdb -e foo tmpdir/pdb2a.o tmpdir/pdb2b.a"] { + unsupported "Create PE image with PDB file" + return + } + + set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb2.pdb 0003"] + + if ![string match "" $exec_output] { + return 0 + } + + set fi [open tmpdir/0003] + fconfigure $fi -translation binary + + seek $fi 24 + + set data [read $fi 4] + binary scan $data i mod_info_size + + seek $fi 36 current + + set mod_info [read $fi $mod_info_size] + + close $fi + + test_mod_info $mod_info } + +test1 +test2 diff --git a/ld/testsuite/ld-pe/pdb2a.s b/ld/testsuite/ld-pe/pdb2a.s new file mode 100644 index 00000000000..414edeb2eec --- /dev/null +++ b/ld/testsuite/ld-pe/pdb2a.s @@ -0,0 +1,5 @@ +.text + +.global foo +foo: + .secrel32 bar diff --git a/ld/testsuite/ld-pe/pdb2b.s b/ld/testsuite/ld-pe/pdb2b.s new file mode 100644 index 00000000000..64010237975 --- /dev/null +++ b/ld/testsuite/ld-pe/pdb2b.s @@ -0,0 +1,5 @@ +.text + +.global bar +bar: + .long 0x12345678