/// Value of AT_high_pc in the input DIE
uint64_t OrigHighPc = 0;
+ /// Value of DW_AT_call_return_pc in the input DIE
+ uint64_t OrigCallReturnPc = 0;
+
/// Offset to apply to PC addresses inside a function.
int64_t PCOffset = 0;
} else if (AttrSpec.Attr == dwarf::DW_AT_call_return_pc) {
// Relocate a return PC address within a call site entry.
if (Die.getTag() == dwarf::DW_TAG_call_site)
- Addr += Info.PCOffset;
+ Addr = (Info.OrigCallReturnPc ? Info.OrigCallReturnPc : Addr) +
+ Info.PCOffset;
}
Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
// inlining function.
AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc),
std::numeric_limits<uint64_t>::max());
+ AttrInfo.OrigCallReturnPc =
+ dwarf::toAddress(InputDIE.find(dwarf::DW_AT_call_return_pc), 0);
}
// Reset the Offset to 0 as we will be working on the local copy of
--- /dev/null
+Test binaries created with the following commands:
+
+$ cat call.c
+__attribute__((noinline, noreturn)) void foo() {
+ asm volatile("" ::: "memory");
+ __builtin_unreachable();
+}
+__attribute__((noinline)) void bar() {
+ asm volatile("nop" :::);
+ foo();
+}
+
+int main() { bar(); }
+
+$ clang -g call.c -fomit-frame-pointer -c -Os -o call.o
+$ clang -g call.o -o call
+
+The test requires the return PC to match a relocation (in this case the
+DW_AT_high_pc of main). Without this change the value would get relocated
+twice.
+
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/call_return_pc/call -o %t.dSYM
+RUN: llvm-dwarfdump %t.dSYM | FileCheck %s -implicit-check-not=DW_AT_call_return_pc
+
+CHECK: DW_AT_call_return_pc (0x0000000100000f72)
+CHECK: DW_AT_call_return_pc (0x0000000100000f78)