From patchwork Tue Jun 18 00:17:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Harmstone X-Patchwork-Id: 1948905 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; secure) header.d=harmstone.com header.i=@harmstone.com header.a=rsa-sha256 header.s=mail header.b=uaerxxWr; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W36mf2D4hz20XR for ; Tue, 18 Jun 2024 10:18:42 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BB97C3882168 for ; Tue, 18 Jun 2024 00:18:39 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail.burntcomma.com (mail.burntcomma.com [IPv6:2a02:8012:8cf0:250::6d61:696c]) by sourceware.org (Postfix) with ESMTPS id 34DFD388206F for ; Tue, 18 Jun 2024 00:17:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 34DFD388206F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=harmstone.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=harmstone.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 34DFD388206F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a02:8012:8cf0:250::6d61:696c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1718669864; cv=none; b=EKWZ+uQScOaE3958RFRAZAusOTQ1BicNJpXMdboMBmOlNe1l1AsHGoNnAvmz3syny8Kb4oIL2pgm3q17HhRSMmFRSxbpmlyLwI4oYhrZQEoB0PX+GjQpf2YPOexOcj3H0IsmolLVF8tIHYVM/Yw9F7DCce+Ag1qEc4aPbfQW7VQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1718669864; c=relaxed/simple; bh=x2FqBrbwrBLgtDNXjmv+1y7wExt1MhgJrBlVXPXd13M=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:Mime-Version; b=hkWewCMeNMi8nYS73vY8UBGLDG8LFibAM20cHHkTsRkPSMA7g2Q9EnAPdVWcKKQKnYOxIgZFGcphi0T6Qc3dDIQj4+yx1kMCHesGAHp68Ouj24g5hrG30d43spWhiX8+mgar66/rx28UQGPSSrAgVR+36NkKn0veFJ6IQPITTCU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from localhost.localdomain (beren.burntcomma.com [IPv6:2a02:8012:8cf0:0:b62e:99ff:fee9:ad9f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (Client did not present a certificate) by mail.burntcomma.com (Postfix) with ESMTPSA id 891463CF0018; Tue, 18 Jun 2024 01:17:21 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=harmstone.com; s=mail; t=1718669841; bh=BFEfKCV26JkG/kvWfMrPAJhbZLfxW6cBMhBs/hqhFSI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=uaerxxWr9oW1IZeuFwZvTix+y1trZm/H8nx9bZmz+Y+WcB0LXs/UE4uImdNJuB16/ PLoCOCU6R/e8gU8nXTZPQEvSZIYKugCQQxK7Glu2RPZDP52zagIVC+tlC1lVSdbVBN pgTMOfvu5CMrJk/bAm3JTVo0udDzmlljwUhP0Yqo= From: Mark Harmstone To: gcc-patches@gcc.gnu.org Cc: Mark Harmstone Subject: [PATCH 04/11] Handle pointers for CodeView Date: Tue, 18 Jun 2024 01:17:06 +0100 Message-ID: <20240618001713.24034-5-mark@harmstone.com> In-Reply-To: <20240618001713.24034-1-mark@harmstone.com> References: <20240618001713.24034-1-mark@harmstone.com> Mime-Version: 1.0 X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_STOCKGEN, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Translates DW_TAG_pointer_type DIEs into LF_POINTER symbols, which get output into the .debug$T section. gcc/ * dwarf2codeview.cc (FIRST_TYPE): Define. (struct codeview_custom_type): New structure. (custom_types, last_custom_type): New variables. (get_type_num): Prototype. (write_lf_pointer, write_custom_types): New functions. (codeview_debug_finish): Call write_custom_types. (add_custom_type, get_type_num_pointer_type): New functions. (get_type_num): Handle DW_TAG_pointer_type DIEs. * dwarf2codeview.h (T_VOID): Define. (CV_POINTER_32, CV_POINTER_64): Likewise. (T_32PVOID, T_64PVOID): Likewise. (CV_PTR_NEAR32, CV_PTR64, LF_POINTER): Likewise. --- gcc/dwarf2codeview.cc | 179 +++++++++++++++++++++++++++++++++++++++++- gcc/dwarf2codeview.h | 13 +++ 2 files changed, 188 insertions(+), 4 deletions(-) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 5006a176260..51401f2d5bc 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see #define CV_CFL_C 0x00 #define CV_CFL_CXX 0x01 +#define FIRST_TYPE 0x1000 + #define LINE_LABEL "Lcvline" #define END_FUNC_LABEL "Lcvendfunc" #define SYMBOL_START_LABEL "Lcvsymstart" @@ -168,6 +170,22 @@ struct die_hasher : free_ptr_hash } }; +struct codeview_custom_type +{ + struct codeview_custom_type *next; + uint32_t num; + uint16_t kind; + + union + { + struct + { + uint32_t base_type; + uint32_t attributes; + } lf_pointer; + }; +}; + static unsigned int line_label_num; static unsigned int func_label_num; static unsigned int sym_label_num; @@ -181,6 +199,9 @@ static const char* last_filename; static uint32_t last_file_id; static codeview_symbol *sym, *last_sym; static hash_table *types_htab; +static codeview_custom_type *custom_types, *last_custom_type; + +static uint32_t get_type_num (dw_die_ref type); /* Record new line number against the current function. */ @@ -845,6 +866,71 @@ write_codeview_symbols (void) asm_fprintf (asm_out_file, "%LLcv_syms_end:\n"); } +/* Write an LF_POINTER type. */ + +static void +write_lf_pointer (codeview_custom_type *t) +{ + /* This is lf_pointer in binutils and lfPointer in Microsoft's cvinfo.h: + + struct lf_pointer + { + uint16_t size; + uint16_t kind; + uint32_t base_type; + uint32_t attributes; + } ATTRIBUTE_PACKED; + */ + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n", + t->num, t->num); + + asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, t->kind); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_pointer.base_type); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, t->lf_pointer.attributes); + putc ('\n', asm_out_file); + + asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num); +} + +/* Write the .debug$T section, which contains all of our custom type + definitions. */ + +static void +write_custom_types (void) +{ + targetm.asm_out.named_section (".debug$T", SECTION_DEBUG, NULL); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, CV_SIGNATURE_C13); + putc ('\n', asm_out_file); + + while (custom_types) + { + codeview_custom_type *n = custom_types->next; + + switch (custom_types->kind) + { + case LF_POINTER: + write_lf_pointer (custom_types); + break; + } + + free (custom_types); + custom_types = n; + } +} + /* Finish CodeView debug info emission. */ void @@ -861,6 +947,9 @@ codeview_debug_finish (void) write_line_numbers (); write_codeview_symbols (); + if (custom_types) + write_custom_types (); + if (types_htab) delete types_htab; } @@ -993,10 +1082,88 @@ get_type_num_base_type (dw_die_ref type) } } -/* Process a DIE representing a type definition and return its number. If - it's something we can't handle, return 0. We keep a hash table so that - we're not adding the same type multiple times - though if we do it's not - disastrous, as ld will deduplicate everything for us. */ +/* Add a new codeview_custom_type to our singly-linked custom_types list. */ + +static void +add_custom_type (codeview_custom_type *ct) +{ + uint32_t num; + + if (last_custom_type) + { + num = last_custom_type->num + 1; + last_custom_type->next = ct; + } + else + { + num = FIRST_TYPE; + custom_types = ct; + } + + last_custom_type = ct; + + ct->num = num; +} + +/* Process a DW_TAG_pointer_type DIE. If this is a pointer to a builtin + type, return the predefined constant for this. Otherwise, add a new + LF_POINTER type and return its number. */ + +static uint32_t +get_type_num_pointer_type (dw_die_ref type) +{ + uint32_t base_type_num, byte_size; + dw_die_ref base_type; + codeview_custom_type *ct; + + byte_size = get_AT_unsigned (type, DW_AT_byte_size); + if (byte_size != 4 && byte_size != 8) + return 0; + + base_type = get_AT_ref (type, DW_AT_type); + + /* If DW_AT_type is not set, this must be a void pointer. */ + if (!base_type) + return byte_size == 4 ? T_32PVOID : T_64PVOID; + + base_type_num = get_type_num (base_type); + if (base_type_num == 0) + return 0; + + /* Pointers to builtin types have predefined type numbers, with the top byte + determining the pointer size - 0x0400 for a 32-bit pointer and 0x0600 + for 64-bit. */ + if (base_type_num < FIRST_TYPE && !(base_type_num & 0xff00)) + { + if (byte_size == 4) + return CV_POINTER_32 | base_type_num; + else + return CV_POINTER_64 | base_type_num; + } + + ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type)); + + ct->next = NULL; + ct->kind = LF_POINTER; + ct->lf_pointer.base_type = base_type_num; + + if (byte_size == 4) + ct->lf_pointer.attributes = CV_PTR_NEAR32; + else + ct->lf_pointer.attributes = CV_PTR_64; + + ct->lf_pointer.attributes |= byte_size << 13; + + add_custom_type (ct); + + return ct->num; +} + +/* Process a DIE representing a type definition, add a CodeView type if + necessary, and return its number. If it's something we can't handle, return + 0. We keep a hash table so that we're not adding the same type multiple + times - though if we do it's not disastrous, as ld will deduplicate + everything for us. */ static uint32_t get_type_num (dw_die_ref type) @@ -1030,6 +1197,10 @@ get_type_num (dw_die_ref type) t->num = get_type_num (get_AT_ref (type, DW_AT_type)); break; + case DW_TAG_pointer_type: + t->num = get_type_num_pointer_type (type); + break; + default: t->num = 0; break; diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h index 7d8a4c161f4..0af4c98250f 100644 --- a/gcc/dwarf2codeview.h +++ b/gcc/dwarf2codeview.h @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see /* Constants for in-built types. */ +#define T_VOID 0x0003 #define T_CHAR 0x0010 #define T_SHORT 0x0011 #define T_LONG 0x0012 @@ -46,6 +47,18 @@ along with GCC; see the file COPYING3. If not see #define T_CHAR32 0x007b #define T_CHAR8 0x007c +#define CV_POINTER_32 0x0400 +#define CV_POINTER_64 0x0600 +#define T_32PVOID (T_VOID | CV_POINTER_32) +#define T_64PVOID (T_VOID | CV_POINTER_64) + +/* LF_POINTER attributes. */ +#define CV_PTR_NEAR32 0x0a +#define CV_PTR_64 0x0c + +/* Constants for type definitions. */ +#define LF_POINTER 0x1002 + /* Debug Format Interface. Used in dwarf2out.cc. */ extern void codeview_debug_finish (void);