Fix breakpoint setting so it always works when there is a line entry in a compile...
authorGreg Clayton <gclayton@fb.com>
Tue, 18 Oct 2022 21:59:26 +0000 (14:59 -0700)
committerGreg Clayton <gclayton@fb.com>
Mon, 24 Oct 2022 23:28:39 +0000 (16:28 -0700)
Prior to this fix, if the compile unit function:

  void CompileUnit::ResolveSymbolContext(const SourceLocationSpec &src_location_spec, SymbolContextItem resolve_scope, SymbolContextList &sc_list);

was called with a resolve scope that wasn't just eSymbolContextLineEntry, we would end up calling:

  line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope);

This is ok as long as the line entry's base address is able to be resolved back to the same information, but there were problems when it didn't. The example I found was we have a file with a bad .debug_aranges section where the address to compile unit mapping was incomplete. When this happens, the above function call to calculate the symbol context would end up matching the module and it would NULL out the compile unit and line entry, which means we would fail to set this breakpoint. We have many other clients that ask for eSymbolContextEverything as the resolve_scope, so all other locations could end up failing as well.

The solutions is to make sure the compile unit matches the current compile unit after calling the calculate symbol context. If the compile unit is NULL, then we report an error via the module/debugger as this indicates an entry in the line table fails to resolve back to any compile unit. If the compile unit is not NULL and it differs from the current compile unit, we restore the current compile unit and line entry to ensure the call to .CalculateSymbolContext doesn't match something completely different, as can easily happen if LTO or other link time optimizations are enabled that could end up outlining or merging functions.

This patch allows breakpoint succeeding to work as expected and not get short circuited by our address lookup logic failing.

Differential Revision: https://reviews.llvm.org/D136207

lldb/source/Symbol/CompileUnit.cpp
lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
lldb/test/API/functionalities/breakpoint/breakpoint_command/bad_aranges.yaml [new file with mode: 0644]

index da9dc95..8b979d3 100644 (file)
@@ -330,14 +330,44 @@ void CompileUnit::ResolveSymbolContext(
     // If they only asked for the line entry, then we're done, we can
     // just copy that over. But if they wanted more than just the line
     // number, fill it in.
+    SymbolContext resolved_sc;
+    sc.line_entry = line_entry;
     if (resolve_scope == eSymbolContextLineEntry) {
-      sc.line_entry = line_entry;
+      sc_list.Append(sc);
     } else {
-      line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc,
+      line_entry.range.GetBaseAddress().CalculateSymbolContext(&resolved_sc,
                                                                resolve_scope);
+      // Sometimes debug info is bad and isn't able to resolve the line entry's
+      // address back to the same compile unit and/or line entry. If the compile
+      // unit changed, then revert back to just the compile unit and line entry.
+      // Prior to this fix, the above code might end up not being able to lookup
+      // the address, and then it would clear compile unit and the line entry in
+      // the symbol context and the breakpoint would fail to get set even though
+      // we have a valid line table entry in this compile unit. The address
+      // lookup can also end up finding another function in another compiler
+      // unit if the DWARF has overlappging address ranges. So if we end up with
+      // no compile unit or a different one after the above function call,
+      // revert back to the same results as if resolve_scope was set exactly to
+      // eSymbolContextLineEntry.
+      if (resolved_sc.comp_unit == this) {
+        sc_list.Append(resolved_sc);
+      } else {
+        if (resolved_sc.comp_unit == nullptr && resolved_sc.module_sp) {
+          // Only report an error if we don't map back to any compile unit. With
+          // link time optimizations, the debug info might have many compile
+          // units that have the same address range due to function outlining
+          // or other link time optimizations. If the compile unit is NULL, then
+          // address resolving is completely failing and more deserving of an
+          // error message the user can see.
+          resolved_sc.module_sp->ReportError(
+              "unable to resolve a line table file address 0x%" PRIx64 " back "
+              "to a compile unit, please file a bug and attach the address "
+              "and file.", line_entry.range.GetBaseAddress().GetFileAddress());
+        }
+        sc_list.Append(sc);
+      }
     }
 
-    sc_list.Append(sc);
     if (num_file_indexes == 1)
       line_idx = line_table->FindLineEntryIndexByFileIndex(
           line_idx + 1, file_indexes.front(), found_entry, &line_entry);
index ed1d0b1..6c0afee 100644 (file)
@@ -106,6 +106,43 @@ class BreakpointCommandTestCase(TestBase):
                 'Incorrectly resolved a breakpoint using full path "%s" with '
                 'debug info that has relative path with matching suffix' % (path))
 
