431 changes: 162 additions & 269 deletions lldb/source/Expression/DWARFExpression.cpp

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,8 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
*frame_base = DWARFExpression(module, data, cu);
if (lo_pc != LLDB_INVALID_ADDRESS) {
assert(lo_pc >= cu->GetBaseAddress());
frame_base->SetLocationListSlide(lo_pc -
cu->GetBaseAddress());
frame_base->SetLocationListAddresses(cu->GetBaseAddress(),
lo_pc);
} else {
set_frame_base_loclist_addr = true;
}
Expand Down Expand Up @@ -379,7 +379,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
if (set_frame_base_loclist_addr) {
dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
assert(lowest_range_pc >= cu->GetBaseAddress());
frame_base->SetLocationListSlide(lowest_range_pc - cu->GetBaseAddress());
frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc);
}

if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3362,9 +3362,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
data = DataExtractor(data, offset, data.GetByteSize() - offset);
location = DWARFExpression(module, data, die.GetCU());
assert(func_low_pc != LLDB_INVALID_ADDRESS);
location.SetLocationListSlide(
func_low_pc -
attributes.CompileUnitAtIndex(i)->GetBaseAddress());
location.SetLocationListAddresses(
attributes.CompileUnitAtIndex(i)->GetBaseAddress(),
func_low_pc);
}
}
} break;
Expand Down
30 changes: 30 additions & 0 deletions lldb/test/Shell/SymbolFile/DWARF/Inputs/debug_loc-aslr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--- !minidump
Streams:
- Type: ThreadList
Threads:
- Thread Id: 0x00003E81
Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B001000000000006CAE000000006B7FC05A0000C81D415A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A2BF9E5A6B7F0000000000000000000000000000000000008850C14BFD7F00009850C14BFD7F00000100000000000000B04AC14BFD7F0000000000000000000060812D01000000000800000000000000B065E05A6B7F00008004400000000000E050C14BFD7F00000000000000000000000000000000000001004700000000007F03FFFF0000FFFFFFFFFFFF000000000000000000000000801F00006B7F00000400000000000000B84CC14BFD7F0000304D405A6B7F0000C84DC14BFD7F0000C0AA405A6B7F00004F033D0000000000B84DC14BFD7F0000E84DC14BFD7F0000000000000000000000000000000000000070E05A6B7F000078629E5A6B7F0000C81D415A6B7F0000804F9E5A6B7F00000000000001000000E603000001000000E093115A6B7F0000804EC14BFD7F0000584EC14BFD7F000099ADC05A6B7F00000100000000000000AAAAD77D0000000002000000000000000800000000000000B065E05A6B7F0000E6B7C05A6B7F0000010000006B7F0000884DC14BFD7F0000106F7C5A6B7F0000984EC14BFD7F0000488B7C5A6B7F0000C4A71CB90000000001000000000000000800000000000000B065E05A6B7F000048B6C05A6B7F0000702AE25A6B7F0000D84DC14BFD7F000030489E5A6B7F0000E84EC14BFD7F0000E05E9E5A6B7F00000991F0460000000001000000000000000800000000000000B065E05A6B7F000048B6C05A6B7F00000100000000000000284EC14BFD7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Stack:
Start of Memory Range: 0x00007FFCEB34A000
Content: DEAD
- Type: SystemInfo
Processor Arch: AMD64
Processor Level: 6
Processor Revision: 15876
Number of Processors: 40
Platform ID: Linux
CSD Version: 'Linux 3.13.0-91-generic'
CPU:
Vendor ID: GenuineIntel
Version Info: 0x00000000
Feature Info: 0x00000000
- Type: LinuxProcStatus
Text: |
Name: linux-x86_64
State: t (tracing stop)
Tgid: 29917
Ngid: 0
Pid: 29917
PPid: 29370
...
129 changes: 129 additions & 0 deletions lldb/test/Shell/SymbolFile/DWARF/debug_loc-aslr.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# This test checks the handling of location lists in the case when the module is
# not loaded at the address at which it was linked (as happens with ASLR for
# instance).

# REQUIRES: x86

# RUN: yaml2obj %S/Inputs/debug_loc-aslr.yaml >%t.dmp
# RUN: llvm-mc --triple=x86_64-pc-linux --filetype=obj %s >%t.o
# RUN: %lldb -c %t.dmp -o "image add %t.o" \
# RUN: -o "image load --file %t.o --slide 0x470000" \
# RUN: -o "thread info" -o "frame variable" -o exit | FileCheck %s

# CHECK: thread #1: tid = 16001, 0x0000000000470001 {{.*}}`_start
# CHECK: (int) x = 47
# CHECK: (int) y = 74

