forked from OSchip/llvm-project
[Mips] Fix handling of R_MIPS_GOT16 relocation and building local part
of GOT. * Read addend for R_MIPS_GOT16 relocation. * Put only high 16 bits of symbol + addend into GOT entries for locally visible symbols. llvm-svn: 204247
This commit is contained in:
parent
b1ba018ed2
commit
e29132d427
|
@ -78,6 +78,7 @@ private:
|
|||
break;
|
||||
case R_MIPS_HI16:
|
||||
case R_MIPS_LO16:
|
||||
case R_MIPS_GOT16:
|
||||
ref->setAddend(*(int16_t *)ap);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace elf {
|
|||
enum {
|
||||
/// \brief Do nothing but mark GOT entry as a global one.
|
||||
LLD_R_MIPS_GLOBAL_GOT = 1024,
|
||||
/// \brief Apply high 16 bits of symbol + addend.
|
||||
LLD_R_MIPS_32_HI16 = 1025,
|
||||
/// \brief The same as R_MIPS_26 but for global symbols.
|
||||
LLD_R_MIPS_GLOBAL_26 = 1026,
|
||||
/// \brief Setup hi 16 bits using the symbol this reference refers to.
|
||||
|
|
|
@ -105,6 +105,11 @@ void relocCall16(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
|
|||
applyReloc(location, G, 0xffff);
|
||||
}
|
||||
|
||||
/// \brief LLD_R_MIPS_32_HI16
|
||||
void reloc32hi16(uint8_t *location, uint64_t S, int64_t A) {
|
||||
applyReloc(location, (S + A) & 0xffff0000, 0xffffffff);
|
||||
}
|
||||
|
||||
/// \brief LLD_R_MIPS_HI16
|
||||
void relocLldHi16(uint8_t *location, uint64_t S) {
|
||||
applyReloc(location, (S + 0x8000) >> 16, 0xffff);
|
||||
|
@ -164,6 +169,9 @@ error_code MipsTargetRelocationHandler::applyRelocation(
|
|||
case LLD_R_MIPS_GLOBAL_GOT:
|
||||
// Do nothing.
|
||||
break;
|
||||
case LLD_R_MIPS_32_HI16:
|
||||
reloc32hi16(location, targetVAddress, ref.addend());
|
||||
break;
|
||||
case LLD_R_MIPS_GLOBAL_26:
|
||||
reloc26ext(location, targetVAddress, ref.addend());
|
||||
break;
|
||||
|
|
|
@ -125,8 +125,11 @@ private:
|
|||
/// \brief Owner of all the Atoms created by this pass.
|
||||
RelocationPassFile _file;
|
||||
|
||||
/// \brief Map Atoms to their GOT entries.
|
||||
llvm::DenseMap<const Atom *, GOTAtom *> _gotLocalMap;
|
||||
/// \brief Map Atoms and addend to local GOT entries.
|
||||
typedef std::pair<const Atom *, int64_t> LocalGotMapKeyT;
|
||||
llvm::DenseMap<LocalGotMapKeyT, GOTAtom *> _gotLocalMap;
|
||||
|
||||
/// \brief Map Atoms to global GOT entries.
|
||||
llvm::DenseMap<const Atom *, GOTAtom *> _gotGlobalMap;
|
||||
|
||||
/// \brief the list of local GOT atoms.
|
||||
|
@ -160,7 +163,7 @@ private:
|
|||
void handlePLT(const Reference &ref);
|
||||
void handleGOT(const Reference &ref);
|
||||
|
||||
const GOTAtom *getLocalGOTEntry(const Atom *a);
|
||||
const GOTAtom *getLocalGOTEntry(const Reference &ref);
|
||||
const GOTAtom *getGlobalGOTEntry(const Atom *a);
|
||||
const PLTAtom *getPLTEntry(const Atom *a);
|
||||
const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a);
|
||||
|
@ -302,7 +305,7 @@ void RelocationPass::handlePLT(const Reference &ref) {
|
|||
|
||||
void RelocationPass::handleGOT(const Reference &ref) {
|
||||
if (requireLocalGOT(ref.target()))
|
||||
const_cast<Reference &>(ref).setTarget(getLocalGOTEntry(ref.target()));
|
||||
const_cast<Reference &>(ref).setTarget(getLocalGOTEntry(ref));
|
||||
else
|
||||
const_cast<Reference &>(ref).setTarget(getGlobalGOTEntry(ref.target()));
|
||||
}
|
||||
|
@ -327,18 +330,23 @@ bool RelocationPass::requireLocalGOT(const Atom *a) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const GOTAtom *RelocationPass::getLocalGOTEntry(const Atom *a) {
|
||||
auto got = _gotLocalMap.find(a);
|
||||
const GOTAtom *RelocationPass::getLocalGOTEntry(const Reference &ref) {
|
||||
const Atom *a = ref.target();
|
||||
LocalGotMapKeyT key(a, ref.addend());
|
||||
|
||||
auto got = _gotLocalMap.find(key);
|
||||
if (got != _gotLocalMap.end())
|
||||
return got->second;
|
||||
|
||||
auto ga = new (_file._alloc) GOT0Atom(_file);
|
||||
_gotLocalMap[a] = ga;
|
||||
_gotLocalMap[key] = ga;
|
||||
|
||||
_localGotVector.push_back(ga);
|
||||
|
||||
if (const DefinedAtom *da = dyn_cast<DefinedAtom>(a))
|
||||
ga->addReferenceELF_Mips(R_MIPS_32, 0, da, 0);
|
||||
if (isLocal(a))
|
||||
ga->addReferenceELF_Mips(LLD_R_MIPS_32_HI16, 0, a, ref.addend());
|
||||
else
|
||||
ga->addReferenceELF_Mips(R_MIPS_32, 0, a, 0);
|
||||
|
||||
DEBUG_WITH_TYPE("MipsGOT", {
|
||||
ga->_name = "__got_";
|
||||
|
|
|
@ -58,6 +58,7 @@ const Registry::KindStrings MipsTargetHandler::kindStrings[] = {
|
|||
LLD_KIND_STRING_ENTRY(R_MIPS_COPY),
|
||||
LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_32_HI16),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_26),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_HI16),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_LO16),
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
# CHECK-GOT: section-name: .got
|
||||
# CHECK-GOT: permissions: rw-
|
||||
# CHECK-GOT: references:
|
||||
# CHECK-GOT: - kind: R_MIPS_32
|
||||
# CHECK-GOT: - kind: LLD_R_MIPS_32_HI16
|
||||
# CHECK-GOT: offset: 0
|
||||
# CHECK-GOT: target: L003
|
||||
# CHECK-GOT: - ref-name: L004
|
||||
|
@ -94,7 +94,7 @@
|
|||
# CHECK-GOT: section-name: .got
|
||||
# CHECK-GOT: permissions: rw-
|
||||
# CHECK-GOT: references:
|
||||
# CHECK-GOT: - kind: R_MIPS_32
|
||||
# CHECK-GOT: - kind: LLD_R_MIPS_32_HI16
|
||||
# CHECK-GOT: offset: 0
|
||||
# CHECK-GOT: target: L005
|
||||
# CHECK-GOT: - ref-name: L006
|
||||
|
|
|
@ -6,105 +6,141 @@
|
|||
# RUN: lld -flavor gnu -target mipsel -shared --noinhibit-exec -o %t2 %t1
|
||||
# RUN: llvm-objdump -t -disassemble %t2 | FileCheck -check-prefix RAW %s
|
||||
|
||||
# Local GOT entries:
|
||||
# YAML: - ref-name: L003
|
||||
# YAML-NEXT: type: got
|
||||
# YAML-NEXT: content: [ 00, 00, 00, 00 ]
|
||||
# YAML-NEXT: alignment: 2^2
|
||||
# YAML-NEXT: section-choice: custom-required
|
||||
# YAML-NEXT: section-name: .got
|
||||
# YAML-NEXT: permissions: rw-
|
||||
# YAML-NEXT: references:
|
||||
# YAML-NEXT: - kind: LLD_R_MIPS_32_HI16
|
||||
# YAML-NEXT: offset: 0
|
||||
# YAML-NEXT: target: L006
|
||||
# YAML-NEXT: - ref-name: L005
|
||||
# YAML-NEXT: type: got
|
||||
# YAML-NEXT: content: [ 00, 00, 00, 00 ]
|
||||
# YAML-NEXT: alignment: 2^2
|
||||
# YAML-NEXT: section-choice: custom-required
|
||||
# YAML-NEXT: section-name: .got
|
||||
# YAML-NEXT: permissions: rw-
|
||||
# YAML-NEXT: references:
|
||||
# YAML-NEXT: - kind: LLD_R_MIPS_32_HI16
|
||||
# YAML-NEXT: offset: 0
|
||||
# YAML-NEXT: target: L006
|
||||
# YAML-NEXT: addend: 66048
|
||||
# YAML-NEXT: - ref-name: L007
|
||||
# YAML-NEXT: type: got
|
||||
# YAML-NEXT: content: [ 00, 00, 00, 00 ]
|
||||
# YAML-NEXT: alignment: 2^2
|
||||
# YAML-NEXT: section-choice: custom-required
|
||||
# YAML-NEXT: section-name: .got
|
||||
# YAML-NEXT: permissions: rw-
|
||||
# YAML-NEXT: references:
|
||||
# YAML-NEXT: - kind: R_MIPS_32
|
||||
# YAML-NEXT: offset: 0
|
||||
# YAML-NEXT: target: hidden
|
||||
|
||||
# YAML: - ref-name: [[L002:[-a-zA-Z0-9_]+]]
|
||||
# YAML: type: got
|
||||
# YAML: content: [ 00, 00, 00, 00 ]
|
||||
# YAML: alignment: 2^2
|
||||
# YAML: section-choice: custom-required
|
||||
# YAML: section-name: .got
|
||||
# YAML: permissions: rw-
|
||||
# YAML: references:
|
||||
# YAML: - kind: R_MIPS_32
|
||||
# YAML: offset: 0
|
||||
# YAML: target: [[L003:[-a-zA-Z0-9_]+]]
|
||||
# YAML: - ref-name: [[L004:[-a-zA-Z0-9_]+]]
|
||||
# YAML: type: got
|
||||
# YAML: content: [ 00, 00, 00, 00 ]
|
||||
# YAML: alignment: 2^2
|
||||
# YAML: section-choice: custom-required
|
||||
# YAML: section-name: .got
|
||||
# YAML: permissions: rw-
|
||||
# YAML: references:
|
||||
# YAML: - kind: R_MIPS_32
|
||||
# YAML: offset: 0
|
||||
# YAML: target: hidden
|
||||
# YAML: - ref-name: [[L005:[-a-zA-Z0-9_]+]]
|
||||
# YAML: type: got
|
||||
# YAML: content: [ 00, 00, 00, 00 ]
|
||||
# YAML: alignment: 2^2
|
||||
# YAML: section-choice: custom-required
|
||||
# YAML: section-name: .got
|
||||
# YAML: permissions: rw-
|
||||
# YAML: references:
|
||||
# YAML: - kind: LLD_R_MIPS_GLOBAL_GOT
|
||||
# YAML: offset: 0
|
||||
# YAML: target: glob
|
||||
# YAML: - kind: R_MIPS_32
|
||||
# YAML: offset: 0
|
||||
# YAML: target: glob
|
||||
# YAML: - ref-name: [[L006:[-a-zA-Z0-9_]+]]
|
||||
# YAML: type: got
|
||||
# YAML: content: [ 00, 00, 00, 00 ]
|
||||
# YAML: alignment: 2^2
|
||||
# YAML: section-choice: custom-required
|
||||
# YAML: section-name: .got
|
||||
# YAML: permissions: rw-
|
||||
# YAML: references:
|
||||
# YAML: - kind: LLD_R_MIPS_GLOBAL_GOT
|
||||
# YAML: offset: 0
|
||||
# YAML: target: extern
|
||||
# YAML: - ref-name: [[L007:[-a-zA-Z0-9_]+]]
|
||||
# YAML: alignment: 2^2
|
||||
# YAML: references:
|
||||
# YAML: - kind: layout-after
|
||||
# YAML: offset: 0
|
||||
# YAML: target: glob
|
||||
# YAML: - name: glob
|
||||
# YAML: scope: global
|
||||
# YAML: content: [ 00, 00, 84, 8F, 00, 00, 84, 24, 00, 00, 84, 8F,
|
||||
# YAML: 00, 00, 84, 8F, 00, 00, 84, 8F ]
|
||||
# YAML: alignment: 2^2
|
||||
# YAML: references:
|
||||
# YAML: - kind: R_MIPS_LO16
|
||||
# YAML: offset: 4
|
||||
# YAML: target: [[L003]]
|
||||
# YAML: - kind: R_MIPS_GOT16
|
||||
# YAML: offset: 8
|
||||
# YAML: target: [[L004]]
|
||||
# YAML: - kind: R_MIPS_CALL16
|
||||
# YAML: offset: 12
|
||||
# YAML: target: [[L005]]
|
||||
# YAML: - kind: R_MIPS_CALL16
|
||||
# YAML: offset: 16
|
||||
# YAML: target: [[L006]]
|
||||
# Global GOT entries:
|
||||
# YAML-NEXT: - ref-name: L008
|
||||
# YAML-NEXT: type: got
|
||||
# YAML-NEXT: content: [ 00, 00, 00, 00 ]
|
||||
# YAML-NEXT: alignment: 2^2
|
||||
# YAML-NEXT: section-choice: custom-required
|
||||
# YAML-NEXT: section-name: .got
|
||||
# YAML-NEXT: permissions: rw-
|
||||
# YAML-NEXT: references:
|
||||
# YAML-NEXT: - kind: LLD_R_MIPS_GLOBAL_GOT
|
||||
# YAML-NEXT: offset: 0
|
||||
# YAML-NEXT: target: glob
|
||||
# YAML-NEXT: - kind: R_MIPS_32
|
||||
# YAML-NEXT: offset: 0
|
||||
# YAML-NEXT: target: glob
|
||||
# YAML-NEXT: - ref-name: L009
|
||||
# YAML-NEXT: type: got
|
||||
# YAML-NEXT: content: [ 00, 00, 00, 00 ]
|
||||
# YAML-NEXT: alignment: 2^2
|
||||
# YAML-NEXT: section-choice: custom-required
|
||||
# YAML-NEXT: section-name: .got
|
||||
# YAML-NEXT: permissions: rw-
|
||||
# YAML-NEXT: references:
|
||||
# YAML-NEXT: - kind: LLD_R_MIPS_GLOBAL_GOT
|
||||
# YAML-NEXT: offset: 0
|
||||
# YAML-NEXT: target: extern
|
||||
|
||||
# Function glob
|
||||
# YAML: - name: glob
|
||||
# YAML-NEXT: scope: global
|
||||
# YAML-NEXT: content: [ 00, 00, 84, 8F, 00, 00, 84, 24, 01, 00, 84, 8F,
|
||||
# YAML-NEXT: 00, 02, 84, 24, 00, 00, 84, 8F, 00, 00, 84, 8F,
|
||||
# YAML-NEXT: 00, 00, 84, 8F ]
|
||||
# YAML-NEXT: alignment: 2^2
|
||||
# YAML-NEXT: references:
|
||||
# YAML-NEXT: - kind: R_MIPS_GOT16
|
||||
# YAML-NEXT: offset: 0
|
||||
# YAML-NEXT: target: L003
|
||||
# YAML-NEXT: - kind: R_MIPS_LO16
|
||||
# YAML-NEXT: offset: 4
|
||||
# YAML-NEXT: target: L006
|
||||
# YAML-NEXT: - kind: R_MIPS_GOT16
|
||||
# YAML-NEXT: offset: 8
|
||||
# YAML-NEXT: target: L005
|
||||
# YAML-NEXT: addend: 66048
|
||||
# YAML-NEXT: - kind: R_MIPS_LO16
|
||||
# YAML-NEXT: offset: 12
|
||||
# YAML-NEXT: target: L006
|
||||
# YAML-NEXT: addend: 512
|
||||
# YAML-NEXT: - kind: R_MIPS_GOT16
|
||||
# YAML-NEXT: offset: 16
|
||||
# YAML-NEXT: target: L007
|
||||
# YAML-NEXT: - kind: R_MIPS_CALL16
|
||||
# YAML-NEXT: offset: 20
|
||||
# YAML-NEXT: target: L008
|
||||
# YAML-NEXT: - kind: R_MIPS_CALL16
|
||||
# YAML-NEXT: offset: 24
|
||||
# YAML-NEXT: target: L009
|
||||
|
||||
# RAW: Disassembly of section .text:
|
||||
# RAW: glob:
|
||||
# RAW-NEXT: 148: 18 80 84 8f lw $4, -32744($gp)
|
||||
# RAW-NEXT: 14c: 00 20 84 24 addiu $4, $4, 8192
|
||||
# RAW-NEXT: 150: 1c 80 84 8f lw $4, -32740($gp)
|
||||
# RAW-NEXT: 154: 20 80 84 8f lw $4, -32736($gp)
|
||||
# RAW-NEXT: 158: 24 80 84 8f lw $4, -32732($gp)
|
||||
# RAW-NEXT: 12c: 18 80 84 8f lw $4, -32744($gp)
|
||||
# RAW-NEXT: 130: 00 20 84 24 addiu $4, $4, 8192
|
||||
# RAW-NEXT: 134: 1c 80 84 8f lw $4, -32740($gp)
|
||||
# RAW-NEXT: 138: 00 22 84 24 addiu $4, $4, 8704
|
||||
# RAW-NEXT: 13c: 20 80 84 8f lw $4, -32736($gp)
|
||||
# RAW-NEXT: 140: 24 80 84 8f lw $4, -32732($gp)
|
||||
# RAW-NEXT: 144: 28 80 84 8f lw $4, -32728($gp)
|
||||
|
||||
# RAW: SYMBOL TABLE:
|
||||
# RAW: 00000000 *UND* 00000000
|
||||
# RAW: 00002000 l .data 00000000 local
|
||||
# RAW: 00002000 l .data 00000000 str1
|
||||
# RAW: 00012200 l .data 00000005 str2
|
||||
# RAW: 0000012c g F .text 0000001c glob
|
||||
# RAW: 00012205 g .data 00000004 hidden
|
||||
|
||||
.global glob
|
||||
.ent glob
|
||||
glob:
|
||||
lw $4,%got(local)($28) # G(local)
|
||||
addiu $4,$4,%lo(local) # local (0x2000)
|
||||
lw $4,%got(str1)($28) # G(str1)
|
||||
addiu $4,$4,%lo(str1) # str1
|
||||
lw $4,%got(str2)($28) # G(str2)
|
||||
addiu $4,$4,%lo(str2) # str2
|
||||
lw $4,%got(hidden)($28) # G(hidden)
|
||||
lw $4,%call16(glob)($28) # G(glob)
|
||||
lw $4,%call16(extern)($28) # G(extern)
|
||||
.end glob
|
||||
|
||||
.data
|
||||
.type local,%object
|
||||
.size local,4
|
||||
local:
|
||||
.word undef
|
||||
.type str1, %object
|
||||
.size str1, 0x10200
|
||||
str1:
|
||||
.ascii "str1\000"
|
||||
.space 0x101fb
|
||||
|
||||
.type str2, @object
|
||||
.size str2, 5
|
||||
str2:
|
||||
.ascii "str2\000"
|
||||
|
||||
.globl hidden
|
||||
.hidden hidden
|
||||
|
|
Loading…
Reference in New Issue