1235633Sdim//===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT --*- C++ -*-===//
2224133Sdim//
3224133Sdim//                     The LLVM Compiler Infrastructure
4224133Sdim//
5224133Sdim// This file is distributed under the University of Illinois Open Source
6224133Sdim// License. See LICENSE.TXT for details.
7224133Sdim//
8224133Sdim//===----------------------------------------------------------------------===//
9224133Sdim//
10224133Sdim// Interface for the implementations of runtime dynamic linker facilities.
11224133Sdim//
12224133Sdim//===----------------------------------------------------------------------===//
13224133Sdim
14224133Sdim#ifndef LLVM_RUNTIME_DYLD_IMPL_H
15224133Sdim#define LLVM_RUNTIME_DYLD_IMPL_H
16224133Sdim
17235633Sdim#include "llvm/ADT/DenseMap.h"
18245431Sdim#include "llvm/ADT/SmallVector.h"
19224133Sdim#include "llvm/ADT/StringMap.h"
20245431Sdim#include "llvm/ADT/Triple.h"
21252723Sdim#include "llvm/ExecutionEngine/ObjectImage.h"
22252723Sdim#include "llvm/ExecutionEngine/RuntimeDyld.h"
23245431Sdim#include "llvm/Object/ObjectFile.h"
24224133Sdim#include "llvm/Support/Debug.h"
25224133Sdim#include "llvm/Support/ErrorHandling.h"
26245431Sdim#include "llvm/Support/Format.h"
27245431Sdim#include "llvm/Support/Host.h"
28263509Sdim#include "llvm/Support/Mutex.h"
29245431Sdim#include "llvm/Support/SwapByteOrder.h"
30245431Sdim#include "llvm/Support/raw_ostream.h"
31245431Sdim#include "llvm/Support/system_error.h"
32235633Sdim#include <map>
33224133Sdim
34224133Sdimusing namespace llvm;
35224133Sdimusing namespace llvm::object;
36224133Sdim
37224133Sdimnamespace llvm {
38235633Sdim
39245431Sdimclass ObjectBuffer;
40245431Sdimclass Twine;
41245431Sdim
42245431Sdim
43245431Sdim/// SectionEntry - represents a section emitted into memory by the dynamic
44245431Sdim/// linker.
45235633Sdimclass SectionEntry {
46235633Sdimpublic:
47245431Sdim  /// Name - section name.
48245431Sdim  StringRef Name;
49245431Sdim
50245431Sdim  /// Address - address in the linker's memory where the section resides.
51245431Sdim  uint8_t *Address;
52245431Sdim
53252723Sdim  /// Size - section size. Doesn't include the stubs.
54235633Sdim  size_t Size;
55245431Sdim
56245431Sdim  /// LoadAddress - the address of the section in the target process's memory.
57245431Sdim  /// Used for situations in which JIT-ed code is being executed in the address
58245431Sdim  /// space of a separate process.  If the code executes in the same address
59245431Sdim  /// space where it was JIT-ed, this just equals Address.
60245431Sdim  uint64_t LoadAddress;
61245431Sdim
62245431Sdim  /// StubOffset - used for architectures with stub functions for far
63245431Sdim  /// relocations (like ARM).
64245431Sdim  uintptr_t StubOffset;
65245431Sdim
66245431Sdim  /// ObjAddress - address of the section in the in-memory object file.  Used
67245431Sdim  /// for calculating relocations in some object formats (like MachO).
68245431Sdim  uintptr_t ObjAddress;
69245431Sdim
70245431Sdim  SectionEntry(StringRef name, uint8_t *address, size_t size,
71252723Sdim               uintptr_t objAddress)
72245431Sdim    : Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address),
73252723Sdim      StubOffset(size), ObjAddress(objAddress) {}
74235633Sdim};
75235633Sdim
76245431Sdim/// RelocationEntry - used to represent relocations internally in the dynamic
77245431Sdim/// linker.
78235633Sdimclass RelocationEntry {
79235633Sdimpublic:
80245431Sdim  /// SectionID - the section this relocation points to.
81245431Sdim  unsigned SectionID;
82245431Sdim
83245431Sdim  /// Offset - offset into the section.
84263509Sdim  uint64_t Offset;
85245431Sdim
86245431Sdim  /// RelType - relocation type.
87245431Sdim  uint32_t RelType;
88245431Sdim
89245431Sdim  /// Addend - the relocation addend encoded in the instruction itself.  Also
90245431Sdim  /// used to make a relocation section relative instead of symbol relative.
91263509Sdim  int64_t Addend;
92245431Sdim
93263509Sdim  /// SymOffset - Section offset of the relocation entry's symbol (used for GOT
94263509Sdim  /// lookup).
95263509Sdim  uint64_t SymOffset;
96263509Sdim
97252723Sdim  /// True if this is a PCRel relocation (MachO specific).
98252723Sdim  bool IsPCRel;
99252723Sdim
100252723Sdim  /// The size of this relocation (MachO specific).
101252723Sdim  unsigned Size;
102252723Sdim
103245431Sdim  RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend)
104252723Sdim    : SectionID(id), Offset(offset), RelType(type), Addend(addend),
105263509Sdim      SymOffset(0), IsPCRel(false), Size(0) {}
106235633Sdim
107252723Sdim  RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
108263509Sdim                  uint64_t symoffset)
109263509Sdim    : SectionID(id), Offset(offset), RelType(type), Addend(addend),
110263509Sdim      SymOffset(symoffset), IsPCRel(false), Size(0) {}
111263509Sdim
112263509Sdim  RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend,
113252723Sdim                  bool IsPCRel, unsigned Size)
114252723Sdim    : SectionID(id), Offset(offset), RelType(type), Addend(addend),
115263509Sdim      SymOffset(0), IsPCRel(IsPCRel), Size(Size) {}
116235633Sdim};
117235633Sdim
118235633Sdimclass RelocationValueRef {
119235633Sdimpublic:
120235633Sdim  unsigned  SectionID;
121263509Sdim  uint64_t  Offset;
122263509Sdim  int64_t   Addend;
123235633Sdim  const char *SymbolName;
124263509Sdim  RelocationValueRef(): SectionID(0), Offset(0), Addend(0), SymbolName(0) {}
125235633Sdim
126235633Sdim  inline bool operator==(const RelocationValueRef &Other) const {
127263509Sdim    return SectionID == Other.SectionID && Offset == Other.Offset &&
128263509Sdim           Addend == Other.Addend && SymbolName == Other.SymbolName;
129235633Sdim  }
130235633Sdim  inline bool operator <(const RelocationValueRef &Other) const {
131263509Sdim    if (SectionID != Other.SectionID)
132263509Sdim      return SectionID < Other.SectionID;
133263509Sdim    if (Offset != Other.Offset)
134263509Sdim      return Offset < Other.Offset;
135263509Sdim    if (Addend != Other.Addend)
136263509Sdim      return Addend < Other.Addend;
137263509Sdim    return SymbolName < Other.SymbolName;
138235633Sdim  }
139235633Sdim};
140235633Sdim
141224133Sdimclass RuntimeDyldImpl {
142224133Sdimprotected:
143224133Sdim  // The MemoryManager to load objects into.
144224133Sdim  RTDyldMemoryManager *MemMgr;
145224133Sdim
146245431Sdim  // A list of all sections emitted by the dynamic linker.  These sections are
147245431Sdim  // referenced in the code by means of their index in this list - SectionID.
148235633Sdim  typedef SmallVector<SectionEntry, 64> SectionList;
149235633Sdim  SectionList Sections;
150224133Sdim
151263509Sdim  typedef unsigned SID; // Type for SectionIDs
152263509Sdim  #define RTDYLD_INVALID_SECTION_ID ((SID)(-1))
153263509Sdim
154235633Sdim  // Keep a map of sections from object file to the SectionID which
155235633Sdim  // references it.
156235633Sdim  typedef std::map<SectionRef, unsigned> ObjSectionToIDMap;
157224133Sdim
158245431Sdim  // A global symbol table for symbols from all loaded modules.  Maps the
159245431Sdim  // symbol name to a (SectionID, offset in section) pair.
160235633Sdim  typedef std::pair<unsigned, uintptr_t> SymbolLoc;
161245431Sdim  typedef StringMap<SymbolLoc> SymbolTableMap;
162245431Sdim  SymbolTableMap GlobalSymbolTable;
163224133Sdim
164245431Sdim  // Pair representing the size and alignment requirement for a common symbol.
165245431Sdim  typedef std::pair<unsigned, unsigned> CommonSymbolInfo;
166245431Sdim  // Keep a map of common symbols to their info pairs
167245431Sdim  typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap;
168235633Sdim
169235633Sdim  // For each symbol, keep a list of relocations based on it. Anytime
170235633Sdim  // its address is reassigned (the JIT re-compiled the function, e.g.),
171235633Sdim  // the relocations get re-resolved.
172235633Sdim  // The symbol (or section) the relocation is sourced from is the Key
173235633Sdim  // in the relocation list where it's stored.
174235633Sdim  typedef SmallVector<RelocationEntry, 64> RelocationList;
175235633Sdim  // Relocations to sections already loaded. Indexed by SectionID which is the
176245431Sdim  // source of the address. The target where the address will be written is
177235633Sdim  // SectionID/Offset in the relocation itself.
178235633Sdim  DenseMap<unsigned, RelocationList> Relocations;
179235633Sdim
180245431Sdim  // Relocations to external symbols that are not yet resolved.  Symbols are
181245431Sdim  // external when they aren't found in the global symbol table of all loaded
182245431Sdim  // modules.  This map is indexed by symbol name.
183245431Sdim  StringMap<RelocationList> ExternalSymbolRelocations;
184245431Sdim
185235633Sdim  typedef std::map<RelocationValueRef, uintptr_t> StubMap;
186235633Sdim
187235633Sdim  Triple::ArchType Arch;
188263509Sdim  bool IsTargetLittleEndian;
189235633Sdim
190263509Sdim  // This mutex prevents simultaneously loading objects from two different
191263509Sdim  // threads.  This keeps us from having to protect individual data structures
192263509Sdim  // and guarantees that section allocation requests to the memory manager
193263509Sdim  // won't be interleaved between modules.  It is also used in mapSectionAddress
194263509Sdim  // and resolveRelocations to protect write access to internal data structures.
195263509Sdim  //
196263509Sdim  // loadObject may be called on the same thread during the handling of of
197263509Sdim  // processRelocations, and that's OK.  The handling of the relocation lists
198263509Sdim  // is written in such a way as to work correctly if new elements are added to
199263509Sdim  // the end of the list while the list is being processed.
200263509Sdim  sys::Mutex lock;
201235633Sdim
202263509Sdim  virtual unsigned getMaxStubSize() = 0;
203263509Sdim  virtual unsigned getStubAlignment() = 0;
204252723Sdim
205224133Sdim  bool HasError;
206224133Sdim  std::string ErrorStr;
207224133Sdim
208224133Sdim  // Set the error state and record an error string.
209224133Sdim  bool Error(const Twine &Msg) {
210224133Sdim    ErrorStr = Msg.str();
211224133Sdim    HasError = true;
212224133Sdim    return true;
213224133Sdim  }
214224133Sdim
215245431Sdim  uint64_t getSectionLoadAddress(unsigned SectionID) {
216245431Sdim    return Sections[SectionID].LoadAddress;
217245431Sdim  }
218245431Sdim
219235633Sdim  uint8_t *getSectionAddress(unsigned SectionID) {
220235633Sdim    return (uint8_t*)Sections[SectionID].Address;
221235633Sdim  }
222224133Sdim
223245431Sdim  void writeInt16BE(uint8_t *Addr, uint16_t Value) {
224263509Sdim    if (IsTargetLittleEndian)
225245431Sdim      Value = sys::SwapByteOrder(Value);
226245431Sdim    *Addr     = (Value >> 8) & 0xFF;
227245431Sdim    *(Addr+1) = Value & 0xFF;
228245431Sdim  }
229245431Sdim
230245431Sdim  void writeInt32BE(uint8_t *Addr, uint32_t Value) {
231263509Sdim    if (IsTargetLittleEndian)
232245431Sdim      Value = sys::SwapByteOrder(Value);
233245431Sdim    *Addr     = (Value >> 24) & 0xFF;
234245431Sdim    *(Addr+1) = (Value >> 16) & 0xFF;
235245431Sdim    *(Addr+2) = (Value >> 8) & 0xFF;
236245431Sdim    *(Addr+3) = Value & 0xFF;
237245431Sdim  }
238245431Sdim
239245431Sdim  void writeInt64BE(uint8_t *Addr, uint64_t Value) {
240263509Sdim    if (IsTargetLittleEndian)
241245431Sdim      Value = sys::SwapByteOrder(Value);
242245431Sdim    *Addr     = (Value >> 56) & 0xFF;
243245431Sdim    *(Addr+1) = (Value >> 48) & 0xFF;
244245431Sdim    *(Addr+2) = (Value >> 40) & 0xFF;
245245431Sdim    *(Addr+3) = (Value >> 32) & 0xFF;
246245431Sdim    *(Addr+4) = (Value >> 24) & 0xFF;
247245431Sdim    *(Addr+5) = (Value >> 16) & 0xFF;
248245431Sdim    *(Addr+6) = (Value >> 8) & 0xFF;
249245431Sdim    *(Addr+7) = Value & 0xFF;
250245431Sdim  }
251245431Sdim
252245431Sdim  /// \brief Given the common symbols discovered in the object file, emit a
253245431Sdim  /// new section for them and update the symbol mappings in the object and
254245431Sdim  /// symbol table.
255245431Sdim  void emitCommonSymbols(ObjectImage &Obj,
256245431Sdim                         const CommonSymbolMap &CommonSymbols,
257245431Sdim                         uint64_t TotalSize,
258245431Sdim                         SymbolTableMap &SymbolTable);
259245431Sdim
260235633Sdim  /// \brief Emits section data from the object file to the MemoryManager.
261235633Sdim  /// \param IsCode if it's true then allocateCodeSection() will be
262245431Sdim  ///        used for emits, else allocateDataSection() will be used.
263235633Sdim  /// \return SectionID.
264235633Sdim  unsigned emitSection(ObjectImage &Obj,
265235633Sdim                       const SectionRef &Section,
266235633Sdim                       bool IsCode);
267235633Sdim
268235633Sdim  /// \brief Find Section in LocalSections. If the secton is not found - emit
269235633Sdim  ///        it and store in LocalSections.
270235633Sdim  /// \param IsCode if it's true then allocateCodeSection() will be
271235633Sdim  ///        used for emmits, else allocateDataSection() will be used.
272235633Sdim  /// \return SectionID.
273235633Sdim  unsigned findOrEmitSection(ObjectImage &Obj,
274235633Sdim                             const SectionRef &Section,
275235633Sdim                             bool IsCode,
276235633Sdim                             ObjSectionToIDMap &LocalSections);
277235633Sdim
278245431Sdim  // \brief Add a relocation entry that uses the given section.
279245431Sdim  void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID);
280235633Sdim
281245431Sdim  // \brief Add a relocation entry that uses the given symbol.  This symbol may
282245431Sdim  // be found in the global symbol table, or it may be external.
283245431Sdim  void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName);
284245431Sdim
285235633Sdim  /// \brief Emits long jump instruction to Addr.
286235633Sdim  /// \return Pointer to the memory area for emitting target address.
287235633Sdim  uint8_t* createStubFunction(uint8_t *Addr);
288235633Sdim
289235633Sdim  /// \brief Resolves relocations from Relocs list with address from Value.
290235633Sdim  void resolveRelocationList(const RelocationList &Relocs, uint64_t Value);
291235633Sdim
292235633Sdim  /// \brief A object file specific relocation resolver
293252723Sdim  /// \param RE The relocation to be resolved
294235633Sdim  /// \param Value Target symbol address to apply the relocation action
295252723Sdim  virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value) = 0;
296235633Sdim
297245431Sdim  /// \brief Parses the object file relocation and stores it to Relocations
298245431Sdim  ///        or SymbolRelocations (this depends on the object file type).
299252723Sdim  virtual void processRelocationRef(unsigned SectionID,
300252723Sdim                                    RelocationRef RelI,
301235633Sdim                                    ObjectImage &Obj,
302235633Sdim                                    ObjSectionToIDMap &ObjSectionToID,
303245431Sdim                                    const SymbolTableMap &Symbols,
304245431Sdim                                    StubMap &Stubs) = 0;
305235633Sdim
306245431Sdim  /// \brief Resolve relocations to external symbols.
307245431Sdim  void resolveExternalSymbols();
308263509Sdim
309263509Sdim  /// \brief Update GOT entries for external symbols.
310263509Sdim  // The base class does nothing.  ELF overrides this.
311263509Sdim  virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {}
312263509Sdim
313245431Sdim  virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
314224133Sdimpublic:
315224133Sdim  RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
316224133Sdim
317224133Sdim  virtual ~RuntimeDyldImpl();
318224133Sdim
319245431Sdim  ObjectImage *loadObject(ObjectBuffer *InputBuffer);
320224133Sdim
321224133Sdim  void *getSymbolAddress(StringRef Name) {
322224133Sdim    // FIXME: Just look up as a function for now. Overly simple of course.
323224133Sdim    // Work in progress.
324263509Sdim    SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name);
325263509Sdim    if (pos == GlobalSymbolTable.end())
326235633Sdim      return 0;
327263509Sdim    SymbolLoc Loc = pos->second;
328235633Sdim    return getSectionAddress(Loc.first) + Loc.second;
329224133Sdim  }
330224133Sdim
331245431Sdim  uint64_t getSymbolLoadAddress(StringRef Name) {
332245431Sdim    // FIXME: Just look up as a function for now. Overly simple of course.
333245431Sdim    // Work in progress.
334263509Sdim    SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name);
335263509Sdim    if (pos == GlobalSymbolTable.end())
336245431Sdim      return 0;
337263509Sdim    SymbolLoc Loc = pos->second;
338245431Sdim    return getSectionLoadAddress(Loc.first) + Loc.second;
339245431Sdim  }
340245431Sdim
341224133Sdim  void resolveRelocations();
342224133Sdim
343235633Sdim  void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
344224133Sdim
345245431Sdim  void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress);
346235633Sdim
347224133Sdim  // Is the linker in an error state?
348224133Sdim  bool hasError() { return HasError; }
349224133Sdim
350224133Sdim  // Mark the error condition as handled and continue.
351224133Sdim  void clearError() { HasError = false; }
352224133Sdim
353224133Sdim  // Get the error message.
354224133Sdim  StringRef getErrorString() { return ErrorStr; }
355224133Sdim
356245431Sdim  virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0;
357252723Sdim
358263509Sdim  virtual void registerEHFrames();
359263509Sdim
360263509Sdim  virtual void deregisterEHFrames();
361263509Sdim
362263509Sdim  virtual void finalizeLoad(ObjSectionToIDMap &SectionMap) {}
363224133Sdim};
364224133Sdim
365224133Sdim} // end namespace llvm
366224133Sdim
367224133Sdim
368224133Sdim#endif
369