public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][WIP] dwarf2out: extend to output debug section directly to object file during debug_early phase
@ 2023-10-23  3:36 Rishi Raj
  2023-10-23 12:48 ` Jan Hubicka
  0 siblings, 1 reply; 4+ messages in thread
From: Rishi Raj @ 2023-10-23  3:36 UTC (permalink / raw)
  To: gcc-patches, Jan Hubicka, Martin Jambor

[-- Attachment #1: Type: text/plain, Size: 70504 bytes --]

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 <rishiraj45035@gmail.com>
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 <rishiraj45035@gmail.com>
---
 .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 <rishiraj45035@gmail.com>
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 <rishiraj45035@gmail.com>
---
 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<size;i++)
+  for(size_t i=0;i<size;i++)
   {
     int byte = (value & 0x7f);
     value >>= 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<size;i++)
+  for(size_t i=0;i<size;i++)
   {
-    int byte = (value & 0x7f);
+    byte = (value & 0x7f);
     value >>= 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<indirect_string_hasher>::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<file_name_acquire_data *, file_name_acquire>
(&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<enum dwarf_form,
+     output_indirect_string_to_object_file> (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<enum dwarf_form,
+              output_indirect_string_to_object_file> (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)
  {
-- 
2.42.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-10-23 15:22 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-23  3:36 [PATCH][WIP] dwarf2out: extend to output debug section directly to object file during debug_early phase Rishi Raj
2023-10-23 12:48 ` Jan Hubicka
2023-10-23 13:15   ` Rishi Raj
2023-10-23 15:22     ` Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).