+    @no_debug_info_test
+    def test_breakpoints_with_bad_aranges(self):
+        """
+            Test that we can set breakpoints in a file that has an invalid
+            .debug_aranges. Older versions of LLDB would find a line entry
+            in the line table and then would use the start address of the line
+            entry to do an address lookup on the entry from the line table. If
+            this address to symbol context lookup would fail, due to a bad
+            .debug_aranges, it would cause the breakpoint to not get resolved.
+            Verify that even in these conditions we are able to resolve a
+            breakpoint.
+
+            The "bad_aranges.yaml" contains a line table that is:
+
+            Line table for /tmp/ab/main.cpp in `a.out
+            0x0000000100003f94: /tmp/ab/main.cpp:1
+            0x0000000100003fb0: /tmp/ab/main.cpp:2:3
+            0x0000000100003fb8: /tmp/ab/main.cpp:2:3
+
+            The .debug_aranges has one range for this compile unit that is
+            invalid: [0x0000000200003f94-0x0000000200003fb8). This will cause
+            the resolving of the addresses to fail.
+        """
+        src_dir = self.getSourceDir()
+        yaml_path = os.path.join(src_dir, "bad_aranges.yaml")
+        yaml_base, ext = os.path.splitext(yaml_path)
+        obj_path = self.getBuildArtifact("a.out")
+        self.yaml2obj(yaml_path, obj_path)
+
+        # Create a target with the object file we just created from YAML
+        target = self.dbg.CreateTarget(obj_path)
+        src_path = '/tmp/ab/main.cpp'
+        bkpt = target.BreakpointCreateByLocation(src_path, 2)
+        self.assertTrue(bkpt.GetNumLocations() > 0,
+            'Couldn\'t resolve breakpoint using "%s" in executate "%s" with '
+            'debug info that has a bad .debug_aranges section' % (src_path, self.getBuildArtifact("a.out")))
+
 
     def setUp(self):
         # Call super's setUp().
diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_command/bad_aranges.yaml b/lldb/test/API/functionalities/breakpoint/breakpoint_command/bad_aranges.yaml
new file mode 100644 (file)
index 0000000..e75b810
--- /dev/null
@@ -0,0 +1,445 @@
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x100000C
+  cpusubtype:      0x0
+  filetype:        0xA
+  ncmds:           7
+  sizeofcmds:      1240
+  flags:           0x0
+  reserved:        0x0
+LoadCommands:
+  - cmd:             LC_UUID
+    cmdsize:         24
+    uuid:            030921EA-6D76-3A68-B515-386B9AF6D568
+  - cmd:             LC_BUILD_VERSION
+    cmdsize:         24
+    platform:        1
+    minos:           786432
+    sdk:             787200
+    ntools:          0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          4096
+    nsyms:           2
+    stroff:          4128
+    strsize:         28
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __PAGEZERO
+    vmaddr:          0
+    vmsize:          4294967296
+    fileoff:         0
+    filesize:        0
+    maxprot:         0
+    initprot:        0
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         232
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          16384
+    fileoff:         0
+    filesize:        0
+    maxprot:         5
+    initprot:        5
+    nsects:          2
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x100003F94
+        size:            36
+        offset:          0x0
+        align:           2
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         CFFAEDFE0C000001000000000A00000007000000D804000000000000000000001B000000
+      - sectname:        __unwind_info
+        segname:         __TEXT
+        addr:            0x100003FB8
+        size:            72
+        offset:          0x0
+        align:           2
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         CFFAEDFE0C000001000000000A00000007000000D804000000000000000000001B00000018000000030921EA6D763A68B515386B9AF6D56832000000180000000100000000000C00
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294983680
+    vmsize:          4096
+    fileoff:         4096
+    filesize:        60
+    maxprot:         1
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         792
+    segname:         __DWARF
+    vmaddr:          4294987776
+    vmsize:          4096
+    fileoff:         8192
+    filesize:        796
+    maxprot:         7
+    initprot:        3
+    nsects:          9
+    flags:           0
+    Sections:
+      - sectname:        __debug_line
+        segname:         __DWARF
+        addr:            0x100005000
+        size:            64
+        offset:          0x2000
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+      - sectname:        __debug_aranges
+        segname:         __DWARF
+        addr:            0x100005040
+        size:            48
+        offset:          0x2040
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+      - sectname:        __debug_info
+        segname:         __DWARF
+        addr:            0x100005070
+        size:            148
+        offset:          0x2070
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+      - sectname:        __debug_abbrev
+        segname:         __DWARF
+        addr:            0x100005104
+        size:            90
+        offset:          0x2104
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+      - sectname:        __debug_str
+        segname:         __DWARF
+        addr:            0x10000515E
+        size:            200
+        offset:          0x215E
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+      - sectname:        __apple_names
+        segname:         __DWARF
+        addr:            0x100005226
+        size:            60
+        offset:          0x2226
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         485341480100000001000000010000000C000000000000000100000001000600000000006A7F9A7C2C000000AB000000010000003200000000000000
+      - sectname:        __apple_namespac
+        segname:         __DWARF
+        addr:            0x100005262
+        size:            36
+        offset:          0x2262
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+      - sectname:        __apple_types
+        segname:         __DWARF
+        addr:            0x100005286
+        size:            114
+        offset:          0x2286
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         48534148010000000200000002000000180000000000000004000000010006000300050005000B000600060000000000010000003080880B6320957C440000005B000000BF0000000100000076000000240000A4283A0C00000000C3000000010000008C00000024000057D77B9300000000
+      - sectname:        __apple_objc
+        segname:         __DWARF
+        addr:            0x1000052F8
+        size:            36
+        offset:          0x22F8
+        align:           0
+        reloff:          0x0
+        nreloc:          0
+        flags:           0x0
+        reserved1:       0x0
+        reserved2:       0x0
+        reserved3:       0x0
+        content:         485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF
+LinkEditData:
+  NameList:
+    - n_strx:          2
+      n_type:          0xF
+      n_sect:          1
+      n_desc:          16
+      n_value:         4294967296
+    - n_strx:          22
+      n_type:          0xF
+      n_sect:          1
+      n_desc:          0
+      n_value:         4294983572
+  StringTable:
+    - ''
+    - ''
+    - __mh_execute_header
+    - _main
+DWARF:
+  debug_str:
+    - ''
+    - 'Apple clang version 13.1.6 (clang-1316.0.21.2)'
+    - main.cpp
+    - '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk'
+    - MacOSX.sdk
+    - '/tmp/ab'
+    - main
+    - argc
+    - argv
+    - envp
+    - int
+    - char
+  debug_abbrev:
+    - ID:              0
+      Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_producer
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_LLVM_sysroot
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_APPLE_sdk
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_stmt_list
+              Form:            DW_FORM_sec_offset
+            - Attribute:       DW_AT_comp_dir
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_low_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_high_pc
+              Form:            DW_FORM_data4
+        - Code:            0x2
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_low_pc
+              Form:            DW_FORM_addr
+            - Attribute:       DW_AT_high_pc
+              Form:            DW_FORM_data4
+            - Attribute:       DW_AT_APPLE_omit_frame_ptr
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_frame_base
+              Form:            DW_FORM_exprloc
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_decl_file
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_decl_line
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+            - Attribute:       DW_AT_external
+              Form:            DW_FORM_flag_present
+        - Code:            0x3
+          Tag:             DW_TAG_formal_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_location
+              Form:            DW_FORM_exprloc
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_decl_file
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_decl_line
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+        - Code:            0x4
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_encoding
+              Form:            DW_FORM_data1
+            - Attribute:       DW_AT_byte_size
+              Form:            DW_FORM_data1
+        - Code:            0x5
+          Tag:             DW_TAG_pointer_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+        - Code:            0x6
+          Tag:             DW_TAG_const_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_type
+              Form:            DW_FORM_ref_addr
+  debug_aranges:
+    - Length:          0x2C
+      Version:         2
+      CuOffset:        0x0
+      AddressSize:     0x8
+      Descriptors:
+        - Address:         0x200003F94
+          Length:          0x24
+  debug_info:
+    - Length:          0x90
+      Version:         4
+      AbbrevTableID:   0
+      AbbrOffset:      0x0
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x1
+          Values:
+            - Value:           0x1
+            - Value:           0x1A
+            - Value:           0x30
+            - Value:           0x39
+            - Value:           0x98
+            - Value:           0x0
+            - Value:           0xA3
+            - Value:           0x100003F94
+            - Value:           0x24
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0x100003F94
+            - Value:           0x24
+            - Value:           0x1
+            - Value:           0x1
+              BlockData:       [ 0x6F ]
+            - Value:           0xAB
+            - Value:           0x1
+            - Value:           0x1
+            - Value:           0x76
+            - Value:           0x1
+        - AbbrCode:        0x3
+          Values:
+            - Value:           0x2
+              BlockData:       [ 0x91, 0x18 ]
+            - Value:           0xB0
+            - Value:           0x1
+            - Value:           0x1
+            - Value:           0x76
+        - AbbrCode:        0x3
+          Values:
+            - Value:           0x2
+              BlockData:       [ 0x91, 0x10 ]
+            - Value:           0xB5
+            - Value:           0x1
+            - Value:           0x1
+            - Value:           0x7D
+        - AbbrCode:        0x3
+          Values:
+            - Value:           0x2
+              BlockData:       [ 0x91, 0x8 ]
+            - Value:           0xBA
+            - Value:           0x1
+            - Value:           0x1
+            - Value:           0x7D
+        - AbbrCode:        0x0
+        - AbbrCode:        0x4
+          Values:
+            - Value:           0xBF
+            - Value:           0x5
+            - Value:           0x4
+        - AbbrCode:        0x5
+          Values:
+            - Value:           0x82
+        - AbbrCode:        0x5
+          Values:
+            - Value:           0x87
+        - AbbrCode:        0x6
+          Values:
+            - Value:           0x8C
+        - AbbrCode:        0x4
+          Values:
+            - Value:           0xC3
+            - Value:           0x6
+            - Value:           0x1
+        - AbbrCode:        0x0
+  debug_line:
+    - Length:          60
+      Version:         4
+      PrologueLength:  32
+      MinInstLength:   1
+      MaxOpsPerInst:   1
+      DefaultIsStmt:   1
+      LineBase:        251
+      LineRange:       14
+      OpcodeBase:      13
+      StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
+      Files:
+        - Name:            main.cpp
+          DirIdx:          0
+          ModTime:         0
+          Length:          0
+      Opcodes:
+        - Opcode:          DW_LNS_extended_op
+          ExtLen:          9
+          SubOpcode:       DW_LNE_set_address
+          Data:            4294983572
+        - Opcode:          DW_LNS_copy
+          Data:            0
+        - Opcode:          DW_LNS_set_column
+          Data:            3
+        - Opcode:          DW_LNS_set_prologue_end
+          Data:            0
+        - Opcode:          DW_LNS_const_add_pc
+          Data:            0
+        - Opcode:          0xAD
+          Data:            0
+        - Opcode:          DW_LNS_advance_pc
+          Data:            8
+        - Opcode:          DW_LNS_extended_op
+          ExtLen:          1
+          SubOpcode:       DW_LNE_end_sequence
+          Data:            0
+...