https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78063

            Bug ID: 78063
           Summary: libbacktrace fails to handle cross CU
                    DW_AT_abstract_origin
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rguenth at gcc dot gnu.org
                CC: iant at google dot com
  Target Milestone: ---

Currently libbacktrace doesn't handle the pending early LTO debug way of
separating early debug and late debug.  We have

  Compilation Unit @ offset 0xfcc:
   Length:        0x111 (32-bit)
   Version:       4
   Abbrev Offset: 0x362
   Pointer Size:  8
 <0><fd7>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <fd8>   DW_AT_producer    : (indirect string, offset: 0x1574): GNU C11
7.0.0
 20161020 (experimental) -mtune=generic -march=x86-64 -g -O2 -O2
-fsanitize=addr
ess -flto -fno-use-linker-plugin -flto-partition=none
    <fdc>   DW_AT_language    : 12      (ANSI C99)
    <fdd>   DW_AT_name        : (indirect string, offset: 0x1523):
/space/rguent
her/src/svn/trunk/gcc/testsuite/c-c++-common/asan/misalign-1.c
...
 <1><10cb>: Abbrev Number: 14 (DW_TAG_subprogram)
    <10cc>   DW_AT_external    : 1
    <10cc>   DW_AT_name        : foo
    <10d0>   DW_AT_decl_file   : 1
    <10d1>   DW_AT_decl_line   : 9
    <10d2>   DW_AT_prototyped  : 1
    <10d2>   DW_AT_type        : <0xff6>

and

  Compilation Unit @ offset 0xe37:
   Length:        0x191 (32-bit)
   Version:       4
   Abbrev Offset: 0x296
   Pointer Size:  8
 <0><e42>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <e43>   DW_AT_producer    : (indirect string, offset: 0x13c4): GNU GIMPLE
7.
0.0 20161020 (experimental) -mtune=generic -march=x86-64 -mtune=generic
-march=x
86-64 -g -O2 -O2 -O2 -O2 -fmath-errno -fsigned-zeros -ftrapping-math -fno-trapv 
-fno-strict-overflow -fno-openmp -fno-openacc -fsanitize=address
-fno-use-linker
-plugin -flto-partition=none
    <e47>   DW_AT_language    : 12      (ANSI C99)
    <e48>   DW_AT_name        : (indirect string, offset: 0x14de): <artificial>
    <e4c>   DW_AT_comp_dir    : (indirect string, offset: 0x14eb):
/abuild/rguen
ther/obj/gcc
    <e50>   DW_AT_ranges      : 0x40
    <e54>   DW_AT_low_pc      : 0x0
    <e5c>   DW_AT_stmt_list   : 0x290
 <1><e60>: Abbrev Number: 2 (DW_TAG_imported_unit)
    <e61>   DW_AT_import      : <0xfd7> [Abbrev Number: 1]
...
 <1><e65>: Abbrev Number: 3 (DW_TAG_subprogram)
    <e66>   DW_AT_abstract_origin: <0x10cb>
    <e6a>   DW_AT_low_pc      : 0x400ac0
    <e72>   DW_AT_high_pc     : 0x59
    <e7a>   DW_AT_frame_base  : 1 byte block: 9c        (DW_OP_call_frame_cfa)
    <e7c>   DW_AT_GNU_all_call_sites: 1
    <e7c>   DW_AT_sibling     : <0xe9d>

so we run into

static int
read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
                     struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
                     const struct line_header *lhdr,
                     backtrace_error_callback error_callback, void *data,
                     struct function_vector *vec_function,
                     struct function_vector *vec_inlined)
{
...
                case DW_AT_abstract_origin:
                case DW_AT_specification:
                  if (abbrev->attrs[i].form == DW_FORM_ref_addr
                      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
                    {
                      /* This refers to an abstract origin defined in
                         some other compilation unit.  We can handle
                         this case if we must, but it's harder.  */
                      break;
                    }
                  if (val.encoding == ATTR_VAL_UINT
                      || val.encoding == ATTR_VAL_REF_UNIT)
                    {
                      const char *name;

                      name = read_referenced_name (ddata, u, val.u.uint,
                                                   error_callback, data);
                      if (name != NULL)
                        function->name = name;
                    }

which causes us to fail to specify the function name to the dwarf_lookup_pc
callback.  This causes libsanitizer to not print file/line info but fall
back to symbolic backtrace completely (it could at least preserve the
partial info I guess).  Which in turn causes most asan and tsan tests
in the testsuite to FAIL with -flto because they scan for a proper
backtrace but we get

READ of size 4 at 0x7fff24ce1c8f thread T0
    #0 0x400b18 in foo (/home/abuild/rguenther/obj/gcc/misalign-1.exe+0x400b18)
    #1 0x40092c in main
(/home/abuild/rguenther/obj/gcc/misalign-1.exe+0x40092c)

instead of the desired

READ of size 4 at 0x7fff2193ea1f thread T0
    #0 0x400b98 in foo
/space/rguenther/src/svn/trunk2/gcc/testsuite/c-c++-common/asan/misalign-1.c:11
    #1 0x4009af in main
/space/rguenther/src/svn/trunk2/gcc/testsuite/c-c++-common/asan/misalign-1.c:35

as said, libbacktrace computes file and line correctly but fails to lookup
the function DW_AT_name as that is only available in the abstract origin.

Reply via email to