Skip to content

Commit

Permalink
[dsymutil] Account for DW_OP_convert being CU relative
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JDevlieghere committed Jul 12, 2022
1 parent 61ace8f commit 7f3000f
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions llvm/lib/DWARFLinker/DWARFLinker.cpp
Expand Up @@ -1005,6 +1005,7 @@ void DWARFLinker::DIECloner::cloneExpression(
// instead indicate the generic type. The same holds for
// DW_OP_reinterpret, which is currently not supported.
if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
RefOffset += Unit.getOrigUnit().getOffset();
auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
CompileUnit::DIEInfo &Info = Unit.getInfo(RefDie);
if (DIE *Clone = Info.Clone)
Expand Down
Binary file not shown.
Binary file not shown.
49 changes: 49 additions & 0 deletions llvm/test/tools/dsymutil/X86/op-convert-offset.test
@@ -0,0 +1,49 @@
# To rebuild the test case:
#
# $ cat op-convert-offset0.c
# extern int a[2];
#
# int foo(_Bool b) {
# return b ? a[1] : a[0];
# }
# $ cat op-convert-offset1.c
# int a[2] = {1, 2};
#
# int foo(_Bool);
#
# int main() {
# return foo(0);
# }
# $ xcrun clang -g -O2 -c -target x86_64-apple-unknown-macho op-convert-offset1.c -emit-llvm
# $ xcrun clang -g -O2 -c -target x86_64-apple-unknown-macho op-convert-offset0.c -emit-llvm
# $ llvm-link op-convert-offset1.bc op-convert-offset0.bc -o op-convert-offset.ll -S
# $ xcrun clang -c op-convert-offset.ll -O0 -arch x86_64
# $ xcrun clang -g op-convert-offset.o -O0 -arch x86_64 -o op-convert-offset

RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/op-convert-offset/op-convert-offset -o %t.dSYM 2>&1
RUN: llvm-dwarfdump %p/../Inputs/private/tmp/op-convert-offset/op-convert-offset.o 2>&1 | FileCheck %s --check-prefix OBJ
RUN: llvm-dwarfdump %t.dSYM 2>&1 | FileCheck %s --check-prefix DSYM

OBJ: 0x0000007d: DW_TAG_base_type
OBJ: DW_AT_name ("DW_ATE_unsigned_1")
OBJ: DW_AT_encoding (DW_ATE_unsigned)
OBJ: DW_AT_byte_size (0x01)

OBJ: 0x00000094: DW_TAG_formal_parameter
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)
OBJ: DW_AT_name ("b")
OBJ: DW_AT_decl_file ("/tmp/op-convert-offset/op-convert-offset0.c")
OBJ: DW_AT_decl_line (3)
OBJ: DW_AT_type (0x000000af "_Bool")

DSYM: 0x00000095: DW_TAG_base_type
DSYM: DW_AT_name ("DW_ATE_unsigned_1")
DSYM: DW_AT_encoding (DW_ATE_unsigned)
DSYM: DW_AT_byte_size (0x01)

DSYM: 0x000000bc: DW_TAG_formal_parameter
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)
DSYM: DW_AT_name ("b")
DSYM: DW_AT_decl_file (0x00)
DSYM: DW_AT_decl_line (3)
DSYM: DW_AT_type (0x000000da "_Bool")

0 comments on commit 7f3000f

Please sign in to comment.