RuntimeDyldMachOX86_64.h revision 274968
1//===-- RuntimeDyldMachOX86_64.h ---- MachO/X86_64 specific code. -*- C++ -*-=//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_RUNTIMEDYLDMACHOX86_64_H
11#define LLVM_RUNTIMEDYLDMACHOX86_64_H
12
13#include "../RuntimeDyldMachO.h"
14
15#define DEBUG_TYPE "dyld"
16
17namespace llvm {
18
19class RuntimeDyldMachOX86_64
20    : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOX86_64> {
21public:
22  RuntimeDyldMachOX86_64(RTDyldMemoryManager *MM)
23      : RuntimeDyldMachOCRTPBase(MM) {}
24
25  unsigned getMaxStubSize() override { return 8; }
26
27  unsigned getStubAlignment() override { return 1; }
28
29  relocation_iterator
30  processRelocationRef(unsigned SectionID, relocation_iterator RelI,
31                       ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,
32                       const SymbolTableMap &Symbols, StubMap &Stubs) override {
33    const MachOObjectFile &Obj =
34        static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
35    MachO::any_relocation_info RelInfo =
36        Obj.getRelocation(RelI->getRawDataRefImpl());
37
38    assert(!Obj.isRelocationScattered(RelInfo) &&
39           "Scattered relocations not supported on X86_64");
40
41    RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI));
42    RelocationValueRef Value(
43        getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols));
44
45    bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
46    if (!IsExtern && RE.IsPCRel)
47      makeValueAddendPCRel(Value, ObjImg, RelI);
48
49    if (RE.RelType == MachO::X86_64_RELOC_GOT ||
50        RE.RelType == MachO::X86_64_RELOC_GOT_LOAD)
51      processGOTRelocation(RE, Value, Stubs);
52    else {
53      RE.Addend = Value.Addend;
54      if (Value.SymbolName)
55        addRelocationForSymbol(RE, Value.SymbolName);
56      else
57        addRelocationForSection(RE, Value.SectionID);
58    }
59
60    return ++RelI;
61  }
62
63  void resolveRelocation(const RelocationEntry &RE, uint64_t Value) {
64    DEBUG(dumpRelocationToResolve(RE, Value));
65    const SectionEntry &Section = Sections[RE.SectionID];
66    uint8_t *LocalAddress = Section.Address + RE.Offset;
67
68    // If the relocation is PC-relative, the value to be encoded is the
69    // pointer difference.
70    if (RE.IsPCRel) {
71      // FIXME: It seems this value needs to be adjusted by 4 for an effective
72      // PC address. Is that expected? Only for branches, perhaps?
73      uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
74      Value -= FinalAddress + 4;
75    }
76
77    switch (RE.RelType) {
78    default:
79      llvm_unreachable("Invalid relocation type!");
80    case MachO::X86_64_RELOC_SIGNED_1:
81    case MachO::X86_64_RELOC_SIGNED_2:
82    case MachO::X86_64_RELOC_SIGNED_4:
83    case MachO::X86_64_RELOC_SIGNED:
84    case MachO::X86_64_RELOC_UNSIGNED:
85    case MachO::X86_64_RELOC_BRANCH:
86      writeBytesUnaligned(LocalAddress, Value + RE.Addend, 1 << RE.Size);
87      break;
88    case MachO::X86_64_RELOC_GOT_LOAD:
89    case MachO::X86_64_RELOC_GOT:
90    case MachO::X86_64_RELOC_SUBTRACTOR:
91    case MachO::X86_64_RELOC_TLV:
92      Error("Relocation type not implemented yet!");
93    }
94  }
95
96  void finalizeSection(ObjectImage &ObjImg, unsigned SectionID,
97                       const SectionRef &Section) {}
98
99private:
100  void processGOTRelocation(const RelocationEntry &RE,
101                            RelocationValueRef &Value, StubMap &Stubs) {
102    SectionEntry &Section = Sections[RE.SectionID];
103    assert(RE.IsPCRel);
104    assert(RE.Size == 2);
105    Value.Addend -= RE.Addend;
106    RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value);
107    uint8_t *Addr;
108    if (i != Stubs.end()) {
109      Addr = Section.Address + i->second;
110    } else {
111      Stubs[Value] = Section.StubOffset;
112      uint8_t *GOTEntry = Section.Address + Section.StubOffset;
113      RelocationEntry GOTRE(RE.SectionID, Section.StubOffset,
114                            MachO::X86_64_RELOC_UNSIGNED, Value.Addend, false,
115                            3);
116      if (Value.SymbolName)
117        addRelocationForSymbol(GOTRE, Value.SymbolName);
118      else
119        addRelocationForSection(GOTRE, Value.SectionID);
120      Section.StubOffset += 8;
121      Addr = GOTEntry;
122    }
123    RelocationEntry TargetRE(RE.SectionID, RE.Offset,
124                             MachO::X86_64_RELOC_UNSIGNED, RE.Addend, true, 2);
125    resolveRelocation(TargetRE, (uint64_t)Addr);
126  }
127};
128}
129
130#undef DEBUG_TYPE
131
132#endif // LLVM_RUNTIMEDYLDMACHOX86_64_H
133