diff --git a/test/tools/dsymutil/ARM/dummy-debug-map.map b/test/tools/dsymutil/ARM/dummy-debug-map.map new file mode 100644 index 00000000000..aa69aeafedb --- /dev/null +++ b/test/tools/dsymutil/ARM/dummy-debug-map.map @@ -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 } +... + diff --git a/test/tools/dsymutil/ARM/scattered.c b/test/tools/dsymutil/ARM/scattered.c new file mode 100644 index 00000000000..c84a602063f --- /dev/null +++ b/test/tools/dsymutil/ARM/scattered.c @@ -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 + diff --git a/test/tools/dsymutil/Inputs/scattered-reloc/1.o b/test/tools/dsymutil/Inputs/scattered-reloc/1.o new file mode 100644 index 00000000000..df5cc9bd3e0 Binary files /dev/null and b/test/tools/dsymutil/Inputs/scattered-reloc/1.o differ diff --git a/test/tools/dsymutil/Inputs/scattered-reloc/1.s b/test/tools/dsymutil/Inputs/scattered-reloc/1.s new file mode 100644 index 00000000000..c4d3781d435 --- /dev/null +++ b/test/tools/dsymutil/Inputs/scattered-reloc/1.s @@ -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: diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index fe971e99607..1cabc9a66c3 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -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); } } }