Fission support for multiple CUs per DWO file
authorDavid Blaikie <dblaikie@gmail.com>
Thu, 6 Jul 2017 18:17:52 +0000 (11:17 -0700)
committerDavid Blaikie <dblaikie@gmail.com>
Thu, 6 Jul 2017 18:59:39 +0000 (11:59 -0700)
In some cases a compiler may produce a single object file (& thus single
DWO file) representing multiple source files. The most common example of
this is in whole program optimization (such as LLVM's LTO). Fission may
still be a beneficial feature to use here - to avoid the need to
read/link the debug info with system libraries and the like.

This change adds basic support for multiple CUs in a single DWO file to
support LLVM's output in this situation.

There is still outstanding work to design and implement a solution for
cross-CU references (usually using DW_FORM_ref_addr) in this scenario.
For now LLVM works around this by duplicating DIEs rather than making
cross-CU references in DWO files. This degrades debugger
behavior/quality especially for file-local entities.

2017-07-06  David Blaikie  <dblaikie@gmail.com>

* dwarf2read.c (struct dwo_file): Use a htab of dwo_unit* (rather than
a singular dwo_unit*) to support multiple CUs in the same way that
multiple TUs are supported.
(create_cus_hash_table): Replace create_dwo_cu with a function for
parsing multiple CUs from a DWO file.
(open_and_init_dwo_file): Use create_cus_hash_table rather than
create_dwo_cu.
(lookup_dwo_cutu): Lookup CU in the hash table in the dwo_file with
htab_find, rather than comparing the signature to a singleton CU in
the dwo_file.

2017-07-06  David Blaikie  <dblaikie@gmail.com>

* gdb.dwarf2/fission-multi-cu.S: Test containing multiple CUs in a DWO,
built from fissiont-multi-cu{1,2}.c.
* gdb.dwarf2/fission-multi-cu.exp: Test similar to fission-base.exp,
except putting 'main' and 'func' in separate CUs in the same DWO file.
* gdb.dwarf2/fission-multi-cu1.c: First CU for the multi-CU-single-DWO
test.
* gdb.dwarf2/fission-multi-cu2.c: Second CU in the multi-CU-single-DWO
test.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/fission-multi-cu.S [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/fission-multi-cu1.c [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/fission-multi-cu2.c [new file with mode: 0644]

index 7908142..a474077 100644 (file)
@@ -1,3 +1,16 @@
+2017-07-06  David Blaikie  <dblaikie@gmail.com>
+
+       * dwarf2read.c (struct dwo_file): Use a htab of dwo_unit* (rather than
+       a singular dwo_unit*) to support multiple CUs in the same way that
+       multiple TUs are supported.
+       (create_cus_hash_table): Replace create_dwo_cu with a function for
+       parsing multiple CUs from a DWO file.
+       (open_and_init_dwo_file): Use create_cus_hash_table rather than
+       create_dwo_cu.
+       (lookup_dwo_cutu): Lookup CU in the hash table in the dwo_file with
+       htab_find, rather than comparing the signature to a singleton CU in
+       the dwo_file.
+
 2017-07-06  Pedro Alves  <palves@redhat.com>
 
        * python/py-unwind.c (pyuw_dealloc_cache): Fix for loop condition.
index 2f70bd2..0fdcd42 100644 (file)
@@ -855,12 +855,11 @@ struct dwo_file
      sections (for lack of a better name).  */
   struct dwo_sections sections;
 
-  /* The CU in the file.
-     We only support one because having more than one requires hacking the
-     dwo_name of each to match, which is highly unlikely to happen.
-     Doing this means all TUs can share comp_dir: We also assume that
-     DW_AT_comp_dir across all TUs in a DWO file will be identical.  */
-  struct dwo_unit *cu;
+  /* The CUs in the file.
+     Each element is a struct dwo_unit. Multiple CUs per DWO are supported as
+     an extension to handle LLVM's Link Time Optimization output (where
+     multiple source files may be compiled into a single object/dwo pair). */
+  htab_t cus;
 
   /* Table of TUs in the file.
      Each element is a struct dwo_unit.  */
@@ -9700,72 +9699,75 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
                        hex_string (dwo_unit->signature));
 }
 
-/* Create the dwo_unit for the lone CU in DWO_FILE.
+/* Create the dwo_units for the CUs in a DWO_FILE.
    Note: This function processes DWO files only, not DWP files.  */
 
-static struct dwo_unit *
-create_dwo_cu (struct dwo_file *dwo_file)
+static void
+create_cus_hash_table (struct dwo_file &dwo_file, dwarf2_section_info &section,
+                      htab_t &cus_htab)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct dwarf2_section_info *section = &dwo_file->sections.info;
+  const struct dwarf2_section_info *abbrev_section = &dwo_file.sections.abbrev;
   const gdb_byte *info_ptr, *end_ptr;
-  struct create_dwo_cu_data create_dwo_cu_data;
-  struct dwo_unit *dwo_unit;
 
-  dwarf2_read_section (objfile, section);
-  info_ptr = section->buffer;
+  dwarf2_read_section (objfile, &section);
+  info_ptr = section.buffer;
 
   if (info_ptr == NULL)
-    return NULL;
+    return;
 
   if (dwarf_read_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
-                         get_section_name (section),
-                         get_section_file_name (section));
+                         get_section_name (&section),
+                         get_section_file_name (&section));
     }
 