.text
.globl _start
_start:
nop
retq
.Lstart_end:

.section .debug_loc,"",@progbits
# This location list implicitly uses the base address of the compile unit.
.Ldebug_loc0:
.quad _start-_start
.quad .Lstart_end-_start
.short 3 # Loc expr size
.byte 8 # DW_OP_const1u
.byte 47
.byte 159 # DW_OP_stack_value
.quad 0
.quad 0

# This is an equivalent location list to the first one, but here the base
# address is set explicitly.
.Ldebug_loc1:
.quad -1
.quad _start
.quad _start-_start
.quad .Lstart_end-_start
.short 3 # Loc expr size
.byte 8 # DW_OP_const1u
.byte 74
.byte 159 # DW_OP_stack_value
.quad 0
.quad 0

.section .debug_abbrev,"",@progbits
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 1 # DW_CHILDREN_yes
.byte 37 # DW_AT_producer
.byte 8 # DW_FORM_string
.byte 19 # DW_AT_language
.byte 5 # DW_FORM_data2
.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 2 # Abbreviation Code
.byte 46 # DW_TAG_subprogram
.byte 1 # DW_CHILDREN_yes
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 6 # DW_FORM_data4
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 4 # Abbreviation Code
.byte 52 # DW_TAG_variable
.byte 0 # DW_CHILDREN_no
.byte 2 # DW_AT_location
.byte 23 # DW_FORM_sec_offset
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 73 # DW_AT_type
.byte 19 # DW_FORM_ref4
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 6 # Abbreviation Code
.byte 36 # DW_TAG_base_type
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.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 0 # EOM(3)
.section .debug_info,"",@progbits
.Lcu_begin0:
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
.Ldebug_info_start0:
.short 4 # DWARF version number
.long .debug_abbrev # Offset Into Abbrev. Section
.byte 8 # Address Size (in bytes)
.byte 1 # Abbrev [1] 0xb:0x6a DW_TAG_compile_unit
.asciz "Hand-written DWARF" # DW_AT_producer
.short 12 # DW_AT_language
.quad _start # DW_AT_low_pc
.long .Lstart_end-_start # DW_AT_high_pc
.byte 2 # Abbrev [2] 0x2a:0x43 DW_TAG_subprogram
.quad _start # DW_AT_low_pc
.long .Lstart_end-_start # DW_AT_high_pc
.asciz "_start" # DW_AT_name
.byte 4 # Abbrev [4] 0x52:0xf DW_TAG_variable
.long .Ldebug_loc0 # DW_AT_location
.asciz "x" # DW_AT_name
.long .Lint # DW_AT_type
.byte 4 # Abbrev [4] 0x52:0xf DW_TAG_variable
.long .Ldebug_loc1 # DW_AT_location
.asciz "y" # DW_AT_name
.long .Lint # DW_AT_type
.byte 0 # End Of Children Mark
.Lint:
.byte 6 # Abbrev [6] 0x6d:0x7 DW_TAG_base_type
.asciz "int" # DW_AT_name
.byte 5 # DW_AT_encoding
.byte 4 # DW_AT_byte_size
.byte 0 # End Of Children Mark
.Ldebug_info_end0:
135 changes: 111 additions & 24 deletions lldb/test/Shell/SymbolFile/DWARF/debug_loc.s
Original file line number Diff line number Diff line change
@@ -1,24 +1,82 @@
# Test debug_loc parsing, including the cases of invalid input. The exact
# Test location list handling, including the cases of invalid input. The exact
# behavior in the invalid cases is not particularly important, but it should be
# "reasonable".

# REQUIRES: x86

# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t
# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" -o exit \
# RUN: | FileCheck %s
# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s --defsym LOC=0 > %t
# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" \
# RUN: -o "image dump symfile" -o exit | FileCheck %s

# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s --defsym LOCLISTS=0 > %t
# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" \
# RUN: -o "image dump symfile" -o exit | FileCheck %s --check-prefix=CHECK --check-prefix=LOCLISTS

# CHECK-LABEL: image lookup -v -a 0
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg5 RDI,
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = ,
# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = ,

# CHECK-LABEL: image lookup -v -a 2
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX,
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = ,
# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = ,
# CHECK: Variable: {{.*}}, name = "x3", type = "int", location = DW_OP_reg1 RDX,

# CHECK-LABEL: image dump symfile
# CHECK: CompileUnit{0x00000000}
# CHECK: Function{
# CHECK: Variable{{.*}}, name = "x0", {{.*}}, scope = parameter, location =
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg5 RDI
# CHECK-NEXT: [0x0000000000000001, 0x0000000000000006): DW_OP_reg0 RAX
# CHECK: Variable{{.*}}, name = "x1", {{.*}}, scope = parameter
# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter, location =
# CHECK-NEXT: error: unexpected end of data
# CHECK: Variable{{.*}}, name = "x3", {{.*}}, scope = parameter, location =
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg1 RDX
# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter, location =
# LOCLISTS-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg2 RCX

