[dsymutil] Fix .debug_addr index calculation

The DW_OP_addrx operation encodes a zero-based index into the
.debug_addr section. The index is relative to the DW_AT_addr_base
attribute of the associated compilation unit. In order to compute the
offset into the .debug_addr section and find the associated relocation,
we need to add the add the add base offset and multiply the index with
the address size.

This patch fixes a bug in this computation, where the multiplication was
omitted. This went unnoticed because for small test cases, the index for
interesting addresses (such as the main subprogram) is often zero.

rdar://110881668

Differential revision: https://reviews.llvm.org/D153162
This commit is contained in:
Jonas Devlieghere
2023-06-16 12:24:27 -07:00
parent 70b1c3999c
commit 8119ab9bf7
4 changed files with 51 additions and 3 deletions

View File

@@ -0,0 +1,45 @@
$ cat dwarf5-addrx-0x0-last.c
#include <stdio.h>
int main (int argc, char const *argv[])
{
int pass_me = argc + 10;
printf("Foo\n");
printf("Bar\n");
return 0;
}
$ clang -gdwarf-5 dwarf5-addrx-0x0-last.c -c -o dwarf5-addrx-0x0-last.o
$ clang dwarf5-addrx-0x0-last.o -o dwarf5-addrx-0x0-last.out
# Sanity check: make sure main's low PC (0x0) requires an index computation
# into the .debug_addr section.
RUN: llvm-dwarfdump -debug-addr %p/../Inputs/private/tmp/dwarf5/dwarf5-addrx-0x0-last.o | FileCheck %s --check-prefix DEBUGADDR
DEBUGADDR: Addrs: [
DEBUGADDR: 0x0000000000000054
DEBUGADDR: 0x0000000000000059
DEBUGADDR: 0x0000000000000000
DEBUGADDR: ]
RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/dwarf5/dwarf5-addrx-0x0-last.out -o %t.dSYM 2>&1 | FileCheck %s --allow-empty
RUN: llvm-dwarfdump --verify %t.dSYM 2>&1 | FileCheck %s
RUN: llvm-dwarfdump --verbose -debug-info %t.dSYM | FileCheck %s --check-prefix DEBUGINFO
RUN: llvm-dwarfdump --verbose -debug-line %t.dSYM | FileCheck %s --check-prefix DEBUGLINE
CHECK-NOT: error:
DEBUGINFO: DW_TAG_subprogram
DEBUGINFO: DW_AT_low_pc [DW_FORM_addr] (0x0000000100003f4c)
DEBUGINFO: DW_AT_high_pc [DW_FORM_data4] (0x00000054)
DEBUGINFO: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000011c] = "main")
DEBUGLINE: 0x0000000100003f4c 4 0 {{.*}} is_stmt
DEBUGLINE: 0x0000000100003f6c 5 17 {{.*}} is_stmt prologue_end
DEBUGLINE: 0x0000000100003f70 5 22 {{.*}}
DEBUGLINE: 0x0000000100003f74 5 7 {{.*}}
DEBUGLINE: 0x0000000100003f78 6 3 {{.*}} is_stmt
DEBUGLINE: 0x0000000100003f84 7 3 {{.*}} is_stmt
DEBUGLINE: 0x0000000100003f94 9 3 {{.*}} is_stmt epilogue_begin
DEBUGLINE: 0x0000000100003fa0 9 3 {{.*}} is_stmt end_sequence

View File

@@ -1081,9 +1081,12 @@ std::optional<int64_t> DwarfLinkerForBinary::AddressManager<
std::optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc);
if (std::optional<uint64_t> AddrOffsetSectionBase =
DIE.getDwarfUnit()->getAddrOffsetSectionBase()) {
uint64_t StartOffset = *AddrOffsetSectionBase + AddrValue->getRawUValue();
uint64_t EndOffset =
StartOffset + DIE.getDwarfUnit()->getAddressByteSize();
// Addrx is a index into the debug_addr section, not an offset, so we need
// to multiply by byte size.
const uint64_t ByteSize = DIE.getDwarfUnit()->getAddressByteSize();
const uint64_t StartOffset =
*AddrOffsetSectionBase + (AddrValue->getRawUValue() * ByteSize);
const uint64_t EndOffset = StartOffset + ByteSize;
return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset);
}