-  create_dwo_cu_data.dwo_file = dwo_file;
-  dwo_unit = NULL;
-
-  end_ptr = info_ptr + section->size;
+  end_ptr = info_ptr + section.size;
   while (info_ptr < end_ptr)
     {
       struct dwarf2_per_cu_data per_cu;
+      struct create_dwo_cu_data create_dwo_cu_data;
+      struct dwo_unit *dwo_unit;
+      void **slot;
+      sect_offset sect_off = (sect_offset) (info_ptr - section.buffer);
 
       memset (&create_dwo_cu_data.dwo_unit, 0,
              sizeof (create_dwo_cu_data.dwo_unit));
       memset (&per_cu, 0, sizeof (per_cu));
       per_cu.objfile = objfile;
       per_cu.is_debug_types = 0;
-      per_cu.sect_off = sect_offset (info_ptr - section->buffer);
-      per_cu.section = section;
+      per_cu.sect_off = sect_offset (info_ptr - section.buffer);
+      per_cu.section = &section;
+
+      init_cutu_and_read_dies_no_follow (
+         &per_cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data);
+      info_ptr += per_cu.length;
+
+      // If the unit could not be parsed, skip it.
+      if (create_dwo_cu_data.dwo_unit.dwo_file == NULL)
+       continue;
 
-      init_cutu_and_read_dies_no_follow (&per_cu, dwo_file,
-                                        create_dwo_cu_reader,
-                                        &create_dwo_cu_data);
+      if (cus_htab == NULL)
+       cus_htab = allocate_dwo_unit_table (objfile);
 
-      if (create_dwo_cu_data.dwo_unit.dwo_file != NULL)
+      dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
+      *dwo_unit = create_dwo_cu_data.dwo_unit;
+      slot = htab_find_slot (cus_htab, dwo_unit, INSERT);
+      gdb_assert (slot != NULL);
+      if (*slot != NULL)
        {
-         /* If we've already found one, complain.  We only support one
-            because having more than one requires hacking the dwo_name of
-            each to match, which is highly unlikely to happen.  */
-         if (dwo_unit != NULL)
-           {
-             complaint (&symfile_complaints,
-                        _("Multiple CUs in DWO file %s [in module %s]"),
-                        dwo_file->dwo_name, objfile_name (objfile));
-             break;
-           }
+         const struct dwo_unit *dup_cu = (const struct dwo_unit *)*slot;
+         sect_offset dup_sect_off = dup_cu->sect_off;
 
-         dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
-         *dwo_unit = create_dwo_cu_data.dwo_unit;
+         complaint (&symfile_complaints,
+                    _("debug cu entry at offset 0x%x is duplicate to"
+                      " the entry at offset 0x%x, signature %s"),
+                    to_underlying (sect_off), to_underlying (dup_sect_off),
+                    hex_string (dwo_unit->signature));
        }
-
-      info_ptr += per_cu.length;
+      *slot = (void *)dwo_unit;
     }
