From patchwork Mon Oct 23 03:36:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rishi Raj X-Patchwork-Id: 1853482 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=Mt4BeP7j; 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 4SDLVL39Hfz23jZ for ; Mon, 23 Oct 2023 14:37:30 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4333E3858032 for ; Mon, 23 Oct 2023 03:37:28 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ot1-x32c.google.com (mail-ot1-x32c.google.com [IPv6:2607:f8b0:4864:20::32c]) by sourceware.org (Postfix) with ESMTPS id 40FAF3858C5F for ; Mon, 23 Oct 2023 03:36:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 40FAF3858C5F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 40FAF3858C5F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::32c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698032224; cv=none; b=v8YgEdI56iW/+n+J0eIArdzoSfZw794YpbPOdFVgytJ1gzazFXcexDup/18+mTymdPy49WQgiTArfCT98fBMZTPnU/FOxEpNneNRFmhxcVUJfLcT0WIkKyI/As5gspMLkokrgE0OmDvVNBv2UBhLsiB/znBfahoUD1HkRz+MvyU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698032224; c=relaxed/simple; bh=AHG5jvwWWF9W4nSsOxRnlLlJAX/Q1i0QNzHQv7PAjj0=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=wXg1M3MhB0O24KRTngbkGrpW7uakwOnIPfKRE5fGpZY4Jaqk7F5WeYQ+jbqUawcpZi7d7Rqhmi2AG69ov6RZUDNmWZ2DwtgN+MX8hqSNdeDoR3GWsWXWNwwEiHfNc+W1DcP1Y/shouBRnCpfZjgTYHzXJUZ+qakENO3rCFJa/bw= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ot1-x32c.google.com with SMTP id 46e09a7af769-6ce2fc858feso1689483a34.3 for ; Sun, 22 Oct 2023 20:36:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698032214; x=1698637014; darn=gcc.gnu.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=/GWZcAgXs6JQEwC46KdgMAqlntr5YW2XLTCuLO/vYNU=; b=Mt4BeP7jzkhApMRS4iWC7csNXK2i5KA+pZYoLwq2wzj77IXRJVxHEJzOfCHGJtTmys gqnSt2coBfwjD0YO9RibmQNWy3dEeqb3gM3MkDJSUQzNdWsJP5/wQaZV2ZthfNlLtiHJ MAJFVxeZNTGPwt59ndjQBU9CfbSG0RNXqnoT5CgeVwRosLF0GLNSYQNsT8RYOxQ1hurL li/Y5lDIhoPd1yBMLc5dlK0nJ9Ne5WhXpzA72lO8aQ483r3EZBCxDkGPI+x9ogs267Ha G96BKUwj68JcBoIai91+4xFkYkNojgThl5K5I7THyj0cGbWQPsbu3TAmF+5o8xNljYG5 vDKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698032214; x=1698637014; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=/GWZcAgXs6JQEwC46KdgMAqlntr5YW2XLTCuLO/vYNU=; b=fCKdqPH/MMIejfK7Q0ZowqRkZKOfQX294tTe7dUXS7MkAmPZ1mabN02v2oZRhHnSqm MzXhqpBZAvvvozzIFok3YZTCyTvPHyZkEiKP696EefETSN+BlITEyioKwhO4jkaxaxKy oyYmyEs4S4ezexmwI5raiSeZxpCi+rL6oOwcXVNrGIRotSJBOJD6fWBIlcGd0Lth6cY2 T51zDGAyzQsdGvsZWMwMqmhZ/MoU1B7FDc6akolC+fvyXin7LqjGhN162Ouh4KdiPWJY cDw1L9Pp4JzxFBgA20A0VJK4esbrocYIWvXJi/xT47xCgjauXzrylJzTDa03JK/eMqzl uK+g== X-Gm-Message-State: AOJu0Yxm8KZta2uQmw0MH4iEysADlMLsb6589x804jQuIM8C0ms1JAjQ 2JrxqVgrUYxE/NSN6hxiQtgxQFdPvEWHXb7BaKjEwBYGm2627w== X-Google-Smtp-Source: AGHT+IEutEZgq0qJqN/Vc6oO/BmHld2cbD2QOqC/AkNk/oGuDc03zITQY3NhleCcctWhC4Hx63eA+md4k5FD8/D+Vc0= X-Received: by 2002:a05:6830:2702:b0:6b8:8f20:4cbc with SMTP id j2-20020a056830270200b006b88f204cbcmr7454417otu.13.1698032214027; Sun, 22 Oct 2023 20:36:54 -0700 (PDT) MIME-Version: 1.0 From: Rishi Raj Date: Mon, 23 Oct 2023 09:06:42 +0530 Message-ID: Subject: [PATCH][WIP] dwarf2out: extend to output debug section directly to object file during debug_early phase To: gcc-patches@gcc.gnu.org, Jan Hubicka , Martin Jambor X-Spam-Status: No, score=-7.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, 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: 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 These patches extend dwarf2out.cc to directly output the debug section to the object file during the early debug phase. From 9cb626b544d87a5bc883e97ee3d96a4af296ebd1 Mon Sep 17 00:00:00 2001 From: Rishi Raj Date: Fri, 6 Oct 2023 19:38:16 +0530 Subject: [PATCH 2/3] Added debug_info and debug_abbrev section code Signed-off-by: Rishi Raj --- .vscode/settings.json | 7 +++++++ gcc/dwarf2out.h | 10 ++++++++++ gcc/langhooks.cc | 7 ------- 3 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 .vscode/settings.json { diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..ce4537107a5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "*.ejs": "html", + "C": ".c", + "p418.C": "cpp" + } +} \ No newline at end of file diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index 05ae0d7f34e..e06bc7679ff 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -418,6 +418,16 @@ struct fixed_point_type_info struct { tree numerator; tree denominator; } arbitrary; } scale_factor; }; +/*Struct to hold compilation unit header need for .debug_info*/ +typedef struct dw_cu_header_struct +{ + uint32_t length; + uint16_t version; + uint8_t unit_type; + uint8_t address_size; + uint32_t debug_abbrev_offset; +} +dw_cu_header; void dwarf2cfi_cc_finalize (void); void dwarf2out_cc_finalize (void); diff --git a/gcc/langhooks.cc b/gcc/langhooks.cc index a76ed974d58..11e4bee8098 100644 --- a/gcc/langhooks.cc +++ b/gcc/langhooks.cc @@ -823,13 +823,6 @@ lhd_begin_section (const char *name) if (flag_bypass_asm) { - static int initialized = false; - if (!initialized) - { - gcc_assert (asm_out_file == NULL); - lto_set_current_out_file (lto_obj_file_open (asm_file_name, true)); - initialized = true; - } lto_obj_begin_section (name); return; } -- 2.42.0 From 284dc60ed2272eb60f7de1e188c92d1cac750d61 Mon Sep 17 00:00:00 2001 From: Rishi Raj Date: Mon, 23 Oct 2023 06:24:16 +0530 Subject: [PATCH 3/3] Extended dwarf2out.cc to output the .debug_line and .debug_info relocations Signed-off-by: Rishi Raj --- gcc/dwarf2out.cc | 1583 ++++++++++++++++++++++++++++++--------------- gcc/lto-object.cc | 2 +- 2 files changed, 1067 insertions(+), 518 deletions(-) diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index b40c6267a0b..59b00e7cb73 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -103,6 +103,8 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple.h" #include "lto-streamer.h" +#include "simple-object.h" + static void dwarf2out_source_line (unsigned int, unsigned int, const char *, int, bool); @@ -2597,7 +2599,6 @@ output_loc_sequence (dw_loc_descr_ref loc, int for_eh_or_skip) /* Output location description stack opcode's operands (if any). The output is single bytes on a line, suitable for .cfi_escape. */ - static void output_loc_operands_raw (dw_loc_descr_ref loc) { @@ -2652,7 +2653,7 @@ output_loc_operands_raw (dw_loc_descr_ref loc) offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3); fputc (',', asm_out_file); - dw2_asm_output_data_raw (2, offset); + dw2_asm_output_data_raw (2, offset); } break; @@ -2774,7 +2775,7 @@ output_loc_sequence_raw (dw_loc_descr_ref loc) gcc_assert (r <= 31); opc = (enum dwarf_location_atom) (DW_OP_reg0 + r); } - /* Output the opcode. */ + /* Output the opcode. */ fprintf (asm_out_file, "%#x", opc); output_loc_operands_raw (loc); @@ -4019,6 +4020,28 @@ static const char *comp_dir_string (void); static void hash_loc_operands (dw_loc_descr_ref, inchash::hash &); +/* object file output ( -fbypass-asm ) helper function */ +static size_t output_data_to_object_file(size_t size, unsigned HOST_WIDE_INT value); +static size_t output_data_uleb128_to_object_file(unsigned HOST_WIDE_INT value); +static size_t output_data_sleb128_to_object_file(HOST_WIDE_INT value); +static size_t output_nstring_to_object_file(const char *str, size_t orig_len); +static size_t output_value_format_to_object_file (dw_attr_node *a); +static void output_die_to_object_file (dw_die_ref die); +static void output_die_abbrevs_to_object_file(unsigned long abbrev_id, dw_die_ref abbrev); +static void output_abbrev_section_to_object_file (void); +static inline size_t output_discr_value_to_object_file (dw_discr_value *discr_value, const char *name); +static void output_compilation_unit_header_to_object_file(enum dwarf_unit_type ut); +static void output_comp_unit_to_object_file (dw_die_ref die, int output_if_empty, const unsigned char *dwo_id); +static void output_line_info_to_object_file (bool prologue_only); +static void output_indirect_strings_to_object_file (void); +static void output_line_string_to_object_file (enum dwarf_form form, const char *str, const char *entry_kind, unsigned int idx); +static void output_file_names_to_object_file (void); +static void modify_buffer_of_object_file (unsigned long offset, size_t size, HOST_WIDE_INT value) + + + + + /* enum for tracking thread-local variables whose address is really an offset relative to the TLS pointer, which will need link-time relocation, but will not need relocation by the DWARF consumer. */ @@ -10153,6 +10176,15 @@ output_value_format (dw_attr_node *a) dw2_asm_output_data_uleb128 (form, "(%s)", dwarf_form_name (form)); } +static size_t +output_value_format_to_object_file (dw_attr_node *a) +{ + enum dwarf_form form = value_format (a); + + return output_data_uleb128_to_object_file(form); + +} + /* Given a die and id, produce the appropriate abbreviations. */ static void @@ -10192,6 +10224,44 @@ output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev) dw2_asm_output_data (1, 0, NULL); } +/* Given a die and id, produce the appropriate abbreviations + directly to lto object file */ + +static void +output_die_abbrevs_to_object_file(unsigned long abbrev_id, dw_die_ref abbrev) +{ + unsigned ix; + dw_attr_node *a_attr; + + output_data_uleb128_to_object_file(abbrev_id); + output_data_uleb128_to_object_file(abbrev->die_tag); + + + if (abbrev->die_child != NULL) + output_data_to_object_file(1,DW_children_yes); + else + output_data_to_object_file(1,DW_children_no); + + for (ix = 0; vec_safe_iterate (abbrev->die_attr, ix, &a_attr); ix++) + { + output_data_uleb128_to_object_file(a_attr->dw_attr); + output_value_format_to_object_file(a_attr); + if (value_format (a_attr) == DW_FORM_implicit_const) + { + if (AT_class (a_attr) == dw_val_class_file_implicit) + { + int f = maybe_emit_file (a_attr->dw_attr_val.v.val_file); + output_data_sleb128_to_object_file(f); + } + else + output_data_sleb128_to_object_file(a_attr->dw_attr_val.v.val_int); + } + } + + output_data_to_object_file (1, 0); + output_data_to_object_file (1, 0); +} + /* Output the .debug_abbrev section which defines the DIE abbreviation table. */ @@ -10211,28 +10281,58 @@ output_abbrev_section (void) } static void -output_data_to_object_file(int size, unsigned HOST_WIDE_INT value) +output_abbrev_section_to_object_file (void) { + lto_obj_begin_section(".gnu.debuglto_.debug_abbrev"); + unsigned int abbrev_id; + dw_die_ref abbrev; + FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev) + if (abbrev_id != 0) + output_die_abbrevs_to_object_file (abbrev_id, abbrev); - char *buff=XNEWVEC(char,size); + /* Terminate the table. */ + output_data_to_object_file (1, 0); + lto_obj_end_section(); - //handle little endian vs big endian. right now assuming little endian - for(int i=size-1;i>=0;i--) - { - buff[i] = value & 0xFF; - value >>= 8; - } +} - void *v; +/* Helper function to output a value of given size to object file */ +static size_t +output_data_to_object_file(size_t size, unsigned HOST_WIDE_INT value) +{ + unsigned char bytes[8]; + unsigned int i; + unsigned char *buff = XNEWVEC(unsigned char, size); + for (i = 0; i < 8; ++i) + { + bytes[i] = value & 0xff; + value >>= 8; + } + if (BYTES_BIG_ENDIAN) + { + for (i = size - 1; i >= 0; --i) + buff[i] = bytes[i]; + } + else + { + for (i = 0; i <= size - 1; ++i) + buff[i] = bytes[i]; + } + + void *v = NULL; lto_obj_append_data((const void *) buff, size, v); + + return size; } -static void +/* Helper function to output a uleb128 to object file */ +static size_t output_data_uleb128_to_object_file(unsigned HOST_WIDE_INT value) { - int size=0, temp_value=value; + size_t size=0; + unsigned HOST_WIDE_INT temp_value=value; //find the size of uleb128 data while(temp_value) @@ -10241,9 +10341,9 @@ output_data_uleb128_to_object_file(unsigned HOST_WIDE_INT value) size++; } - char *buff=XNEWVEC(char,size); + unsigned char *buff=XNEWVEC(unsigned char,size); - for(int i=0;i>= 7; @@ -10253,31 +10353,37 @@ output_data_uleb128_to_object_file(unsigned HOST_WIDE_INT value) buff[i]=byte; } - void *v; + void *v=NULL; lto_obj_append_data((const void *) buff, size, v); + return size; } -static void -output_data_sleb128_to_object_file(unsigned HOST_WIDE_INT value) + /* Helper function to output sleb128 to object file*/ +static size_t +output_data_sleb128_to_object_file(HOST_WIDE_INT value) { - int size=0, temp_value=value,more; + size_t size=0; + HOST_WIDE_INT temp_value=value; + int byte, more; //find the size of sleb128 data while(1) { - int byte = (value & 0x7f); - temp_value>>=7; + byte = (temp_value & 0x7f); + temp_value >>= 7; size++; - more = !((value == 0 && (byte & 0x40) == 0) - || (value == -1 && (byte & 0x40) != 0)); + more = !((temp_value == 0 && (byte & 0x40) == 0) + || (temp_value == -1 && (byte & 0x40) != 0)); + if (more) + byte |= 0x80; if(!more) break; } - char *buff=XNEWVEC(char,size); + unsigned char *buff=XNEWVEC(unsigned char,size); - for(int i=0;i>= 7; more = !((value == 0 && (byte & 0x40) == 0) || (value == -1 && (byte & 0x40) != 0)); @@ -10288,84 +10394,22 @@ output_data_sleb128_to_object_file(unsigned HOST_WIDE_INT value) buff[i]=byte; } - void *v; + void *v=NULL; lto_obj_append_data((const void *) buff, size, v); -} -static void -output_value_format_to_object_file (dw_attr_node *a) -{ - enum dwarf_form form = value_format (a); - - output_data_uleb128_to_object_file(form); - // dw2_asm_output_data_uleb128 (form, "(%s)", dwarf_form_name (form)); + return size; } -/* Given a die and id, produce the appropriate abbreviations -directly to lto object file */ - -static void -output_die_abbrevs_to_object_file(unsigned long abbrev_id, dw_die_ref abbrev) +static size_t +output_nstring_to_object_file(const char *str, size_t orig_len ) { - unsigned ix; - dw_attr_node *a_attr; - - // dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)"); - // dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)", - // dwarf_tag_name (abbrev->die_tag)); - output_data_uleb128_to_object_file(abbrev_id); - output_data_uleb128_to_object_file(abbrev->die_tag); - - - if (abbrev->die_child != NULL) - output_data_to_object_file(1,DW_children_yes); - // dw2_asm_output_data (1, DW_children_yes, "DW_children_yes"); - else - output_data_to_object_file(1,DW_children_no); - // dw2_asm_output_data (1, DW_children_no, "DW_children_no"); - - for (ix = 0; vec_safe_iterate (abbrev->die_attr, ix, &a_attr); ix++) - { - // dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)", - // dwarf_attr_name (a_attr->dw_attr)); - output_data_uleb128_to_object_file(a_attr->dw_attr); - // output_value_format (a_attr); - output_value_format_to_object_file(a_attr); - if (value_format (a_attr) == DW_FORM_implicit_const) - { - if (AT_class (a_attr) == dw_val_class_file_implicit) - { - int f = maybe_emit_file (a_attr->dw_attr_val.v.val_file); - // const char *filename = a_attr->dw_attr_val.v.val_file->filename; - // dw2_asm_output_data_sleb128 (f, "(%s)", filename); - output_data_sleb128_to_object_file(f); - } - else - output_data_sleb128_to_object_file(a_attr->dw_attr_val.v.val_int); - // dw2_asm_output_data_sleb128 (a_attr->dw_attr_val.v.val_int, NULL); - } - } - - output_data_to_object_file (1, 0); - output_data_to_object_file (1, 0); + if(orig_len == (size_t) -1) + orig_len=strlen(str)+1; + void *v_=NULL; + lto_obj_append_data((const void *)str,orig_len,v_); + return orig_len; } -static void -output_abbrev_section_to_object_file (void) -{ - lto_obj_begin_section(".gnu.debuglto_.debug_abbrev"); - unsigned int abbrev_id; - dw_die_ref abbrev; - FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev) - if (abbrev_id != 0) - output_die_abbrevs_to_object_file (abbrev_id, abbrev); - - /* Terminate the table. */ - output_data_to_object_file (1, 0); - lto_obj_end_section(); - -} - /* Return a new location list, given the begin and end range, and the expression. */ @@ -10930,6 +10974,14 @@ output_discr_value (dw_discr_value *discr_value, const char *name) else dw2_asm_output_data_sleb128 (discr_value->v.sval, "%s", name); } +static inline size_t +output_discr_value_to_object_file (dw_discr_value *discr_value, const char *name) +{ + if (discr_value->pos) + return output_data_uleb128_to_object_file (discr_value->v.uval); + else + return output_data_sleb128_to_object_file (discr_value->v.sval); +} /* Output the DIE and its attributes. Called recursively to generate the definitions of each child DIE. */ @@ -11472,62 +11524,63 @@ output_compilation_unit_header (dwo_id } } +struct lto_simple_object +{ + /* The base information. */ + lto_file base; + + /* The system file descriptor. */ + int fd; + + /* The simple_object if we are reading the file. */ + simple_object_read *sobj_r; + + /* The simple_object if we are writing the file. */ + simple_object_write *sobj_w; + + /* The currently active section. */ + simple_object_write_section *section; +}; + static void output_die_to_object_file (dw_die_ref die) { + struct lto_simple_object *lo = (struct lto_simple_object *) lto_get_current_out_file (); + static uint64_t debug_info_offset = sizeof(dw_cu_header); /* current offset into .debug_info section */ + static uint64_t debug_str_offset=0; /* Current Offset into .debug_line */ + static uint64_t debug_line_str_offset=0; /* Current offset into .debug_line_str */ dw_attr_node *a; dw_die_ref c; - unsigned long size; unsigned ix; - // dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)", - // (unsigned long)die->die_offset, - // dwarf_tag_name (die->die_tag)); - //this outputs the abbreviation code for this die - - output_data_uleb128_to_object_file(die->die_abbrev); - return; //as I haven't handled all of the possible cases below output the abbrev code and return + debug_info_offset+=output_data_uleb128_to_object_file(die->die_abbrev); - - //ouput each attribute of this die FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) { const char *name = dwarf_attr_name (a->dw_attr); switch (AT_class (a)) - { +{ case dw_val_class_addr: - //TO DO: will have to first read about rtx type - // dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name); + gcc_unreachable(); break; case dw_val_class_offset: - dw2_asm_output_data (dwarf_offset_size, a->dw_attr_val.v.val_offset, - "%s", name); + debug_info_offset+=output_data_to_object_file(dwarf_offset_size,a->dw_attr_val.v.val_offset); break; case dw_val_class_range_list: - // handle it later as We have to output this into a different section - // output_range_list_offset (a); + gcc_unreachable(); break; case dw_val_class_loc: - size = size_of_locs (AT_loc (a)); - - /* Output the block length for this list of location operations. */ - if (dwarf_version >= 4) - dw2_asm_output_data_uleb128 (size, "%s", name); - else - dw2_asm_output_data (constant_size (size), size, "%s", name); - - output_loc_sequence (AT_loc (a), -1); - break; + gcc_unreachable(); case dw_val_class_const: /* ??? It would be slightly more efficient to use a scheme like is used for unsigned constants below, but gdb 4.x does not sign extend. Gdb 5.x does sign extend. */ - dw2_asm_output_data_sleb128 (AT_int (a), "%s", name); + debug_info_offset+=output_data_sleb128_to_object_file (AT_int (a)); break; case dw_val_class_unsigned_const: @@ -11536,40 +11589,21 @@ output_die_to_object_file (dw_die_ref die) if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location && csize >= 4) - dw2_asm_output_data_uleb128 (AT_unsigned (a), "%s", name); + debug_info_offset+=output_data_uleb128_to_object_file(AT_unsigned(a)); else - dw2_asm_output_data (csize, AT_unsigned (a), "%s", name); + debug_info_offset+=output_data_to_object_file(csize,AT_unsigned(a)); } break; case dw_val_class_symview: - { - int vsize; - if (symview_upper_bound <= 0xff) - vsize = 1; - else if (symview_upper_bound <= 0xffff) - vsize = 2; - else if (symview_upper_bound <= 0xffffffff) - vsize = 4; - else - vsize = 8; - dw2_asm_output_addr (vsize, a->dw_attr_val.v.val_symbolic_view, - "%s", name); - } + gcc_unreachable(); break; case dw_val_class_const_implicit: - if (flag_debug_asm) - fprintf (asm_out_file, "\t\t\t%s %s (" - HOST_WIDE_INT_PRINT_DEC ")\n", - ASM_COMMENT_START, name, AT_int (a)); + gcc_unreachable(); break; case dw_val_class_unsigned_const_implicit: - if (flag_debug_asm) - fprintf (asm_out_file, "\t\t\t%s %s (" - HOST_WIDE_INT_PRINT_HEX ")\n", - ASM_COMMENT_START, name, AT_unsigned (a)); break; case dw_val_class_const_double: @@ -11577,10 +11611,9 @@ output_die_to_object_file (dw_die_ref die) unsigned HOST_WIDE_INT first, second; if (HOST_BITS_PER_WIDE_INT >= DWARF_LARGEST_DATA_FORM_BITS) - dw2_asm_output_data (1, + debug_info_offset+=output_data_to_object_file (1, HOST_BITS_PER_DOUBLE_INT - / HOST_BITS_PER_CHAR, - NULL); + / HOST_BITS_PER_CHAR); if (WORDS_BIG_ENDIAN) { @@ -11593,10 +11626,10 @@ output_die_to_object_file (dw_die_ref die) second = a->dw_attr_val.v.val_double.high; } - dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR, - first, "%s", name); - dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR, - second, NULL); + debug_info_offset+=output_data_to_object_file (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR, + first); + debug_info_offset+=output_data_to_object_file (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR, + second); } break; @@ -11606,21 +11639,20 @@ output_die_to_object_file (dw_die_ref die) int len = get_full_len (*a->dw_attr_val.v.val_wide); int l = HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; if (len * HOST_BITS_PER_WIDE_INT > DWARF_LARGEST_DATA_FORM_BITS) - dw2_asm_output_data (1, get_full_len (*a->dw_attr_val.v.val_wide) - * l, NULL); + debug_info_offset+=output_data_to_object_file (1, get_full_len (*a->dw_attr_val.v.val_wide) + * l); + if (WORDS_BIG_ENDIAN) for (i = len - 1; i >= 0; --i) { - dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i), - "%s", name); + debug_info_offset+=output_data_to_object_file (l, a->dw_attr_val.v.val_wide->elt (i)); name = ""; } else for (i = 0; i < len; ++i) { - dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i), - "%s", name); + debug_info_offset+=output_data_to_object_file (l, a->dw_attr_val.v.val_wide->elt (i)); name = ""; } } @@ -11633,8 +11665,8 @@ output_die_to_object_file (dw_die_ref die) unsigned int i; unsigned char *p; - dw2_asm_output_data (constant_size (len * elt_size), - len * elt_size, "%s", name); + debug_info_offset+=output_data_to_object_file (constant_size (len * elt_size), + len * elt_size); if (elt_size > sizeof (HOST_WIDE_INT)) { elt_size /= 2; @@ -11643,8 +11675,7 @@ output_die_to_object_file (dw_die_ref die) for (i = 0, p = (unsigned char *) a->dw_attr_val.v.val_vec.array; i < len; i++, p += elt_size) - dw2_asm_output_data (elt_size, extract_int (p, elt_size), - "fp or vector constant word %u", i); + debug_info_offset+=output_data_to_object_file (elt_size, extract_int (p, elt_size)); break; } @@ -11658,145 +11689,91 @@ output_die_to_object_file (dw_die_ref die) DW_FORM_flag_present if it is set to 1 in all DIEs using the same abbrev entry. */ gcc_assert (AT_flag (a) == 1); - if (flag_debug_asm) - fprintf (asm_out_file, "\t\t\t%s %s\n", - ASM_COMMENT_START, name); break; } - dw2_asm_output_data (1, AT_flag (a), "%s", name); + debug_info_offset+=output_data_to_object_file (1, AT_flag (a)); break; case dw_val_class_loc_list: - output_loc_list_offset (a); + gcc_unreachable(); break; case dw_val_class_view_list: - output_view_list_offset (a); + gcc_unreachable(); break; - case dw_val_class_die_ref: - if (AT_ref_external (a)) + case dw_val_class_die_ref: // have to output this + if (AT_ref_external (a)) { - if (AT_ref (a)->comdat_type_p) - { - comdat_type_node *type_node - = AT_ref (a)->die_id.die_type_node; - - gcc_assert (type_node); - output_signature (type_node->signature, name); - } - else - { - const char *sym = AT_ref (a)->die_id.die_symbol; - int size; - - gcc_assert (sym); - /* In DWARF2, DW_FORM_ref_addr is sized by target address - length, whereas in DWARF3 it's always sized as an - offset. */ - if (dwarf_version == 2) - size = DWARF2_ADDR_SIZE; - else - size = dwarf_offset_size; - /* ??? We cannot unconditionally output die_offset if - non-zero - others might create references to those - DIEs via symbols. - And we do not clear its DIE offset after outputting it - (and the label refers to the actual DIEs, not the - DWARF CU unit header which is when using label + offset - would be the correct thing to do). - ??? This is the reason for the with_offset flag. */ - if (AT_ref (a)->with_offset) - dw2_asm_output_offset (size, sym, AT_ref (a)->die_offset, - debug_info_section, "%s", name); - else - dw2_asm_output_offset (size, sym, debug_info_section, "%s", - name); - } + gcc_unreachable(); } else { gcc_assert (AT_ref (a)->die_offset); - dw2_asm_output_data (dwarf_offset_size, AT_ref (a)->die_offset, - "%s", name); + debug_info_offset+=output_data_to_object_file (dwarf_offset_size, AT_ref (a)->die_offset); } break; case dw_val_class_fde_ref: - { - char l1[MAX_ARTIFICIAL_LABEL_BYTES]; - - ASM_GENERATE_INTERNAL_LABEL (l1, FDE_LABEL, - a->dw_attr_val.v.val_fde_index * 2); - dw2_asm_output_offset (dwarf_offset_size, l1, debug_frame_section, - "%s", name); - } + gcc_unreachable(); break; case dw_val_class_vms_delta: -#ifdef ASM_OUTPUT_DWARF_VMS_DELTA - dw2_asm_output_vms_delta (dwarf_offset_size, - AT_vms_delta2 (a), AT_vms_delta1 (a), - "%s", name); -#else - dw2_asm_output_delta (dwarf_offset_size, - AT_vms_delta2 (a), AT_vms_delta1 (a), - "%s", name); -#endif - break; + gcc_unreachable(); case dw_val_class_lbl_id: - output_attr_index_or_value (a); + gcc_unreachable(); break; - case dw_val_class_lineptr: - dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a), - debug_line_section, "%s", name); + case dw_val_class_lineptr: + simple_object_write_add_relocation(lo->section, debug_info_offset, 0, + ".gnu.debuglto_.debug_line", 3); + debug_info_offset += output_data_to_object_file(dwarf_offset_size,0); break; case dw_val_class_macptr: - dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a), - debug_macinfo_section, "%s", name); + gcc_unreachable(); break; case dw_val_class_loclistsptr: - dw2_asm_output_offset (dwarf_offset_size, AT_lbl (a), - debug_loc_section, "%s", name); + gcc_unreachable(); break; case dw_val_class_str: - if (a->dw_attr_val.v.val_str->form == DW_FORM_strp) - dw2_asm_output_offset (dwarf_offset_size, - a->dw_attr_val.v.val_str->label, - debug_str_section, - "%s: \"%s\"", name, AT_string (a)); - else if (a->dw_attr_val.v.val_str->form == DW_FORM_line_strp) - dw2_asm_output_offset (dwarf_offset_size, - a->dw_attr_val.v.val_str->label, - debug_line_str_section, - "%s: \"%s\"", name, AT_string (a)); - else if (a->dw_attr_val.v.val_str->form == dwarf_FORM (DW_FORM_strx)) - dw2_asm_output_data_uleb128 (AT_index (a), - "%s: \"%s\"", name, AT_string (a)); - else - dw2_asm_output_nstring (AT_string (a), -1, "%s", name); - break; + { + if (a->dw_attr_val.v.val_str->form == DW_FORM_strp) + { + simple_object_write_add_relocation(lo->section, debug_info_offset, + debug_str_offset, ".gnu.debuglto_.debug_str", 4); + debug_info_offset += output_data_to_object_file(dwarf_offset_size, 0); + debug_str_offset += strlen(a->dw_attr_val.v.val_str->str)+1; + + } + else if (a->dw_attr_val.v.val_str->form == DW_FORM_line_strp) + { + simple_object_write_add_relocation(lo->section, debug_info_offset, + debug_line_str_offset, ".gnu.debuglto_.debug_line_str", 5); + debug_info_offset += output_data_to_object_file(dwarf_offset_size, 0); + debug_line_str_offset += strlen(a->dw_attr_val.v.val_str->str)+1; + + } + + else if (a->dw_attr_val.v.val_str->form == dwarf_FORM (DW_FORM_strx)) + debug_info_offset+=output_data_uleb128_to_object_file (AT_index (a)); + else + debug_info_offset+=output_nstring_to_object_file (AT_string (a), -1); + break; + } case dw_val_class_file: { int f = maybe_emit_file (a->dw_attr_val.v.val_file); - dw2_asm_output_data (constant_size (f), f, "%s (%s)", name, - a->dw_attr_val.v.val_file->filename); + debug_info_offset+=output_data_to_object_file (constant_size (f), f); break; } case dw_val_class_file_implicit: - if (flag_debug_asm) - fprintf (asm_out_file, "\t\t\t%s %s (%d, %s)\n", - ASM_COMMENT_START, name, - maybe_emit_file (a->dw_attr_val.v.val_file), - a->dw_attr_val.v.val_file->filename); break; case dw_val_class_data8: @@ -11804,18 +11781,16 @@ output_die_to_object_file (dw_die_ref die) int i; for (i = 0; i < 8; i++) - dw2_asm_output_data (1, a->dw_attr_val.v.val_data8[i], - i == 0 ? "%s" : NULL, name); + debug_info_offset+=output_data_to_object_file (1, a->dw_attr_val.v.val_data8[i]); break; } case dw_val_class_high_pc: - dw2_asm_output_delta (DWARF2_ADDR_SIZE, AT_lbl (a), - get_AT_low_pc (die), "DW_AT_high_pc"); + gcc_unreachable(); break; case dw_val_class_discr_value: - output_discr_value (&a->dw_attr_val.v.val_discr_value, name); + debug_info_offset+=output_discr_value_to_object_file (&a->dw_attr_val.v.val_discr_value, name); break; case dw_val_class_discr_list: @@ -11824,23 +11799,22 @@ output_die_to_object_file (dw_die_ref die) const int size = size_of_discr_list (list); /* This is a block, so output its length first. */ - dw2_asm_output_data (constant_size (size), size, - "%s: block size", name); + + debug_info_offset+=output_data_to_object_file (constant_size (size), size); for (; list != NULL; list = list->dw_discr_next) { /* One byte for the discriminant value descriptor, and then as many LEB128 numbers as required. */ if (list->dw_discr_range) - dw2_asm_output_data (1, DW_DSC_range, - "%s: DW_DSC_range", name); + debug_info_offset+=output_data_to_object_file (1, DW_DSC_range); else - dw2_asm_output_data (1, DW_DSC_label, - "%s: DW_DSC_label", name); + debug_info_offset+=output_data_to_object_file (1, DW_DSC_label); - output_discr_value (&list->dw_discr_lower_bound, name); + debug_info_offset+=output_discr_value_to_object_file (&list->dw_discr_lower_bound, name); if (list->dw_discr_range) - output_discr_value (&list->dw_discr_upper_bound, name); + debug_info_offset+=output_discr_value_to_object_file (&list->dw_discr_upper_bound, name); + } break; } @@ -11853,15 +11827,16 @@ output_die_to_object_file (dw_die_ref die) FOR_EACH_CHILD (die, c, output_die_to_object_file (c)); /* Add null byte to terminate sibling list. */ - // if (die->die_child != NULL) - // dw2_asm_output_data (1, 0, "end of children of DIE %#lx", - // (unsigned long) die->die_offset); + if (die->die_child != NULL) + debug_info_offset+=output_data_to_object_file(1,0); } - static void output_compilation_unit_header_to_object_file(enum dwarf_unit_type ut) { + struct lto_simple_object *lo = (struct lto_simple_object *) lto_get_current_out_file (); + lto_obj_begin_section(".gnu.debuglto_.debug_info"); + dw_cu_header *cu_header; cu_header = XNEW(dw_cu_header); cu_header->length = next_die_offset - DWARF_INITIAL_LENGTH_SIZE; @@ -11869,7 +11844,10 @@ output_compilation_unit_header_to_object_file(enum dwarf_unit_type ut) cu_header->unit_type = ut; cu_header->address_size = DWARF2_ADDR_SIZE; cu_header->debug_abbrev_offset = 0x0; - void *v; + + simple_object_write_add_relocation(lo->section, 8, 0, + ".gnu.debuglto_.debug_abbrev", 2); + void *v = NULL; lto_obj_append_data((const void *)cu_header,sizeof(dw_cu_header),v); } @@ -11878,9 +11856,8 @@ static void output_comp_unit_to_object_file (dw_die_ref die, int output_if_empty, const unsigned char *dwo_id) { - const char *secname, *oldsym; - char *tmp; - + const char *oldsym; + /* Unless we are outputting main CU, we may throw away empty ones. */ if (!output_if_empty && die->die_child == NULL) return; @@ -11914,6 +11891,14 @@ output_comp_unit_to_object_file (dw_die_ref die, int output_if_empty, oldsym = die->die_id.die_symbol; + /* For LTO cross unit DIE refs we want a symbol on the start of the + debuginfo section, not on the CU DIE. */ + if ((flag_generate_lto || flag_generate_offload) && oldsym) + { + struct lto_simple_object *lo = (struct lto_simple_object *) lto_get_current_out_file (); + simple_object_write_add_symbol(lo->sobj_w, oldsym, 0, 0, 2, 0, 1, 2); + } + output_compilation_unit_header_to_object_file(dwo_id ? DW_UT_split_compile : DW_UT_compile); output_die_to_object_file(die); @@ -13156,8 +13141,8 @@ output_line_string (enum dwarf_form form, const char *str, /* Output the directory table and the file name table. We try to minimize the total amount of memory needed. A heuristic is used to avoid large - slowdowns with many input files. */ - + slowdowns with many input files. */ + static void output_file_names (void) { @@ -13493,229 +13478,783 @@ output_file_names (void) snprintf (filebuf, maxfilelen, "%s;%d", files[file_idx].path + dirs[dir_idx].length, ver); - output_line_string (str_form, filebuf, "File Entry", (unsigned) i + 1); + output_line_string (str_form, filebuf, "File Entry", (unsigned) i + 1); + + /* Include directory index. */ + if (dwarf_version >= 5 && idx_form != DW_FORM_udata) + dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2, + dir_idx + idx_offset, NULL); + else + dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL); + + /* Modification time. */ + dw2_asm_output_data_uleb128 ((vms_file_stats_name (files[file_idx].path, + &cdt, 0, 0, 0) == 0) + ? cdt : 0, NULL); + + /* File length in bytes. */ + dw2_asm_output_data_uleb128 ((vms_file_stats_name (files[file_idx].path, + 0, &siz, 0, 0) == 0) + ? siz : 0, NULL); +#else + output_line_string (str_form, + files[file_idx].path + dirs[dir_idx].length, + "File Entry", (unsigned) i + 1); + + /* Include directory index. */ + if (dwarf_version >= 5 && idx_form != DW_FORM_udata) + dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2, + dir_idx + idx_offset, NULL); + else + dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL); + + if (dwarf_version >= 5) + continue; + + /* Modification time. */ + dw2_asm_output_data_uleb128 (0, NULL); + + /* File length in bytes. */ + dw2_asm_output_data_uleb128 (0, NULL); +#endif /* VMS_DEBUGGING_INFO */ + } + + if (dwarf_version < 5) + dw2_asm_output_data (1, 0, "End file name table"); +} + +/* Output one line number table into the .debug_line section. */ + +static void +output_one_line_info_table (dw_line_info_table *table) +{ + char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; + unsigned int current_line = 1; + bool current_is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START; + dw_line_info_entry *ent, *prev_addr = NULL; + size_t i; + unsigned int view; + + view = 0; + + FOR_EACH_VEC_SAFE_ELT (table->entries, i, ent) + { + switch (ent->opcode) + { + case LI_set_address: + /* ??? Unfortunately, we have little choice here currently, and + must always use the most general form. GCC does not know the + address delta itself, so we can't use DW_LNS_advance_pc. Many + ports do have length attributes which will give an upper bound + on the address range. We could perhaps use length attributes + to determine when it is safe to use DW_LNS_fixed_advance_pc. */ + ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); + + view = 0; + + /* This can handle any delta. This takes + 4+DWARF2_ADDR_SIZE bytes. */ + dw2_asm_output_data (1, 0, "set address %s%s", line_label, + debug_variable_location_views + ? ", reset view to 0" : ""); + dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); + dw2_asm_output_data (1, DW_LNE_set_address, NULL); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); + + prev_addr = ent; + break; + + case LI_adv_address: + { + ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); + char prev_label[MAX_ARTIFICIAL_LABEL_BYTES]; + ASM_GENERATE_INTERNAL_LABEL (prev_label, LINE_CODE_LABEL, prev_addr->val); + + view++; + + dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, "fixed advance PC, increment view to %i", view); + dw2_asm_output_delta (2, line_label, prev_label, + "from %s to %s", prev_label, line_label); + + prev_addr = ent; + break; + } + + case LI_set_line: + if (ent->val == current_line) + { + /* We still need to start a new row, so output a copy insn. */ + dw2_asm_output_data (1, DW_LNS_copy, + "copy line %u", current_line); + } + else + { + int line_offset = ent->val - current_line; + int line_delta = line_offset - DWARF_LINE_BASE; + + current_line = ent->val; + if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) + { + /* This can handle deltas from -10 to 234, using the current + definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. + This takes 1 byte. */ + dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, + "line %u", current_line); + } + else + { + /* This can handle any delta. This takes at least 4 bytes, + depending on the value being encoded. */ + dw2_asm_output_data (1, DW_LNS_advance_line, + "advance to line %u", current_line); + dw2_asm_output_data_sleb128 (line_offset, NULL); + dw2_asm_output_data (1, DW_LNS_copy, NULL); + } + } + break; + + case LI_set_file: + dw2_asm_output_data (1, DW_LNS_set_file, "set file %u", ent->val); + dw2_asm_output_data_uleb128 (ent->val, "%u", ent->val); + break; + + case LI_set_column: + dw2_asm_output_data (1, DW_LNS_set_column, "column %u", ent->val); + dw2_asm_output_data_uleb128 (ent->val, "%u", ent->val); + break; + + case LI_negate_stmt: + current_is_stmt = !current_is_stmt; + dw2_asm_output_data (1, DW_LNS_negate_stmt, + "is_stmt %d", current_is_stmt); + break; + + case LI_set_prologue_end: + dw2_asm_output_data (1, DW_LNS_set_prologue_end, + "set prologue end"); + break; + + case LI_set_epilogue_begin: + dw2_asm_output_data (1, DW_LNS_set_epilogue_begin, + "set epilogue begin"); + break; + + case LI_set_discriminator: + dw2_asm_output_data (1, 0, "discriminator %u", ent->val); + dw2_asm_output_data_uleb128 (1 + size_of_uleb128 (ent->val), NULL); + dw2_asm_output_data (1, DW_LNE_set_discriminator, NULL); + dw2_asm_output_data_uleb128 (ent->val, NULL); + break; + } + } + + /* Emit debug info for the address of the end of the table. */ + dw2_asm_output_data (1, 0, "set address %s", table->end_label); + dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); + dw2_asm_output_data (1, DW_LNE_set_address, NULL); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, table->end_label, NULL); + + dw2_asm_output_data (1, 0, "end sequence"); + dw2_asm_output_data_uleb128 (1, NULL); + dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); +} + +static unsigned int output_line_info_generation; + +/* Output the source line number correspondence information. This + information goes into the .debug_line section. */ + +static void +output_line_info (bool prologue_only) +{ + char l1[MAX_ARTIFICIAL_LABEL_BYTES], l2[MAX_ARTIFICIAL_LABEL_BYTES]; + char p1[MAX_ARTIFICIAL_LABEL_BYTES], p2[MAX_ARTIFICIAL_LABEL_BYTES]; + bool saw_one = false; + int opc; + + ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, + output_line_info_generation); + ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, + output_line_info_generation); + ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, + output_line_info_generation); + ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, + output_line_info_generation++); + + if (!XCOFF_DEBUGGING_INFO ) + { + if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_delta (dwarf_offset_size, l2, l1, + "Length of Source Line Info"); + } + + ASM_OUTPUT_LABEL (asm_out_file, l1); + + output_dwarf_version (); + if (dwarf_version >= 5) + { + dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); + dw2_asm_output_data (1, 0, "Segment Size"); + } + dw2_asm_output_delta (dwarf_offset_size, p2, p1, "Prolog Length"); + ASM_OUTPUT_LABEL (asm_out_file, p1); + + /* Define the architecture-dependent minimum instruction length (in bytes). + In this implementation of DWARF, this field is used for information + purposes only. Since GCC generates assembly language, we have no + a priori knowledge of how many instruction bytes are generated for each + source line, and therefore can use only the DW_LNE_set_address and + DW_LNS_fixed_advance_pc line information commands. Accordingly, we fix + this as '1', which is "correct enough" for all architectures, + and don't let the target override. */ + dw2_asm_output_data (1, 1, "Minimum Instruction Length"); + + if (dwarf_version >= 4) + dw2_asm_output_data (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN, + "Maximum Operations Per Instruction"); + dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START, + "Default is_stmt_start flag"); + dw2_asm_output_data (1, DWARF_LINE_BASE, + "Line Base Value (Special Opcodes)"); + dw2_asm_output_data (1, DWARF_LINE_RANGE, + "Line Range Value (Special Opcodes)"); + dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE, + "Special Opcode Base"); + + for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; opc++) + { + int n_op_args; + switch (opc) + { + case DW_LNS_advance_pc: + case DW_LNS_advance_line: + case DW_LNS_set_file: + case DW_LNS_set_column: + case DW_LNS_fixed_advance_pc: + case DW_LNS_set_isa: + n_op_args = 1; + break; + default: + n_op_args = 0; + break; + } + + dw2_asm_output_data (1, n_op_args, "opcode: %#x has %d args", + opc, n_op_args); + } + + /* Write out the information about the files we use. */ + output_file_names (); + ASM_OUTPUT_LABEL (asm_out_file, p2); + if (prologue_only) + { + /* Output the marker for the end of the line number info. */ + ASM_OUTPUT_LABEL (asm_out_file, l2); + return; + } + + if (separate_line_info) + { + dw_line_info_table *table; + size_t i; + + FOR_EACH_VEC_ELT (*separate_line_info, i, table) + if (table->in_use) + { + output_one_line_info_table (table); + saw_one = true; + } + } + if (cold_text_section_line_info && cold_text_section_line_info->in_use) + { + output_one_line_info_table (cold_text_section_line_info); + saw_one = true; + } + + /* ??? Some Darwin linkers crash on a .debug_line section with no + sequences. Further, merely a DW_LNE_end_sequence entry is not + sufficient -- the address column must also be initialized. + Make sure to output at least one set_address/end_sequence pair, + choosing .text since that section is always present. */ + if (text_section_line_info->in_use || !saw_one) + output_one_line_info_table (text_section_line_info); + + /* Output the marker for the end of the line number info. */ + ASM_OUTPUT_LABEL (asm_out_file, l2); +} + +unsigned long debug_line_offset=0; + +static void +output_line_string_to_object_file (enum dwarf_form form, const char *str, + const char *entry_kind, unsigned int idx) +{ + static long debug_line_str_offset = 0; + struct lto_simple_object *lo = (struct lto_simple_object *) lto_get_current_out_file (); + switch (form) + { + case DW_FORM_string: + debug_line_offset += output_nstring_to_object_file(str, -1); + break; + case DW_FORM_line_strp: + if (!debug_line_str_hash) + debug_line_str_hash + = hash_table::create_ggc (10); + + struct indirect_string_node *node; + node = find_AT_string_in_table (str, debug_line_str_hash); + set_indirect_string (node); + node->form = form; + simple_object_write_add_relocation(lo->section, debug_line_offset, + debug_line_str_offset, ".gnu.debuglto_.debug_line_str", 5); + debug_line_offset += output_data_to_object_file(dwarf_offset_size, 0); + debug_line_str_offset += strlen(node->str) + 1; + //Add relocations + // dw2_asm_output_offset (dwarf_offset_size, node->label, + // debug_line_str_section, "%s: %#x: \"%s\"", + // entry_kind, 0, node->str); + break; + default: + gcc_unreachable (); + } +} + +static void +output_file_names_to_object_file (void) +{ + struct file_name_acquire_data fnad; + int numfiles; + struct file_info *files; + struct dir_info *dirs; + int *saved; + int *savehere; + int *backmap; + int ndirs; + int idx_offset; + int i; + + if (!last_emitted_file) + { + if (dwarf_version >= 5) + { + const char *comp_dir = comp_dir_string (); + if (comp_dir == NULL) + comp_dir = ""; + debug_line_offset += output_data_to_object_file(1,1); + enum dwarf_form str_form = DW_FORM_string; + if (DWARF5_USE_DEBUG_LINE_STR) + str_form = DW_FORM_line_strp; + debug_line_offset += output_data_uleb128_to_object_file (DW_LNCT_path); + debug_line_offset += output_data_uleb128_to_object_file (str_form); + debug_line_offset += output_data_uleb128_to_object_file (1); + if (str_form == DW_FORM_string) + output_nstring_to_object_file(comp_dir, -1); + else + output_line_string_to_object_file (str_form, comp_dir, "Directory Entry", 0); + + const char *filename0 = get_AT_string (comp_unit_die (), DW_AT_name); + if (filename0 == NULL) + filename0 = ""; +#ifdef VMS_DEBUGGING_INFO + debug_line_offset += output_data_to_object_file(1, 4); +#else + debug_line_offset += output_data_to_object_file(1, 2); +#endif + debug_line_offset += output_data_uleb128_to_object_file(DW_LNCT_path); + debug_line_offset += output_data_uleb128_to_object_file(str_form); + debug_line_offset += output_data_uleb128_to_object_file(DW_LNCT_directory_index); + debug_line_offset += output_data_uleb128_to_object_file(DW_FORM_data1); + +#ifdef VMS_DEBUGGING_INFO + debug_line_offset += output_data_uleb128_to_object_file(DW_LNCT_timestamp); + debug_line_offset += output_data_uleb128_to_object_file(DW_FORM_udata); + debug_line_offset += output_data_uleb128_to_object_file(DW_LNCT_size); + debug_line_offset += output_data_uleb128_to_object_file(DW_FORM_udata); + +#endif + debug_line_offset += output_data_uleb128_to_object_file(1); + output_line_string_to_object_file(str_form, filename0, "File Entry", 0); + debug_line_offset += output_data_to_object_file(1, 0); + +#ifdef VMS_DEBUGGING_INFO + debug_line_offset += output_data_uleb128_to_object_file(0); + debug_line_offset += output_data_uleb128_to_object_file(0); + +#endif + } + else + { + debug_line_offset += output_data_to_object_file(1, 0); + debug_line_offset += output_data_to_object_file(1, 0); + + } + return; + } + + numfiles = last_emitted_file->emitted_number; + + /* Allocate the various arrays we need. */ + files = XALLOCAVEC (struct file_info, numfiles); + dirs = XALLOCAVEC (struct dir_info, numfiles); + + fnad.files = files; + fnad.used_files = 0; + fnad.max_files = numfiles; + file_table->traverse (&fnad); + gcc_assert (fnad.used_files == fnad.max_files); + + qsort (files, numfiles, sizeof (files[0]), file_info_cmp); + + /* Find all the different directories used. */ + dirs[0].path = files[0].path; + dirs[0].length = files[0].fname - files[0].path; + dirs[0].prefix = -1; + dirs[0].count = 1; + dirs[0].dir_idx = 0; + files[0].dir_idx = 0; + ndirs = 1; + + for (i = 1; i < numfiles; i++) + if (files[i].fname - files[i].path == dirs[ndirs - 1].length + && memcmp (dirs[ndirs - 1].path, files[i].path, + dirs[ndirs - 1].length) == 0) + { + /* Same directory as last entry. */ + files[i].dir_idx = ndirs - 1; + ++dirs[ndirs - 1].count; + } + else + { + int j; + + /* This is a new directory. */ + dirs[ndirs].path = files[i].path; + dirs[ndirs].length = files[i].fname - files[i].path; + dirs[ndirs].count = 1; + dirs[ndirs].dir_idx = ndirs; + files[i].dir_idx = ndirs; + + /* Search for a prefix. */ + dirs[ndirs].prefix = -1; + for (j = 0; j < ndirs; j++) + if (dirs[j].length < dirs[ndirs].length + && dirs[j].length > 1 + && (dirs[ndirs].prefix == -1 + || dirs[j].length > dirs[dirs[ndirs].prefix].length) + && memcmp (dirs[j].path, dirs[ndirs].path, dirs[j].length) == 0) + dirs[ndirs].prefix = j; + + ++ndirs; + } + + /* Now to the actual work. We have to find a subset of the directories which + allow expressing the file name using references to the directory table + with the least amount of characters. We do not do an exhaustive search + where we would have to check out every combination of every single + possible prefix. Instead we use a heuristic which provides nearly optimal + results in most cases and never is much off. */ + saved = XALLOCAVEC (int, ndirs); + savehere = XALLOCAVEC (int, ndirs); + + memset (saved, '\0', ndirs * sizeof (saved[0])); + for (i = 0; i < ndirs; i++) + { + int j; + int total; + + /* We can always save some space for the current directory. But this + does not mean it will be enough to justify adding the directory. */ + savehere[i] = dirs[i].length; + total = (savehere[i] - saved[i]) * dirs[i].count; + + for (j = i + 1; j < ndirs; j++) + { + savehere[j] = 0; + if (saved[j] < dirs[i].length) + { + /* Determine whether the dirs[i] path is a prefix of the + dirs[j] path. */ + int k; + + k = dirs[j].prefix; + while (k != -1 && k != (int) i) + k = dirs[k].prefix; + + if (k == (int) i) + { + /* Yes it is. We can possibly save some memory by + writing the filenames in dirs[j] relative to + dirs[i]. */ + savehere[j] = dirs[i].length; + total += (savehere[j] - saved[j]) * dirs[j].count; + } + } + } + + /* Check whether we can save enough to justify adding the dirs[i] + directory. */ + if (total > dirs[i].length + 1) + { + /* It's worthwhile adding. */ + for (j = i; j < ndirs; j++) + if (savehere[j] > 0) + { + /* Remember how much we saved for this directory so far. */ + saved[j] = savehere[j]; + + /* Remember the prefix directory. */ + dirs[j].dir_idx = i; + } + } + } + + /* Emit the directory name table. */ + idx_offset = dirs[0].length > 0 ? 1 : 0; + enum dwarf_form str_form = DW_FORM_string; + enum dwarf_form idx_form = DW_FORM_udata; + if (dwarf_version >= 5) + { + const char *comp_dir = comp_dir_string (); + if (comp_dir == NULL) + comp_dir = ""; + debug_line_offset += output_data_to_object_file(1, 1); + + if (DWARF5_USE_DEBUG_LINE_STR) + str_form = DW_FORM_line_strp; + debug_line_offset += output_data_uleb128_to_object_file(DW_LNCT_path); + debug_line_offset += output_data_uleb128_to_object_file(str_form); + debug_line_offset += output_data_uleb128_to_object_file(ndirs + idx_offset); + + if (str_form == DW_FORM_string) + { + output_nstring_to_object_file(comp_dir, -1); + + for (i = 1 - idx_offset; i < ndirs; i++) //See this again + output_nstring_to_object_file(dirs[i].path, + dirs[i].length + - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR); + + } + else + { + output_line_string_to_object_file (str_form, comp_dir, "Directory Entry", 0); + + for (i = 1 - idx_offset; i < ndirs; i++) + { + const char *str + = ggc_alloc_string (dirs[i].path, + dirs[i].length + - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR); + output_line_string_to_object_file (str_form, str, "Directory Entry", + (unsigned) i + idx_offset); + } + } + } + else + { + for (i = 1 - idx_offset; i < ndirs; i++) + output_nstring_to_object_file(dirs[i].path, + dirs[i].length + - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR); + debug_line_offset += output_data_to_object_file(1, 0); + + } + + /* We have to emit them in the order of emitted_number since that's + used in the debug info generation. To do this efficiently we + generate a back-mapping of the indices first. */ + backmap = XALLOCAVEC (int, numfiles); + for (i = 0; i < numfiles; i++) + backmap[files[i].file_idx->emitted_number - 1] = i; + + if (dwarf_version >= 5) + { + const char *filename0 = get_AT_string (comp_unit_die (), DW_AT_name); + if (filename0 == NULL) + filename0 = ""; + /* DW_LNCT_directory_index can use DW_FORM_udata, DW_FORM_data1 and + DW_FORM_data2. Choose one based on the number of directories + and how much space would they occupy in each encoding. + If we have at most 256 directories, all indexes fit into + a single byte, so DW_FORM_data1 is most compact (if there + are at most 128 directories, DW_FORM_udata would be as + compact as that, but not shorter and slower to decode). */ + if (ndirs + idx_offset <= 256) + idx_form = DW_FORM_data1; + /* If there are more than 65536 directories, we have to use + DW_FORM_udata, DW_FORM_data2 can't refer to them. + Otherwise, compute what space would occupy if all the indexes + used DW_FORM_udata - sum - and compare that to how large would + be DW_FORM_data2 encoding, and pick the more efficient one. */ + else if (ndirs + idx_offset <= 65536) + { + unsigned HOST_WIDE_INT sum = 1; + for (i = 0; i < numfiles; i++) + { + int file_idx = backmap[i]; + int dir_idx = dirs[files[file_idx].dir_idx].dir_idx; + sum += size_of_uleb128 (dir_idx); + } + if (sum >= HOST_WIDE_INT_UC (2) * (numfiles + 1)) + idx_form = DW_FORM_data2; + } +#ifdef VMS_DEBUGGING_INFO + debug_line_offset += output_data_to_object_file(1, 4); +#else + debug_line_offset += output_data_to_object_file(1, 2); + +#endif + debug_line_offset += output_data_uleb128_to_object_file(DW_LNCT_path); + debug_line_offset += output_data_uleb128_to_object_file(str_form); + debug_line_offset += output_data_uleb128_to_object_file(DW_LNCT_directory_index); + debug_line_offset += output_data_uleb128_to_object_file(idx_form); + +#ifdef VMS_DEBUGGING_INFO + dw2_asm_output_data_uleb128 (DW_LNCT_timestamp); + dw2_asm_output_data_uleb128 (DW_FORM_udata); + dw2_asm_output_data_uleb128 (DW_LNCT_size); + dw2_asm_output_data_uleb128 (DW_FORM_udata); + +#endif + debug_line_offset += output_data_uleb128_to_object_file(numfiles + 1); + + + output_line_string_to_object_file (str_form, filename0, "File Entry", 0); + + + /* Include directory index. */ + if (idx_form != DW_FORM_udata) + debug_line_offset += output_data_to_object_file(idx_form == DW_FORM_data1 ? 1 : 2, 0); + else + debug_line_offset += output_data_uleb128_to_object_file(0); + +#ifdef VMS_DEBUGGING_INFO + debug_line_offset += output_data_uleb128_to_object_file(0); + debug_line_offset += output_data_uleb128_to_object_file(0); + +#endif + } + + /* Now write all the file names. */ + for (i = 0; i < numfiles; i++) + { + int file_idx = backmap[i]; + int dir_idx = dirs[files[file_idx].dir_idx].dir_idx; + +#ifdef VMS_DEBUGGING_INFO +#define MAX_VMS_VERSION_LEN 6 /* ";32768" */ + + /* Setting these fields can lead to debugger miscomparisons, + but VMS Debug requires them to be set correctly. */ + + int ver; + long long cdt; + long siz; + int maxfilelen = (strlen (files[file_idx].path) + + dirs[dir_idx].length + + MAX_VMS_VERSION_LEN + 1); + char *filebuf = XALLOCAVEC (char, maxfilelen); + + vms_file_stats_name (files[file_idx].path, 0, 0, 0, &ver); + snprintf (filebuf, maxfilelen, "%s;%d", + files[file_idx].path + dirs[dir_idx].length, ver); + + output_line_string_to_object_file (str_form, filebuf, "File Entry", (unsigned) i + 1); + /* Include directory index. */ if (dwarf_version >= 5 && idx_form != DW_FORM_udata) - dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2, - dir_idx + idx_offset, NULL); + debug_line_offset += output_data_to_object_file(idx_form == DW_FORM_data1 ? 1 : 2, dir_idx_idx_offset); + else - dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL); + debug_line_offset += output_data_uleb128_to_object_file(dir_idx + idx_offset); - /* Modification time. */ - dw2_asm_output_data_uleb128 ((vms_file_stats_name (files[file_idx].path, - &cdt, 0, 0, 0) == 0) - ? cdt : 0, NULL); + /* Modification time. */ + debug_line_offset += output_data_uleb128_to_object_file((vms_file_stats_name(files[file_idx].path, &cdt, 0, 0, 0) == 0) ? cdt : 0); + + /* File length in bytes. */ + debug_line_offset += output_data_uleb128_to_object_file((vms_file_stats_name(files[file_idx].path, 0, &siz, 0, 0) == 0) ? siz : 0); - /* File length in bytes. */ - dw2_asm_output_data_uleb128 ((vms_file_stats_name (files[file_idx].path, - 0, &siz, 0, 0) == 0) - ? siz : 0, NULL); #else - output_line_string (str_form, - files[file_idx].path + dirs[dir_idx].length, - "File Entry", (unsigned) i + 1); + output_line_string_to_object_file (str_form, + files[file_idx].path + dirs[dir_idx].length, + "File Entry", (unsigned) i + 1); /* Include directory index. */ if (dwarf_version >= 5 && idx_form != DW_FORM_udata) - dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2, - dir_idx + idx_offset, NULL); + debug_line_offset += output_data_to_object_file(idx_form == DW_FORM_data1 ? 1 : 2, dir_idx + idx_offset); + else - dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL); + debug_line_offset += output_data_uleb128_to_object_file(dir_idx + idx_offset); if (dwarf_version >= 5) continue; /* Modification time. */ - dw2_asm_output_data_uleb128 (0, NULL); + debug_line_offset += output_data_uleb128_to_object_file(0); /* File length in bytes. */ - dw2_asm_output_data_uleb128 (0, NULL); + debug_line_offset += output_data_uleb128_to_object_file(0); + #endif /* VMS_DEBUGGING_INFO */ } if (dwarf_version < 5) - dw2_asm_output_data (1, 0, "End file name table"); + debug_line_offset += output_data_to_object_file(1, 0); } - - -/* Output one line number table into the .debug_line section. */ - static void -output_one_line_info_table (dw_line_info_table *table) +modify_buffer_of_object_file (unsigned long offset, size_t size, HOST_WIDE_INT value) { - char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; - unsigned int current_line = 1; - bool current_is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START; - dw_line_info_entry *ent, *prev_addr = NULL; - size_t i; - unsigned int view; - - view = 0; - - FOR_EACH_VEC_SAFE_ELT (table->entries, i, ent) + struct lto_simple_object *lo = (struct lto_simple_object *) lto_get_current_out_file (); + unsigned char bytes[8]; + unsigned int i; + unsigned char *buff = XNEWVEC(unsigned char, size); + for (i = 0; i < 8; ++i) { - switch (ent->opcode) - { - case LI_set_address: - /* ??? Unfortunately, we have little choice here currently, and - must always use the most general form. GCC does not know the - address delta itself, so we can't use DW_LNS_advance_pc. Many - ports do have length attributes which will give an upper bound - on the address range. We could perhaps use length attributes - to determine when it is safe to use DW_LNS_fixed_advance_pc. */ - ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); - - view = 0; - - /* This can handle any delta. This takes - 4+DWARF2_ADDR_SIZE bytes. */ - dw2_asm_output_data (1, 0, "set address %s%s", line_label, - debug_variable_location_views - ? ", reset view to 0" : ""); - dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); - dw2_asm_output_data (1, DW_LNE_set_address, NULL); - dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); - - prev_addr = ent; - break; - - case LI_adv_address: - { - ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, ent->val); - char prev_label[MAX_ARTIFICIAL_LABEL_BYTES]; - ASM_GENERATE_INTERNAL_LABEL (prev_label, LINE_CODE_LABEL, prev_addr->val); - - view++; - - dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, "fixed advance PC, increment view to %i", view); - dw2_asm_output_delta (2, line_label, prev_label, - "from %s to %s", prev_label, line_label); - - prev_addr = ent; - break; - } - - case LI_set_line: - if (ent->val == current_line) - { - /* We still need to start a new row, so output a copy insn. */ - dw2_asm_output_data (1, DW_LNS_copy, - "copy line %u", current_line); - } - else - { - int line_offset = ent->val - current_line; - int line_delta = line_offset - DWARF_LINE_BASE; - - current_line = ent->val; - if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) - { - /* This can handle deltas from -10 to 234, using the current - definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. - This takes 1 byte. */ - dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, - "line %u", current_line); - } - else - { - /* This can handle any delta. This takes at least 4 bytes, - depending on the value being encoded. */ - dw2_asm_output_data (1, DW_LNS_advance_line, - "advance to line %u", current_line); - dw2_asm_output_data_sleb128 (line_offset, NULL); - dw2_asm_output_data (1, DW_LNS_copy, NULL); - } - } - break; - - case LI_set_file: - dw2_asm_output_data (1, DW_LNS_set_file, "set file %u", ent->val); - dw2_asm_output_data_uleb128 (ent->val, "%u", ent->val); - break; - - case LI_set_column: - dw2_asm_output_data (1, DW_LNS_set_column, "column %u", ent->val); - dw2_asm_output_data_uleb128 (ent->val, "%u", ent->val); - break; - - case LI_negate_stmt: - current_is_stmt = !current_is_stmt; - dw2_asm_output_data (1, DW_LNS_negate_stmt, - "is_stmt %d", current_is_stmt); - break; - - case LI_set_prologue_end: - dw2_asm_output_data (1, DW_LNS_set_prologue_end, - "set prologue end"); - break; - - case LI_set_epilogue_begin: - dw2_asm_output_data (1, DW_LNS_set_epilogue_begin, - "set epilogue begin"); - break; - - case LI_set_discriminator: - dw2_asm_output_data (1, 0, "discriminator %u", ent->val); - dw2_asm_output_data_uleb128 (1 + size_of_uleb128 (ent->val), NULL); - dw2_asm_output_data (1, DW_LNE_set_discriminator, NULL); - dw2_asm_output_data_uleb128 (ent->val, NULL); - break; - } + bytes[i] = value & 0xff; + value >>= 8; } - - /* Emit debug info for the address of the end of the table. */ - dw2_asm_output_data (1, 0, "set address %s", table->end_label); - dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); - dw2_asm_output_data (1, DW_LNE_set_address, NULL); - dw2_asm_output_addr (DWARF2_ADDR_SIZE, table->end_label, NULL); - - dw2_asm_output_data (1, 0, "end sequence"); - dw2_asm_output_data_uleb128 (1, NULL); - dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); + if (BYTES_BIG_ENDIAN) + { + for (i = size - 1; i >= 0; --i) + buff[i] = bytes[i]; + } + else + { + for (i = 0; i <= size - 1; ++i) + buff[i] = bytes[i]; + } + simple_object_modify_buffer (lo->section, offset, buff, 1); } -static unsigned int output_line_info_generation; - -/* Output the source line number correspondence information. This - information goes into the .debug_line section. */ - static void -output_line_info (bool prologue_only) +output_line_info_to_object_file (bool prologue_only) { - char l1[MAX_ARTIFICIAL_LABEL_BYTES], l2[MAX_ARTIFICIAL_LABEL_BYTES]; - char p1[MAX_ARTIFICIAL_LABEL_BYTES], p2[MAX_ARTIFICIAL_LABEL_BYTES]; + lto_obj_begin_section(".gnu.debuglto_.debug_line"); bool saw_one = false; int opc; - ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, - output_line_info_generation); - ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, - output_line_info_generation); - ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, - output_line_info_generation); - ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, - output_line_info_generation++); - if (!XCOFF_DEBUGGING_INFO) { if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) - dw2_asm_output_data (4, 0xffffffff, - "Initial length escape value indicating 64-bit DWARF extension"); - dw2_asm_output_delta (dwarf_offset_size, l2, l1, - "Length of Source Line Info"); + debug_line_offset += output_data_to_object_file (4, 0xffffffff); + // dw2_asm_output_delta (dwarf_offset_size, l2, l1, + // "Length of Source Line Info"); + debug_line_offset += output_data_to_object_file(dwarf_offset_size,0); + } - ASM_OUTPUT_LABEL (asm_out_file, l1); + debug_line_offset += output_data_to_object_file(2,dwarf_version); // output dwarf version - output_dwarf_version (); if (dwarf_version >= 5) { - dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size"); - dw2_asm_output_data (1, 0, "Segment Size"); + debug_line_offset += output_data_to_object_file (1, DWARF2_ADDR_SIZE); + debug_line_offset += output_data_to_object_file (1, 0); } - dw2_asm_output_delta (dwarf_offset_size, p2, p1, "Prolog Length"); - ASM_OUTPUT_LABEL (asm_out_file, p1); + // dw2_asm_output_delta (dwarf_offset_size, p2, p1, "Prolog Length"); + debug_line_offset += output_data_to_object_file(dwarf_offset_size,0); /* Define the architecture-dependent minimum instruction length (in bytes). In this implementation of DWARF, this field is used for information @@ -13725,19 +14264,13 @@ output_line_info (bool prologue_only) DW_LNS_fixed_advance_pc line information commands. Accordingly, we fix this as '1', which is "correct enough" for all architectures, and don't let the target override. */ - dw2_asm_output_data (1, 1, "Minimum Instruction Length"); - + debug_line_offset += output_data_to_object_file (1, 1); if (dwarf_version >= 4) - dw2_asm_output_data (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN, - "Maximum Operations Per Instruction"); - dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START, - "Default is_stmt_start flag"); - dw2_asm_output_data (1, DWARF_LINE_BASE, - "Line Base Value (Special Opcodes)"); - dw2_asm_output_data (1, DWARF_LINE_RANGE, - "Line Range Value (Special Opcodes)"); - dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE, - "Special Opcode Base"); + debug_line_offset += output_data_to_object_file (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN); + debug_line_offset += output_data_to_object_file (1, DWARF_LINE_DEFAULT_IS_STMT_START); + debug_line_offset += output_data_to_object_file (1, DWARF_LINE_BASE); + debug_line_offset += output_data_to_object_file (1, DWARF_LINE_RANGE); + debug_line_offset += output_data_to_object_file (1, DWARF_LINE_OPCODE_BASE); for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; opc++) { @@ -13757,50 +14290,18 @@ output_line_info (bool prologue_only) break; } - dw2_asm_output_data (1, n_op_args, "opcode: %#x has %d args", - opc, n_op_args); - } - - /* Write out the information about the files we use. */ - output_file_names (); - ASM_OUTPUT_LABEL (asm_out_file, p2); - if (prologue_only) - { - /* Output the marker for the end of the line number info. */ - ASM_OUTPUT_LABEL (asm_out_file, l2); - return; - } + debug_line_offset += output_data_to_object_file (1, n_op_args); - if (separate_line_info) - { - dw_line_info_table *table; - size_t i; - - FOR_EACH_VEC_ELT (*separate_line_info, i, table) - if (table->in_use) - { - output_one_line_info_table (table); - saw_one = true; - } - } - if (cold_text_section_line_info && cold_text_section_line_info->in_use) - { - output_one_line_info_table (cold_text_section_line_info); - saw_one = true; } - /* ??? Some Darwin linkers crash on a .debug_line section with no - sequences. Further, merely a DW_LNE_end_sequence entry is not - sufficient -- the address column must also be initialized. - Make sure to output at least one set_address/end_sequence pair, - choosing .text since that section is always present. */ - if (text_section_line_info->in_use || !saw_one) - output_one_line_info_table (text_section_line_info); - - /* Output the marker for the end of the line number info. */ - ASM_OUTPUT_LABEL (asm_out_file, l2); + /* Write out the information about the files we use. */ + output_file_names_to_object_file (); + /* Modify the write buffer so it holds the correct unit length */ + modify_buffer_of_object_file (0, dwarf_offset_size, debug_line_offset - 4); + /* Modify the write buffer so it holds the correct header length */ + modify_buffer_of_object_file (8, dwarf_offset_size, debug_line_offset -12); + lto_obj_end_section(); } - /* Return true if DW_AT_endianity should be emitted according to REVERSE. */ static inline bool @@ -30377,6 +30878,24 @@ output_indirect_string (indirect_string_node **h, enum dwarf_form form) return 1; } +/* A helper function for dwarf2out_finish called through + htab_traverse. Emit one queued .debug_str string directly to object file. */ + +int +output_indirect_string_to_object_file (indirect_string_node **h, enum dwarf_form form) +{ + struct indirect_string_node *node = *h; + + node->form = find_string_form (node); + if (node->form == form && node->refcount > 0) + { + void *v = NULL; + lto_obj_append_data((const void *)node->str, strlen (node->str)+1,v); + } + + return 1; +} + /* Output the indexed string table. */ static void @@ -30431,6 +30950,20 @@ output_indirect_strings (void) } } + +/* Output the indexed string table directly to object file. */ + +static void +output_indirect_strings_to_object_file (void) +{ + lto_obj_begin_section(".gnu.debuglto_.debug_str"); + if (!dwarf_split_debug_info) + debug_str_hash->traverse (DW_FORM_strp); + lto_obj_end_section(); + +} + /* Callback for htab_traverse to assign an index to an entry in the table, and to write that entry to the .debug_addr section. */ @@ -33872,7 +34405,23 @@ dwarf2out_early_finish (const char *filename) else { output_comp_unit_to_object_file(comp_unit_die(), true, NULL); - output_abbrev_section_to_object_file(); + if (vec_safe_length (abbrev_die_table) != 1) + output_abbrev_section_to_object_file(); + + output_line_info_to_object_file (true);//.debug line section + /* If we emitted any indirect strings, output the string table too. */ + if (debug_str_hash || skeleton_debug_str_hash) + output_indirect_strings_to_object_file (); //.debug_str + //.debug_line_str + if (debug_line_str_hash) + { + lto_obj_begin_section(".gnu.debuglto_.debug_line_str"); + + const enum dwarf_form form = DW_FORM_line_strp; + debug_line_str_hash->traverse (form); + lto_obj_end_section(); + } } } diff --git a/gcc/lto-object.cc b/gcc/lto-object.cc index 097c81a686e..4dcf71549e3 100644 --- a/gcc/lto-object.cc +++ b/gcc/lto-object.cc @@ -189,7 +189,7 @@ lto_obj_file_close (lto_file *file) gcc_assert (lo->base.offset == 0); /*Add __gnu_lto_slim symbol*/ - simple_object_write_add_symbol (lo->sobj_w, "__gnu_lto_slim",1,1); + simple_object_write_add_symbol (lo->sobj_w, "__gnu_lto_slim",1,1,1,1,-1,0); errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err); if (errmsg != NULL)