[dsymutil] Support scattered relocs.

Although it seems like clang will never emit scattered relocations in
the debug information (at least I couldn't find a way), we have too
support them for the benefit of other compilers.
As clang doesn't generate them, the included testcase was produced
from hacked up assembly.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@259339 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Frederic Riss 2016-02-01 03:44:22 +00:00
parent 25f74b9089
commit f768b25cef
5 changed files with 228 additions and 2 deletions

View File

@ -0,0 +1,15 @@
# This is a dummy debug map used for some tests where the contents of the
# map are just an implementation detail. The tests wanting to use that file
# should put all there object files in an explicitely named sub-directory
# of Inputs, and they should be named 1.o, 2.o, ...
# As not finding an object file or symbols isn't a fatal error for dsymutil,
# you can extend this file with as much object files and symbols as needed.
---
triple: 'thumbv7-apple-darwin'
objects:
- filename: 1.o
symbols:
- { sym: _bar, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }
...

View File

@ -0,0 +1,12 @@
RUN: llvm-dsymutil -y %p/dummy-debug-map.map -oso-prepend-path %p/../Inputs/scattered-reloc/ -f -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
// See Inputs/scattered-reloc/scattered.s to see how this test
// actually works.
int bar = 42;
CHECK: DW_TAG_variable
CHECK-NOT: DW_TAG
CHECK: DW_AT_name{{.*}}"bar"
CHECK-NOT: DW_TAG
CHECK: DW_AT_location{{.*}}<0x05> 03 10 00 01 00

Binary file not shown.

View File

@ -0,0 +1,186 @@
# This assembly file was generated from the following trivial C code:
# $ cat scattered.c
# int bar = 42;
# $ clang -S -arch armv7 -g scattered.c
# $ clang -c -o 1.o scattered.s
#
# Then I edited the debug info bellow to change the DW_AT_location of the bar
# variable from '.long _bar' to '.long _bar + 16' in order to generate a
# scattered reloc (I do not think LLVM will generate scattered relocs in
# debug info by itself).
.section __TEXT,__text,regular,pure_instructions
.ios_version_min 5, 0
.syntax unified
.file 1 "scattered.c"
.section __DATA,__data
.globl _bar @ @bar
.p2align 2
_bar:
.long 42 @ 0x2a
.section __DWARF,__debug_str,regular,debug
Linfo_string:
.asciz "clang version 3.9.0 (trunk 259311)" @ string offset=0
.asciz "scattered.c" @ string offset=35
.asciz "/tmp" @ string offset=47
.asciz "bar" @ string offset=52
.asciz "int" @ string offset=56
.section __DWARF,__debug_loc,regular,debug
Lsection_debug_loc:
.section __DWARF,__debug_abbrev,regular,debug
Lsection_abbrev:
.byte 1 @ Abbreviation Code
.byte 17 @ DW_TAG_compile_unit
.byte 1 @ DW_CHILDREN_yes
.byte 37 @ DW_AT_producer
.byte 14 @ DW_FORM_strp
.byte 19 @ DW_AT_language
.byte 5 @ DW_FORM_data2
.byte 3 @ DW_AT_name
.byte 14 @ DW_FORM_strp
.byte 16 @ DW_AT_stmt_list
.byte 6 @ DW_FORM_data4
.byte 27 @ DW_AT_comp_dir
.byte 14 @ DW_FORM_strp
.byte 0 @ EOM(1)
.byte 0 @ EOM(2)
.byte 2 @ Abbreviation Code
.byte 52 @ DW_TAG_variable
.byte 0 @ DW_CHILDREN_no
.byte 3 @ DW_AT_name
.byte 14 @ DW_FORM_strp
.byte 73 @ DW_AT_type
.byte 19 @ DW_FORM_ref4
.byte 63 @ DW_AT_external
.byte 12 @ DW_FORM_flag
.byte 58 @ DW_AT_decl_file
.byte 11 @ DW_FORM_data1
.byte 59 @ DW_AT_decl_line
.byte 11 @ DW_FORM_data1
.byte 2 @ DW_AT_location
.byte 10 @ DW_FORM_block1
.byte 0 @ EOM(1)
.byte 0 @ EOM(2)
.byte 3 @ Abbreviation Code
.byte 36 @ DW_TAG_base_type
.byte 0 @ DW_CHILDREN_no
.byte 3 @ DW_AT_name
.byte 14 @ DW_FORM_strp
.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 __DWARF,__debug_info,regular,debug
Lsection_info:
Lcu_begin0:
.long 52 @ Length of Unit
.short 2 @ DWARF version number
Lset0 = Lsection_abbrev-Lsection_abbrev @ Offset Into Abbrev. Section
.long Lset0
.byte 4 @ Address Size (in bytes)
.byte 1 @ Abbrev [1] 0xb:0x2d DW_TAG_compile_unit
.long 0 @ DW_AT_producer
.short 12 @ DW_AT_language
.long 35 @ DW_AT_name
Lset1 = Lline_table_start0-Lsection_line @ DW_AT_stmt_list
.long Lset1
.long 47 @ DW_AT_comp_dir
.byte 2 @ Abbrev [2] 0x1e:0x12 DW_TAG_variable
.long 52 @ DW_AT_name
.long 48 @ DW_AT_type
.byte 1 @ DW_AT_external
.byte 1 @ DW_AT_decl_file
.byte 1 @ DW_AT_decl_line
.byte 5 @ DW_AT_location
.byte 3
.long _bar + 16
.byte 3 @ Abbrev [3] 0x30:0x7 DW_TAG_base_type
.long 56 @ DW_AT_name
.byte 5 @ DW_AT_encoding
.byte 4 @ DW_AT_byte_size
.byte 0 @ End Of Children Mark
.section __DWARF,__debug_ranges,regular,debug
Ldebug_range:
.section __DWARF,__debug_macinfo,regular,debug
.byte 0 @ End Of Macro List Mark
.section __DWARF,__apple_names,regular,debug
Lnames_begin:
.long 1212240712 @ Header Magic
.short 1 @ Header Version
.short 0 @ Header Hash Function
.long 1 @ Header Bucket Count
.long 1 @ Header Hash Count
.long 12 @ Header Data Length
.long 0 @ HeaderData Die Offset Base
.long 1 @ HeaderData Atom Count
.short 1 @ DW_ATOM_die_offset
.short 6 @ DW_FORM_data4
.long 0 @ Bucket 0
.long 193487034 @ Hash in Bucket 0
.long LNames0-Lnames_begin @ Offset in Bucket 0
LNames0:
.long 52 @ bar
.long 1 @ Num DIEs
.long 30
.long 0
.section __DWARF,__apple_objc,regular,debug
Lobjc_begin:
.long 1212240712 @ Header Magic
.short 1 @ Header Version
.short 0 @ Header Hash Function
.long 1 @ Header Bucket Count
.long 0 @ Header Hash Count
.long 12 @ Header Data Length
.long 0 @ HeaderData Die Offset Base
.long 1 @ HeaderData Atom Count
.short 1 @ DW_ATOM_die_offset
.short 6 @ DW_FORM_data4
.long -1 @ Bucket 0
.section __DWARF,__apple_namespac,regular,debug
Lnamespac_begin:
.long 1212240712 @ Header Magic
.short 1 @ Header Version
.short 0 @ Header Hash Function
.long 1 @ Header Bucket Count
.long 0 @ Header Hash Count
.long 12 @ Header Data Length
.long 0 @ HeaderData Die Offset Base
.long 1 @ HeaderData Atom Count
.short 1 @ DW_ATOM_die_offset
.short 6 @ DW_FORM_data4
.long -1 @ Bucket 0
.section __DWARF,__apple_types,regular,debug
Ltypes_begin:
.long 1212240712 @ Header Magic
.short 1 @ Header Version
.short 0 @ Header Hash Function
.long 1 @ Header Bucket Count
.long 1 @ Header Hash Count
.long 20 @ Header Data Length
.long 0 @ HeaderData Die Offset Base
.long 3 @ HeaderData Atom Count
.short 1 @ DW_ATOM_die_offset
.short 6 @ DW_FORM_data4
.short 3 @ DW_ATOM_die_tag
.short 5 @ DW_FORM_data2
.short 4 @ DW_ATOM_type_flags
.short 11 @ DW_FORM_data1
.long 0 @ Bucket 0
.long 193495088 @ Hash in Bucket 0
.long Ltypes0-Ltypes_begin @ Offset in Bucket 0
Ltypes0:
.long 56 @ int
.long 1 @ Num DIEs
.long 48
.short 36
.byte 0
.long 0
.subsections_via_symbols
.section __DWARF,__debug_line,regular,debug
Lsection_line:
Lline_table_start0:

View File

@ -1898,6 +1898,19 @@ findValidRelocsMachO(const object::SectionRef &Section,
uint32_t Offset = Offset64;
// Mach-o uses REL relocations, the addend is at the relocation offset.
uint64_t Addend = Data.getUnsigned(&Offset, RelocSize);
uint64_t SymAddress;
int64_t SymOffset;
if (Obj.isRelocationScattered(MachOReloc)) {
// The address of the base symbol for scattered relocations is
// stored in the reloc itself. The actual addend will store the
// base address plus the offset.
SymAddress = Obj.getScatteredRelocationValue(MachOReloc);
SymOffset = int64_t(Addend) - SymAddress;
} else {
SymAddress = Addend;
SymOffset = 0;
}
auto Sym = Reloc.getSymbol();
if (Sym != Obj.symbol_end()) {
@ -1908,11 +1921,11 @@ findValidRelocsMachO(const object::SectionRef &Section,
}
if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
} else if (const auto *Mapping = DMO.lookupObjectAddress(Addend)) {
} else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
// Do not store the addend. The addend was the address of the
// symbol in the object file, the address in the binary that is
// stored in the debug map doesn't need to be offseted.
ValidRelocs.emplace_back(Offset64, RelocSize, 0, Mapping);
ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
}
}
}