.ifdef LOC
.macro OFFSET_PAIR lo hi
.quad \lo
.quad \hi
.endm

.macro BASE_ADDRESS base
.quad -1
.quad \base
.endm

.macro EXPR_SIZE sz
.short \sz
.endm

.macro END_OF_LIST
.quad 0
.quad 0
.endm
.endif

.ifdef LOCLISTS
.macro OFFSET_PAIR lo hi
.byte 4 # DW_LLE_offset_pair
.uleb128 \lo
.uleb128 \hi
.endm

.macro BASE_ADDRESS base
.byte 6 # DW_LLE_base_address
.quad \base
.endm

.macro EXPR_SIZE sz
.uleb128 \sz
.endm

.macro END_OF_LIST
.byte 0 # DW_LLE_end_of_list
.endm
.endif

.type f,@function
f: # @f
.Lfunc_begin0:
Expand All @@ -44,33 +102,48 @@ f: # @f
.Linfo_string4:
.asciz "int"

.ifdef LOC
.section .debug_loc,"",@progbits
.endif
.ifdef LOCLISTS
.section .debug_loclists,"",@progbits
.long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length
.Ldebug_loclist_table_start0:
.short 5 # Version
.byte 8 # Address size
.byte 0 # Segment selector size
.long 0 # Offset entry count
.endif
.Ldebug_loc0:
.quad .Lfunc_begin0-.Lfunc_begin0
.quad .Ltmp0-.Lfunc_begin0
.short 1 # Loc expr size
OFFSET_PAIR .Lfunc_begin0-.Lfunc_begin0, .Ltmp0-.Lfunc_begin0
EXPR_SIZE 1
.byte 85 # super-register DW_OP_reg5
.quad .Ltmp0-.Lfunc_begin0
.quad .Lfunc_end0-.Lfunc_begin0
.short 1 # Loc expr size
OFFSET_PAIR .Ltmp0-.Lfunc_begin0, .Lfunc_end0-.Lfunc_begin0
EXPR_SIZE 1
.byte 80 # super-register DW_OP_reg0
.quad 0
.quad 0
END_OF_LIST

.Ldebug_loc3:
.quad -1 # Select base address
.quad .Ltmp1
.quad .Ltmp1-.Ltmp1
.quad .Ltmp2-.Ltmp1
.short 1 # Loc expr size
BASE_ADDRESS .Ltmp1
OFFSET_PAIR .Ltmp1-.Ltmp1, .Ltmp2-.Ltmp1
EXPR_SIZE 1
.byte 81 # super-register DW_OP_reg1
.quad 0
.quad 0
END_OF_LIST

.ifdef LOCLISTS
.Ldebug_loc4:
.byte 3 # DW_LLE_startx_length
.uleb128 0xdead
.uleb128 1
EXPR_SIZE 1
.byte 82 # super-register DW_OP_reg2
END_OF_LIST
.endif

.Ldebug_loc2:
.quad .Lfunc_begin0-.Lfunc_begin0
.quad .Lfunc_end0-.Lfunc_begin0
.short 0xdead # Loc expr size
OFFSET_PAIR .Lfunc_begin0-.Lfunc_begin0, .Lfunc_end0-.Lfunc_begin0
EXPR_SIZE 0xdead
.Ldebug_loclist_table_end0:

.section .debug_abbrev,"",@progbits
.byte 1 # Abbreviation Code
Expand Down Expand Up @@ -123,9 +196,17 @@ f: # @f
.Lcu_begin0:
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
.Ldebug_info_start0:
.ifdef LOC
.short 4 # DWARF version number
.long .debug_abbrev # Offset Into Abbrev. Section
.byte 8 # Address Size (in bytes)
.endif
.ifdef LOCLISTS
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
.endif
.byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit
.long .Linfo_string0 # DW_AT_producer
.short 12 # DW_AT_language
Expand All @@ -150,6 +231,12 @@ f: # @f
.long .Ldebug_loc3 # DW_AT_location
.asciz "x3" # DW_AT_name
.long .Lint-.Lcu_begin0 # DW_AT_type
.ifdef LOCLISTS
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
.long .Ldebug_loc4 # DW_AT_location
.asciz "x4" # DW_AT_name
.long .Lint-.Lcu_begin0 # DW_AT_type
.endif
.byte 0 # End Of Children Mark
.Lint:
.byte 4 # Abbrev [4] 0x53:0x7 DW_TAG_base_type
Expand Down