-
-  return dwo_unit;
 }
 
 /* DWP file .debug_{cu,tu}_index section format:
@@ -10770,7 +10772,7 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
   bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
                         &dwo_file->sections);
 
-  dwo_file->cu = create_dwo_cu (dwo_file);
+  create_cus_hash_table (*dwo_file, dwo_file->sections.info, dwo_file->cus);
 
   create_debug_types_hash_table (dwo_file, dwo_file->sections.types,
                                 dwo_file->tus);
@@ -11137,10 +11139,14 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit,
              dwo_cutu
                = (struct dwo_unit *) htab_find (dwo_file->tus, &find_dwo_cutu);
            }
-         else if (!is_debug_types && dwo_file->cu)
+         else if (!is_debug_types && dwo_file->cus)
            {
-             if (signature == dwo_file->cu->signature)
-               dwo_cutu = dwo_file->cu;
+             struct dwo_unit find_dwo_cutu;
+
+             memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu));
+             find_dwo_cutu.signature = signature;
+             dwo_cutu = (struct dwo_unit *)htab_find (dwo_file->cus,
+                                                      &find_dwo_cutu);
            }
 
          if (dwo_cutu != NULL)
index d6a7252..8f28f44 100644 (file)
@@ -1,3 +1,14 @@
+2017-07-06  David Blaikie  <dblaikie@gmail.com>
+
+       * gdb.dwarf2/fission-multi-cu.S: Test containing multiple CUs in a DWO,
+       built from fissiont-multi-cu{1,2}.c.
+       * gdb.dwarf2/fission-multi-cu.exp: Test similar to fission-base.exp,
+       except putting 'main' and 'func' in separate CUs in the same DWO file.
+       * gdb.dwarf2/fission-multi-cu1.c: First CU for the multi-CU-single-DWO
+       test.
+       * gdb.dwarf2/fission-multi-cu2.c: Second CU in the multi-CU-single-DWO
+       test.
+
 2017-07-06  Pedro Alves  <palves@redhat.com>
 
        * gdb.python/py-unwind.exp: Test flushregs.
diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.S b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.S
new file mode 100644 (file)
index 0000000..d09a7e5
--- /dev/null
@@ -0,0 +1,374 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2017 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   This file was created by doing:
+
+   clang fission-multi-cu*.c -g -fno-split-dwarf-inlining -emit-llvm -S -c
+   llvm-link fission-multi-cu*.ll -S -o fission-multi-cu.ll
+   clang-tot fission-multi-cu.ll -gsplit-dwarf -S
+
+   and then massaging the output.
+*/
+       .text
+       .file   "llvm-link"
+       .globl  func
+       .p2align        4, 0x90
+       .type   func,@function
+func:                                   # @func
+.Lfunc_begin0:
+       .file   1 "fission-multi-cu1.c"
+       .loc    1 20 0                  # fission-multi-cu1.c:20:0
+       .cfi_startproc
+# BB#0:                                 # %entry
+       pushq   %rbp
+       .cfi_def_cfa_offset 16
+       .cfi_offset %rbp, -16
+       movq    %rsp, %rbp
+       .cfi_def_cfa_register %rbp
+       movl    %edi, -4(%rbp)
+       .loc    1 21 10 prologue_end    # fission-multi-cu1.c:21:10
+       movl    -4(%rbp), %edi
+       .loc    1 21 14 is_stmt 0       # fission-multi-cu1.c:21:14
+       addl    $1, %edi
+       .loc    1 21 3                  # fission-multi-cu1.c:21:3
+       movl    %edi, %eax
+       popq    %rbp
+       retq
+.Lfunc_end0:
+       .size   func, .Lfunc_end0-func
+       .cfi_endproc
+
+       .globl  main
+       .p2align        4, 0x90
+       .type   main,@function
+main:                                   # @main
+.Lfunc_begin1:
+       .file   2 "fission-multi-cu2.c"
+       .loc    2 23 0 is_stmt 1        # fission-multi-cu2.c:23:0
+       .cfi_startproc
+# BB#0:                                 # %entry
+       pushq   %rbp
+       .cfi_def_cfa_offset 16
+       .cfi_offset %rbp, -16
+       movq    %rsp, %rbp
+       .cfi_def_cfa_register %rbp
+       movl    $4294967295, %edi       # imm = 0xFFFFFFFF
+       .loc    2 24 3 prologue_end     # fission-multi-cu2.c:24:3
+       movb    $0, %al
+       callq   func
+       xorl    %eax, %eax
+       .loc    2 25 1                  # fission-multi-cu2.c:25:1
+       popq    %rbp
+       retq
+.Lfunc_end1:
+       .size   main, .Lfunc_end1-main
+       .cfi_endproc
+
+       .section        .debug_str,"MS",@progbits,1
+.Lskel_string0:
+       .asciz  "fission-multi-cu.dwo"  # string offset=0
+.Lskel_string1:
+       .asciz  "/tmp/src/gdb/testsuite" # string offset=21
+       .section        .debug_loc.dwo,"",@progbits
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                       # Abbreviation Code
+       .byte   17                      # DW_TAG_compile_unit
+       .byte   0                       # DW_CHILDREN_no
+       .byte   16                      # DW_AT_stmt_list
+       .byte   23                      # DW_FORM_sec_offset
+       .ascii  "\260B"                 # DW_AT_GNU_dwo_name
+       .byte   14                      # DW_FORM_strp
+       .byte   27                      # DW_AT_comp_dir
+       .byte   14                      # DW_FORM_strp
+       .ascii  "\261B"                 # DW_AT_GNU_dwo_id
+       .byte   7                       # DW_FORM_data8
+       .ascii  "\263B"                 # DW_AT_GNU_addr_base
+       .byte   23                      # DW_FORM_sec_offset
+       .byte   17                      # DW_AT_low_pc
+       .byte   1                       # DW_FORM_addr
+       .byte   18                      # DW_AT_high_pc
+       .byte   6                       # DW_FORM_data4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   0                       # EOM(3)
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .long   44                      # Length of Unit
+       .short  4                       # DWARF version number
+       .long   .debug_abbrev           # Offset Into Abbrev. Section
+       .byte   8                       # Address Size (in bytes)
+       .byte   1                       # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit
+       .long   .Lline_table_start0     # DW_AT_stmt_list
+       .long   .Lskel_string0          # DW_AT_GNU_dwo_name
+       .long   .Lskel_string1          # DW_AT_comp_dir
+       .quad   7615852067747431413     # DW_AT_GNU_dwo_id
+       .long   .debug_addr             # DW_AT_GNU_addr_base
+       .quad   .Lfunc_begin0           # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+.Lcu_begin1:
+       .long   44                      # Length of Unit
+       .short  4                       # DWARF version number
+       .long   .debug_abbrev           # Offset Into Abbrev. Section
+       .byte   8                       # Address Size (in bytes)
+       .byte   1                       # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit
+       .long   .Lline_table_start0     # DW_AT_stmt_list
+       .long   .Lskel_string0          # DW_AT_GNU_dwo_name
+       .long   .Lskel_string1          # DW_AT_comp_dir
+       .quad   2037650261599692324     # DW_AT_GNU_dwo_id
+       .long   .debug_addr             # DW_AT_GNU_addr_base
+       .quad   .Lfunc_begin1           # DW_AT_low_pc
+       .long   .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+       .section        .debug_ranges,"",@progbits
+       .section        .debug_macinfo,"",@progbits
+.Lcu_macro_begin1:
+.Lcu_macro_begin3:
+       .byte   0                       # End Of Macro List Mark
+       .section        .debug_str.dwo,"MS",@progbits,1
+.Linfo_string0:
+       .asciz  "fission-multi-cu.dwo"  # string offset=0
+.Linfo_string1:
+       .asciz  "clang version 5.0.0 (trunk 302855) (llvm/trunk 302853)" # string offset=21
+.Linfo_string2:
+       .asciz  "fission-multi-cu1.c" # string offset=76
+.Linfo_string3:
+       .asciz  "fission-multi-cu2.c" # string offset=96
+.Linfo_string4:
+       .asciz  "func"                  # string offset=116
+.Linfo_string5:
+       .asciz  "int"                   # string offset=121
+.Linfo_string6:
+       .asciz  "main"                  # string offset=125
+.Linfo_string7:
+       .asciz  "arg"                   # string offset=130
+       .section        .debug_str_offsets.dwo,"",@progbits
+       .long   0
+       .long   21
+       .long   76
+       .long   96
+       .long   116
+       .long   121
+       .long   125
+       .long   130
+       .section        .debug_info.dwo,"",@progbits
+       .long   53                      # Length of Unit
+       .short  4                       # DWARF version number
+       .long   0                       # Offset Into Abbrev. Section
+       .byte   8                       # Address Size (in bytes)
+       .byte   1                       # Abbrev [1] 0xb:0x2e DW_TAG_compile_unit
+       .byte   0                       # DW_AT_GNU_dwo_name
+       .byte   1                       # DW_AT_producer
+       .short  12                      # DW_AT_language
+       .byte   2                       # DW_AT_name
+       .quad   7615852067747431413     # DW_AT_GNU_dwo_id
+       .byte   2                       # Abbrev [2] 0x19:0x1b DW_TAG_subprogram
+       .byte   0                       # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+       .byte   1                       # DW_AT_frame_base
+       .byte   86
+       .byte   4                       # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   19                      # DW_AT_decl_line
+                                        # DW_AT_prototyped
+       .long   52                      # DW_AT_type
+                                        # DW_AT_external
+       .byte   3                       # Abbrev [3] 0x28:0xb DW_TAG_formal_parameter
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   124
+       .byte   7                       # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   19                      # DW_AT_decl_line
+       .long   52                      # DW_AT_type
+       .byte   0                       # End Of Children Mark
+       .byte   4                       # Abbrev [4] 0x34:0x4 DW_TAG_base_type
+       .byte   5                       # DW_AT_name
+       .byte   5                       # DW_AT_encoding
+       .byte   4                       # DW_AT_byte_size
+       .byte   0                       # End Of Children Mark
+       .long   41                      # Length of Unit
+       .short  4                       # DWARF version number
+       .long   0                       # Offset Into Abbrev. Section
+       .byte   8                       # Address Size (in bytes)
+       .byte   1                       # Abbrev [1] 0xb:0x22 DW_TAG_compile_unit
+       .byte   0                       # DW_AT_GNU_dwo_name
+       .byte   1                       # DW_AT_producer
+       .short  12                      # DW_AT_language
+       .byte   3                       # DW_AT_name
+       .quad   2037650261599692324     # DW_AT_GNU_dwo_id
+       .byte   5                       # Abbrev [5] 0x19:0xf DW_TAG_subprogram
+       .byte   1                       # DW_AT_low_pc
+       .long   .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+       .byte   1                       # DW_AT_frame_base
+       .byte   86
+       .byte   6                       # DW_AT_name
+       .byte   2                       # DW_AT_decl_file
+       .byte   22                      # DW_AT_decl_line
+       .long   40                      # DW_AT_type
+                                        # DW_AT_external
+       .byte   4                       # Abbrev [4] 0x28:0x4 DW_TAG_base_type
+       .byte   5                       # DW_AT_name
+       .byte   5                       # DW_AT_encoding
+       .byte   4                       # DW_AT_byte_size
+       .byte   0                       # End Of Children Mark
+       .section        .debug_abbrev.dwo,"",@progbits
+       .byte   1                       # Abbreviation Code
+       .byte   17                      # DW_TAG_compile_unit
+       .byte   1                       # DW_CHILDREN_yes
+       .ascii  "\260B"                 # DW_AT_GNU_dwo_name
+       .ascii  "\202>"                 # DW_FORM_GNU_str_index
+       .byte   37                      # DW_AT_producer
+       .ascii  "\202>"                 # DW_FORM_GNU_str_index
+       .byte   19                      # DW_AT_language
+       .byte   5                       # DW_FORM_data2
+       .byte   3                       # DW_AT_name
+       .ascii  "\202>"                 # DW_FORM_GNU_str_index
+       .ascii  "\261B"                 # DW_AT_GNU_dwo_id
+       .byte   7                       # DW_FORM_data8
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   2                       # Abbreviation Code
+       .byte   46                      # DW_TAG_subprogram
+       .byte   1                       # DW_CHILDREN_yes
+       .byte   17                      # DW_AT_low_pc
+       .ascii  "\201>"                 # DW_FORM_GNU_addr_index
+       .byte   18                      # DW_AT_high_pc
+       .byte   6                       # DW_FORM_data4
+       .byte   64                      # DW_AT_frame_base
+       .byte   24                      # DW_FORM_exprloc
+       .byte   3                       # DW_AT_name
+       .ascii  "\202>"                 # DW_FORM_GNU_str_index
+       .byte   58                      # DW_AT_decl_file
+       .byte   11                      # DW_FORM_data1
+       .byte   59                      # DW_AT_decl_line
+       .byte   11                      # DW_FORM_data1
+       .byte   39                      # DW_AT_prototyped
+       .byte   25                      # DW_FORM_flag_present
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   63                      # DW_AT_external
+       .byte   25                      # DW_FORM_flag_present
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   3                       # Abbreviation Code
+       .byte   5                       # DW_TAG_formal_parameter
+       .byte   0                       # DW_CHILDREN_no
+       .byte   2                       # DW_AT_location
+       .byte   24                      # DW_FORM_exprloc
+       .byte   3                       # DW_AT_name
+       .ascii  "\202>"                 # DW_FORM_GNU_str_index
+       .byte   58                      # DW_AT_decl_file
+       .byte   11                      # DW_FORM_data1
+       .byte   59                      # DW_AT_decl_line
+       .byte   11                      # DW_FORM_data1
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   4                       # Abbreviation Code
+       .byte   36                      # DW_TAG_base_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   3                       # DW_AT_name
+       .ascii  "\202>"                 # DW_FORM_GNU_str_index
+       .byte   62                      # DW_AT_encoding
+       .byte   11                      # DW_FORM_data1
+       .byte   11                      # DW_AT_byte_size
+       .byte   11                      # DW_FORM_data1
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   5                       # Abbreviation Code
+       .byte   46                      # DW_TAG_subprogram
+       .byte   0                       # DW_CHILDREN_no
+       .byte   17                      # DW_AT_low_pc
+       .ascii  "\201>"                 # DW_FORM_GNU_addr_index
+       .byte   18                      # DW_AT_high_pc
+       .byte   6                       # DW_FORM_data4
+       .byte   64                      # DW_AT_frame_base
+       .byte   24                      # DW_FORM_exprloc
+       .byte   3                       # DW_AT_name
+       .ascii  "\202>"                 # DW_FORM_GNU_str_index
+       .byte   58                      # DW_AT_decl_file
+       .byte   11                      # DW_FORM_data1
+       .byte   59                      # DW_AT_decl_line
+       .byte   11                      # DW_FORM_data1
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   63                      # DW_AT_external
+       .byte   25                      # DW_FORM_flag_present
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   0                       # EOM(3)
+       .section        .debug_line.dwo,"",@progbits
+.Ltmp4:
+       .long   (.Ltmp5-.Ltmp4)-4
+       .short  2
+       .long   (.Ltmp6-.Ltmp4)-10
+       .byte   1
+       .byte   1
+       .byte   -5
+       .byte   14
+       .byte   1
+       .byte   0
+       .byte   0
+.Ltmp6:
+.Ltmp5:
+       .section        .debug_addr,"",@progbits
+       .quad   .Lfunc_begin0
+       .quad   .Lfunc_begin1
+       .section        .debug_pubnames,"",@progbits
+       .long   .LpubNames_end0-.LpubNames_begin0 # Length of Public Names Info
+.LpubNames_begin0:
+       .short  2                       # DWARF Version
+       .long   .Lcu_begin0             # Offset of Compilation Unit Info
+       .long   48                      # Compilation Unit Length
+       .long   25                      # DIE offset
+       .asciz  "func"                  # External Name
+       .long   0                       # End Mark
+.LpubNames_end0:
+       .long   .LpubNames_end1-.LpubNames_begin1 # Length of Public Names Info
+.LpubNames_begin1:
+       .short  2                       # DWARF Version
+       .long   .Lcu_begin1             # Offset of Compilation Unit Info
+       .long   48                      # Compilation Unit Length
+       .long   25                      # DIE offset
+       .asciz  "main"                  # External Name
+       .long   0                       # End Mark
+.LpubNames_end1:
+       .section        .debug_pubtypes,"",@progbits
+       .long   .LpubTypes_end0-.LpubTypes_begin0 # Length of Public Types Info
+.LpubTypes_begin0:
+       .short  2                       # DWARF Version
+       .long   .Lcu_begin0             # Offset of Compilation Unit Info
+       .long   48                      # Compilation Unit Length
+       .long   52                      # DIE offset
+       .asciz  "int"                   # External Name
+       .long   0                       # End Mark
+.LpubTypes_end0:
+       .long   .LpubTypes_end1-.LpubTypes_begin1 # Length of Public Types Info
+.LpubTypes_begin1:
+       .short  2                       # DWARF Version
+       .long   .Lcu_begin1             # Offset of Compilation Unit Info
+       .long   48                      # Compilation Unit Length
+       .long   40                      # DIE offset
+       .asciz  "int"                   # External Name
+       .long   0                       # End Mark
+.LpubTypes_end1:
+
+       .ident  "clang version 5.0.0 (trunk 302855) (llvm/trunk 302853)"
+       .ident  "clang version 5.0.0 (trunk 302855) (llvm/trunk 302853)"
+       .section        ".note.GNU-stack","",@progbits
+       .section        .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp b/gdb/testsuite/gdb.dwarf2/fission-multi-cu.exp
new file mode 100644 (file)
index 0000000..1f23c5b
--- /dev/null
@@ -0,0 +1,67 @@
+# Copyright 2012-2017 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+# We run objcopy locally to split out the .dwo file.
+if [is_remote host] {
+    return 0
+}
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if ![dwarf2_support] {
+    return 0
+}
+
+# This test can only be run on x86-64 targets.
+if {![istarget x86_64-*] || ![is_lp64_target]} {
+    return 0
+}
+
+standard_testfile .S
+
+if [build_executable_from_fission_assembler \
+       "$testfile.exp" "$binfile" "$srcfile" {nodebug}] {
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+# Make sure we can find the .dwo file, regardless of whether we're
+# running in parallel mode.
+gdb_test_no_output "set debug-file-directory [file dirname $binfile]" \
+    "set debug-file-directory"
+gdb_load $binfile
+
+if ![runto_main] {
+    return -1
+}
+
+# Do a few basic things to verify we're finding the DWO debug info.
+
+gdb_test "ptype main" "type = int \\(\\)"
+gdb_test "ptype func" "type = int \\(int\\)"
+
+gdb_test "frame" "#0 *main \\(\\) at ${testfile}2\\.c:$decimal.*" \
+    "frame in main"
+
+gdb_test "break func" "Breakpoint.*at.* file .*${testfile}1\\.c, line .*"
+
+gdb_test "continue" "Breakpoint.* func \\(arg=-1\\).*" \
+    "continue to func"
+
+gdb_test "frame" "#0 *func \\(arg=-1\\) at ${testfile}1\\.c:$decimal.*" \
+    "frame in func"
diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu1.c b/gdb/testsuite/gdb.dwarf2/fission-multi-cu1.c
new file mode 100644 (file)
index 0000000..d93e2f9
--- /dev/null
@@ -0,0 +1,22 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2017 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+func (int arg)
+{
+  return arg + 1;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/fission-multi-cu2.c b/gdb/testsuite/gdb.dwarf2/fission-multi-cu2.c
new file mode 100644 (file)
index 0000000..053b3ea
--- /dev/null
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2017 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+void func ();
+
+int
+main ()
+{
+  func (-1);
+}