Skip to content

Commit 7f3000f

Browse files
committed
[dsymutil] Account for DW_OP_convert being CU relative
Currently, dsymutil treats the DW_OP_convert operand as absolute instead of CU relative, as described by in the DWARFv5 spec, 2.5.1.6: "[DW_OP_convert] takes one operand, which is an unsigned LEB128 integer that represents the offset of a debugging information entry in the current compilation unit" This patch makes dsymutil correctly treat the offset as CU relative, preventing a crash when there are multiple compilation units. Big thanks to Akira Hatanaka for figuring out this issue and providing both a reduced test case and a proposed fix.
1 parent 61ace8f commit 7f3000f

File tree

4 files changed

+50
-0
lines changed

4 files changed

+50
-0
lines changed

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,7 @@ void DWARFLinker::DIECloner::cloneExpression(
10051005
// instead indicate the generic type. The same holds for
10061006
// DW_OP_reinterpret, which is currently not supported.
10071007
if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
1008+
RefOffset += Unit.getOrigUnit().getOffset();
10081009
auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
10091010
CompileUnit::DIEInfo &Info = Unit.getInfo(RefDie);
10101011
if (DIE *Clone = Info.Clone)
Binary file not shown.
Binary file not shown.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# To rebuild the test case:
2+
#
3+
# $ cat op-convert-offset0.c
4+
# extern int a[2];
5+
#
6+
# int foo(_Bool b) {
7+
# return b ? a[1] : a[0];
8+
# }
9+
# $ cat op-convert-offset1.c
10+
# int a[2] = {1, 2};
11+
#
12+
# int foo(_Bool);
13+
#
14+
# int main() {
15+
# return foo(0);
16+
# }
17+
# $ xcrun clang -g -O2 -c -target x86_64-apple-unknown-macho op-convert-offset1.c -emit-llvm
18+
# $ xcrun clang -g -O2 -c -target x86_64-apple-unknown-macho op-convert-offset0.c -emit-llvm
19+
# $ llvm-link op-convert-offset1.bc op-convert-offset0.bc -o op-convert-offset.ll -S
20+
# $ xcrun clang -c op-convert-offset.ll -O0 -arch x86_64
21+
# $ xcrun clang -g op-convert-offset.o -O0 -arch x86_64 -o op-convert-offset
22+
23+
RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/op-convert-offset/op-convert-offset -o %t.dSYM 2>&1
24+
RUN: llvm-dwarfdump %p/../Inputs/private/tmp/op-convert-offset/op-convert-offset.o 2>&1 | FileCheck %s --check-prefix OBJ
25+
RUN: llvm-dwarfdump %t.dSYM 2>&1 | FileCheck %s --check-prefix DSYM
26+
27+
OBJ: 0x0000007d: DW_TAG_base_type
28+
OBJ: DW_AT_name ("DW_ATE_unsigned_1")
29+
OBJ: DW_AT_encoding (DW_ATE_unsigned)
30+
OBJ: DW_AT_byte_size (0x01)
31+
32+
OBJ: 0x00000094: DW_TAG_formal_parameter
33+
OBJ: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_convert (0x0000007d) "DW_ATE_unsigned_1", DW_OP_convert (0x00000081) "DW_ATE_unsigned_8", DW_OP_stack_value)
34+
OBJ: DW_AT_name ("b")
35+
OBJ: DW_AT_decl_file ("/tmp/op-convert-offset/op-convert-offset0.c")
36+
OBJ: DW_AT_decl_line (3)
37+
OBJ: DW_AT_type (0x000000af "_Bool")
38+
39+
DSYM: 0x00000095: DW_TAG_base_type
40+
DSYM: DW_AT_name ("DW_ATE_unsigned_1")
41+
DSYM: DW_AT_encoding (DW_ATE_unsigned)
42+
DSYM: DW_AT_byte_size (0x01)
43+
44+
DSYM: 0x000000bc: DW_TAG_formal_parameter
45+
DSYM: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_convert (0x00000095) "DW_ATE_unsigned_1", DW_OP_convert (0x0000009c) "DW_ATE_unsigned_8", DW_OP_stack_value)
46+
DSYM: DW_AT_name ("b")
47+
DSYM: DW_AT_decl_file (0x00)
48+
DSYM: DW_AT_decl_line (3)
49+
DSYM: DW_AT_type (0x000000da "_Bool")

0 commit comments

Comments
 (0)