diff mbox series

[WIP] dwarf2out: extend to output debug section directly to object file during debug_early phase

Message ID CA+1a67NDE_iQ4d7RNVuMfwPt57-7+8+pgov=VapZ0og97+ieHg@mail.gmail.com
State New
Headers show
Series [WIP] dwarf2out: extend to output debug section directly to object file during debug_early phase | expand

Commit Message

Rishi Raj Oct. 23, 2023, 3:36 a.m. UTC
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

  {

Comments

Jan Hubicka Oct. 23, 2023, 12:48 p.m. UTC | #1
Hello,
thanks for the patch.

Overall it looks in right direction except for the code duplication in
output_die and friends.
> +/* 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);

So this basically renames dw2_asm_output_data to
output_data_to_object_file and similarly for other output functions.

What would be main problems of making dw2_asm_* functions to do the
right thing when outputting to object file?
Either by conditionals or turning them to virtual functions/hooks as
Richi suggested?

It may be performance critical how quickly we sput out the bytecode.
In future we may templateize this, but right now it is likely premature
optimization.
> 
> +struct lto_simple_object
lto_simple_object is declared in lto frontend.  Why do you need to
duplicate it here?

It looks like adding relocations should be abstracted by lto API,
so you don't need to look inside this structure that is
lto/lto-object.cc only.

> +/* Output one line number table into the .debug_line section.  */
> +
> +static void
> +output_one_line_info_table (dw_line_info_table *table)
It is hard to tell from the diff.  Did you just moved these functions
earlier in source file?

Honza
Rishi Raj Oct. 23, 2023, 1:15 p.m. UTC | #2
On Mon, 23 Oct 2023 at 18:18, Jan Hubicka <hubicka@ucw.cz> wrote:

> Hello,
> thanks for the patch.
>
> Overall it looks in right direction except for the code duplication in
> output_die and friends.
> > +/* 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);
>
> So this basically renames dw2_asm_output_data to
> output_data_to_object_file and similarly for other output functions.
>
> What would be main problems of making dw2_asm_* functions to do the
> right thing when outputting to object file?
> Either by conditionals or turning them to virtual functions/hooks as
> Richi suggested?
>
I think it's doable via conditionals. Can you explain the second approach
in more detail?


>
> It may be performance critical how quickly we sput out the bytecode.
> In future we may templateize this, but right now it is likely premature
> optimization.
>
Cool.

> >
> > +struct lto_simple_object
> lto_simple_object is declared in lto frontend.  Why do you need to
> duplicate it here?
>
> It looks like adding relocations should be abstracted by lto API,
> so you don't need to look inside this structure that is
> lto/lto-object.cc only.
>
I should have taken this approach, but instead, I exposed simple objects to
dwarf2out.
That's the reason to duplicate the above struct. I will take care of this
while refactoring
and abstracting it by lto API


>
> > +/* Output one line number table into the .debug_line section.  */
> > +
> > +static void
> > +output_one_line_info_table (dw_line_info_table *table)
> It is hard to tell from the diff.  Did you just moved these functions
> earlier in source file?
>
Yeah. I will refactor the dwarf2out soon to clear these confusions.
Jan Hubicka Oct. 23, 2023, 3:22 p.m. UTC | #3
> > > +  output_data_to_object_file (1, 0);
> > > +  output_data_to_object_file (1, 0);
> >
> > So this basically renames dw2_asm_output_data to
> > output_data_to_object_file and similarly for other output functions.
> >
> > What would be main problems of making dw2_asm_* functions to do the
> > right thing when outputting to object file?
> > Either by conditionals or turning them to virtual functions/hooks as
> > Richi suggested?
> >
> I think it's doable via conditionals. Can you explain the second approach
> in more detail?

Basically you want to have output functions
like dw2_asm_output_data to do the right thing and either store
it to the LTO simple object section or the assembly file.
So either we can add conditionals to every dw2_asm_* function needed
of the form
  if (outputting_to_lto)
     ... new code ...
  else
     ... existing code ...

Or have a virtual table with two different dw2_asm implementations.
Older GCC code uses hooks which is essencially a structure holding
function pointers, mostly because it was implemented before we converted
source base to C++. Some newer code uses virtual functions for this.
> > > +struct lto_simple_object
> > lto_simple_object is declared in lto frontend.  Why do you need to
> > duplicate it here?
> >
> > It looks like adding relocations should be abstracted by lto API,
> > so you don't need to look inside this structure that is
> > lto/lto-object.cc only.
> >
> I should have taken this approach, but instead, I exposed simple objects to
> dwarf2out.
> That's the reason to duplicate the above struct. I will take care of this
> while refactoring
> and abstracting it by lto API

Yep, this should not be hard to do.

Thanks for all the work!
Honza
> 
> 
> >
> > > +/* Output one line number table into the .debug_line section.  */
> > > +
> > > +static void
> > > +output_one_line_info_table (dw_line_info_table *table)
> > It is hard to tell from the diff.  Did you just moved these functions
> > earlier in source file?
> >
> Yeah. I will refactor the dwarf2out soon to clear these confusions.
> 
> -- 
> Rishi
> 
> 
> >
> > Honza
> >
diff mbox series

Patch

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)