diff options
| author | Nick Kledzik <kledzik@apple.com> | 2014-11-18 00:30:17 +0000 |
|---|---|---|
| committer | Nick Kledzik <kledzik@apple.com> | 2014-11-18 00:30:17 +0000 |
| commit | 60db3549e2a2dbd21b9201256f0898d78db4daed (patch) | |
| tree | 41cdcc69e2eba76ac4b22f70b9c79b85a266a8cc | |
| parent | 218f7199ca3d6b65cd600c9fa93983d0d7173c61 (diff) | |
| download | bcm5719-llvm-60db3549e2a2dbd21b9201256f0898d78db4daed.tar.gz bcm5719-llvm-60db3549e2a2dbd21b9201256f0898d78db4daed.zip | |
[mach-o] enhance arm64 reloc parser to support local pointer relocations
The arm64 assembler almost always uses r_extern=1 relocations in which the
r_symbolnum field is the index of the symbol the relocation references. But
sometimes it will set r_extern=0 in which case the linker needs to read the
content of the reloction to determine the target.
Add test case that the r_extern=0 relocation round trips.
llvm-svn: 222198
| -rw-r--r-- | lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp | 24 | ||||
| -rw-r--r-- | lld/test/mach-o/parse-data-relocs-arm64.yaml | 141 |
2 files changed, 105 insertions, 60 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp index e83a082faa0..de97c576ecd 100644 --- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp +++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp @@ -191,7 +191,7 @@ private: void applyFixupRelocatable(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, - uint64_t inAtomAddress); + uint64_t inAtomAddress, bool targetUnnamed); // Utility functions for inspecting/updating instructions. static uint32_t setDisplacementInBranch26(uint32_t instr, int32_t disp); @@ -399,6 +399,11 @@ std::error_code ArchHandler_arm64::getReferenceInfo( return ec; *addend = *(const little64_t *)fixupContent; return std::error_code(); + case ARM64_RELOC_UNSIGNED | rLength8: + // ex: .quad Lfoo + N + *kind = pointer64; + return atomFromAddress(reloc.symbol, *(little64_t *)fixupContent, + target, addend); case ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8: // ex: .quad _foo@GOT *kind = pointer64ToGOT; @@ -482,6 +487,7 @@ void ArchHandler_arm64::generateAtomContent( for (const Reference *ref : atom) { uint32_t offset = ref->offsetInAtom(); const Atom *target = ref->target(); + bool targetUnnamed = target->name().empty(); uint64_t targetAddress = 0; if (isa<DefinedAtom>(target)) targetAddress = findAddress(*target); @@ -489,7 +495,7 @@ void ArchHandler_arm64::generateAtomContent( uint64_t fixupAddress = atomAddress + offset; if (relocatable) { applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress, - targetAddress, atomAddress); + targetAddress, atomAddress, targetUnnamed); } else { applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress); @@ -588,7 +594,8 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, - uint64_t inAtomAddress) { + uint64_t inAtomAddress, + bool targetUnnamed) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::AArch64); @@ -613,7 +620,10 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref, *loc32 = setImm12(*loc32, 0); return; case pointer64: - *loc64 = ref.addend(); + if (targetUnnamed) + *loc64 = targetAddress + ref.addend(); + else + *loc64 = ref.addend(); return; case delta64: *loc64 = ref.addend() + inAtomAddress - fixupAddress; @@ -707,7 +717,11 @@ void ArchHandler_arm64::appendSectionRelocations( ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4); return; case pointer64: - appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, + if (ref.target()->name().empty()) + appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, + ARM64_RELOC_UNSIGNED | rLength8); + else + appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_UNSIGNED | rExtern | rLength8); return; case delta64: diff --git a/lld/test/mach-o/parse-data-relocs-arm64.yaml b/lld/test/mach-o/parse-data-relocs-arm64.yaml index 2d9690fcba5..d02422f6a6f 100644 --- a/lld/test/mach-o/parse-data-relocs-arm64.yaml +++ b/lld/test/mach-o/parse-data-relocs-arm64.yaml @@ -1,5 +1,5 @@ -# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s \ -# RUN: && lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s +# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s +# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s # # Test parsing and writing of arm64 data relocations. # @@ -14,127 +14,126 @@ --- !mach-o arch: arm64 file-type: MH_OBJECT -flags: [ ] -has-UUID: false -OS: unknown +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] sections: - - segment: __TEXT - section: __text - type: S_REGULAR - attributes: [ S_ATTR_PURE_INSTRUCTIONS ] - address: 0x0000000000000000 - segment: __DATA section: __data type: S_REGULAR attributes: [ ] - alignment: 3 address: 0x0000000000000000 content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xD0, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0xFF, - 0xC8, 0xFF, 0xFF, 0xFF ] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xFF, 0xFF, + 0xB0, 0xFF, 0xFF, 0xFF ] relocations: - - offset: 0x00000038 + - offset: 0x00000050 type: ARM64_RELOC_POINTER_TO_GOT length: 2 pc-rel: true extern: true - symbol: 3 - - offset: 0x00000034 + symbol: 1 + - offset: 0x0000004C type: ARM64_RELOC_SUBTRACTOR length: 2 pc-rel: false extern: true - symbol: 2 - - offset: 0x00000034 + symbol: 1 + - offset: 0x0000004C type: ARM64_RELOC_UNSIGNED length: 2 pc-rel: false extern: true - symbol: 3 - - offset: 0x00000030 + symbol: 1 + - offset: 0x00000048 type: ARM64_RELOC_SUBTRACTOR length: 2 pc-rel: false extern: true - symbol: 2 - - offset: 0x00000030 + symbol: 1 + - offset: 0x00000048 type: ARM64_RELOC_UNSIGNED length: 2 pc-rel: false extern: true - symbol: 3 - - offset: 0x00000028 + symbol: 1 + - offset: 0x00000040 + type: ARM64_RELOC_UNSIGNED + length: 3 + pc-rel: false + extern: true + symbol: 1 + - offset: 0x00000038 + type: ARM64_RELOC_UNSIGNED + length: 3 + pc-rel: false + extern: false + symbol: 1 + - offset: 0x00000030 type: ARM64_RELOC_SUBTRACTOR length: 3 pc-rel: false extern: true - symbol: 2 - - offset: 0x00000028 + symbol: 1 + - offset: 0x00000030 type: ARM64_RELOC_UNSIGNED length: 3 pc-rel: false extern: true - symbol: 3 - - offset: 0x00000020 + symbol: 1 + - offset: 0x00000028 type: ARM64_RELOC_SUBTRACTOR length: 3 pc-rel: false extern: true - symbol: 2 - - offset: 0x00000020 + symbol: 1 + - offset: 0x00000028 type: ARM64_RELOC_UNSIGNED length: 3 pc-rel: false extern: true - symbol: 3 - - offset: 0x00000018 + symbol: 1 + - offset: 0x00000020 type: ARM64_RELOC_SUBTRACTOR length: 3 pc-rel: false extern: true - symbol: 2 - - offset: 0x00000018 + symbol: 1 + - offset: 0x00000020 type: ARM64_RELOC_UNSIGNED length: 3 pc-rel: false extern: true - symbol: 3 - - offset: 0x00000010 + symbol: 1 + - offset: 0x00000018 type: ARM64_RELOC_POINTER_TO_GOT length: 3 pc-rel: false extern: true - symbol: 3 - - offset: 0x00000008 + symbol: 1 + - offset: 0x00000010 type: ARM64_RELOC_UNSIGNED length: 3 pc-rel: false extern: true - symbol: 3 - - offset: 0x00000000 + symbol: 1 + - offset: 0x00000008 type: ARM64_RELOC_UNSIGNED length: 3 pc-rel: false extern: true - symbol: 3 + symbol: 1 local-symbols: - - name: ltmp0 - type: N_SECT - sect: 1 - value: 0x0000000000000000 - - name: ltmp1 - type: N_SECT - sect: 2 - value: 0x0000000000000000 - name: _v1 type: N_SECT - sect: 2 - value: 0x0000000000000000 + sect: 1 + value: 0x0000000000000008 undefined-symbols: - name: _foo type: N_UNDF @@ -143,13 +142,18 @@ undefined-symbols: ... # CHECK: defined-atoms: +# CHECK: - ref-name: L000 +# CHECK: type: data +# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] # CHECK: - name: _v1 # CHECK: type: data # CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 08, 00, 00, 00, # CHECK: 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, # CHECK: 00, 00, 00, 00, 00, 00, 00, 00, E0, FF, FF, FF, # CHECK: FF, FF, FF, FF, DC, FF, FF, FF, FF, FF, FF, FF, -# CHECK: D0, FF, FF, FF, CE, FF, FF, FF, C8, FF, FF, FF ] +# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00, +# CHECK: 00, 00, 00, 00, C0, FF, FF, FF, BE, FF, FF, FF, +# CHECK: B0, FF, FF, FF ] # CHECK: references: # CHECK: - kind: pointer64 # CHECK: offset: 0 @@ -175,17 +179,44 @@ undefined-symbols: # CHECK: offset: 40 # CHECK: target: _foo # CHECK: addend: 4 -# CHECK: - kind: delta32 +# CHECK: - kind: pointer64 # CHECK: offset: 48 +# CHECK: target: L000 +# CHECK-NOT: addend: +# CHECK: - kind: pointer64 +# CHECK: offset: 56 +# CHECK: target: _foo +# CHECK: addend: 4 +# CHECK: - kind: delta32 +# CHECK: offset: 64 # CHECK: target: _foo # CHECK-NOT: addend: # CHECK: - kind: delta32 -# CHECK: offset: 52 +# CHECK: offset: 68 # CHECK: target: _foo # CHECK: addend: 2 # CHECK: - kind: delta32ToGOT -# CHECK: offset: 56 +# CHECK: offset: 72 # CHECK: target: _foo # CHECK-NOT: addend: # CHECK: undefined-atoms: # CHECK: - name: _foo + + + +# .data +#Lanon: +# .quad 0 +#_v1: +# .quad _foo +# .quad _foo + 8 +# .quad _foo@GOT +# .quad _foo + 24 - . +# .quad _foo - . +# .quad _foo + 4 - . +# .quad Lanon +# .quad Lanon + 4 +# .long _foo - . +# .long _foo +2 - . +# .long _foo@GOT - . + |

