1e0934bee3a4f40731169bc42b15a39ce39978175Jim Grosbach//===-- RuntimeDyldImpl.h - Run-time dynamic linker for MC-JIT --*- C++ -*-===// 2cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 3cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// The LLVM Compiler Infrastructure 4cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 5cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// This file is distributed under the University of Illinois Open Source 6cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// License. See LICENSE.TXT for details. 7cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 8cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev//===----------------------------------------------------------------------===// 9cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 10cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// Interface for the implementations of runtime dynamic linker facilities. 11cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev// 12cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev//===----------------------------------------------------------------------===// 13cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 14cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#ifndef LLVM_RUNTIME_DYLD_IMPL_H 15cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#define LLVM_RUNTIME_DYLD_IMPL_H 16cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 17020f4e861a9a32059f76377e787703c92ba55a98Jim Grosbach#include "llvm/ADT/DenseMap.h" 18cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#include "llvm/ADT/SmallVector.h" 196d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky#include "llvm/ADT/StringMap.h" 206d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky#include "llvm/ADT/Triple.h" 21a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#include "llvm/ExecutionEngine/ObjectImage.h" 22a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#include "llvm/ExecutionEngine/RuntimeDyld.h" 23cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/ExecutionEngine/RuntimeDyldChecker.h" 246d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky#include "llvm/Object/ObjectFile.h" 25cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#include "llvm/Support/Debug.h" 26cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#include "llvm/Support/ErrorHandling.h" 270e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev#include "llvm/Support/Format.h" 286e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella#include "llvm/Support/Host.h" 296169453ba37ac353655f2475f336e66f31276752Andrew Kaylor#include "llvm/Support/Mutex.h" 306e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella#include "llvm/Support/SwapByteOrder.h" 316d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky#include "llvm/Support/raw_ostream.h" 326d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky#include <map> 33cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include <system_error> 34cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 35cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevusing namespace llvm; 360e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshevusing namespace llvm::object; 37cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 38cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevnamespace llvm { 390e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 403f23cef24fc9200def464bd4bce820678b5715deAndrew Kaylorclass ObjectBuffer; 416d15e8717767af9a6a20c6ea456119c15c77dd00Eli Benderskyclass Twine; 426d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 436d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky/// SectionEntry - represents a section emitted into memory by the dynamic 446d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky/// linker. 450e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshevclass SectionEntry { 460e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshevpublic: 476e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella /// Name - section name. 486e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella StringRef Name; 496e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella 506d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// Address - address in the linker's memory where the section resides. 516d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint8_t *Address; 526d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 53a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola /// Size - section size. Doesn't include the stubs. 546d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky size_t Size; 556d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 566d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// LoadAddress - the address of the section in the target process's memory. 576d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// Used for situations in which JIT-ed code is being executed in the address 586d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// space of a separate process. If the code executes in the same address 596d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// space where it was JIT-ed, this just equals Address. 606d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint64_t LoadAddress; 616d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 626d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// StubOffset - used for architectures with stub functions for far 636d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// relocations (like ARM). 646d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uintptr_t StubOffset; 656d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 666d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// ObjAddress - address of the section in the in-memory object file. Used 676d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// for calculating relocations in some object formats (like MachO). 686d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uintptr_t ObjAddress; 696d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 706e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella SectionEntry(StringRef name, uint8_t *address, size_t size, 71a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola uintptr_t objAddress) 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : Name(name), Address(address), Size(size), 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines LoadAddress((uintptr_t)address), StubOffset(size), 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ObjAddress(objAddress) {} 750e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev}; 760e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 776d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky/// RelocationEntry - used to represent relocations internally in the dynamic 786d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky/// linker. 790e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshevclass RelocationEntry { 800e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshevpublic: 816d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// SectionID - the section this relocation points to. 826d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky unsigned SectionID; 836d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 846d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// Offset - offset into the section. 85ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor uint64_t Offset; 866d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 876d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// RelType - relocation type. 886d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky uint32_t RelType; 896d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 906d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// Addend - the relocation addend encoded in the instruction itself. Also 916d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky /// used to make a relocation section relative instead of symbol relative. 92ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor int64_t Addend; 93ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor 94dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines struct SectionPair { 95dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t SectionA; 96dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint32_t SectionB; 97dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 99ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor /// SymOffset - Section offset of the relocation entry's symbol (used for GOT 100ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor /// lookup). 101dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines union { 102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint64_t SymOffset; 103dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SectionPair Sections; 104dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 1056d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky 10687b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola /// True if this is a PCRel relocation (MachO specific). 10787b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola bool IsPCRel; 10887b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola 10987b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola /// The size of this relocation (MachO specific). 11087b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola unsigned Size; 11187b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola 1126d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : SectionID(id), Offset(offset), RelType(type), Addend(addend), 11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymOffset(0), IsPCRel(false), Size(0) {} 115ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor 116ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, 117ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor uint64_t symoffset) 11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : SectionID(id), Offset(offset), RelType(type), Addend(addend), 11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymOffset(symoffset), IsPCRel(false), Size(0) {} 12087b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola 12187b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, 12287b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola bool IsPCRel, unsigned Size) 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : SectionID(id), Offset(offset), RelType(type), Addend(addend), 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymOffset(0), IsPCRel(IsPCRel), Size(Size) {} 125dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 126dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, 127dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, 128dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines uint64_t SectionBOffset, bool IsPCRel, unsigned Size) 129dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : SectionID(id), Offset(offset), RelType(type), 130dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), 131dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Size(Size) { 132dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Sections.SectionA = SectionA; 133dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Sections.SectionB = SectionB; 134dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 1350e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev}; 1360e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 1370e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshevclass RelocationValueRef { 1380e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshevpublic: 13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned SectionID; 14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t Offset; 14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int64_t Addend; 1420e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev const char *SymbolName; 143dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines RelocationValueRef() : SectionID(0), Offset(0), Addend(0), 144dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SymbolName(nullptr) {} 1450e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 1460e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev inline bool operator==(const RelocationValueRef &Other) const { 14774e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer return SectionID == Other.SectionID && Offset == Other.Offset && 14874e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer Addend == Other.Addend && SymbolName == Other.SymbolName; 1490e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev } 15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines inline bool operator<(const RelocationValueRef &Other) const { 15174e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer if (SectionID != Other.SectionID) 15274e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer return SectionID < Other.SectionID; 15374e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer if (Offset != Other.Offset) 15474e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer return Offset < Other.Offset; 15574e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer if (Addend != Other.Addend) 15674e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer return Addend < Other.Addend; 15774e81aae7c07b0619a77a5a0a56fdb954ce4b8fdBenjamin Kramer return SymbolName < Other.SymbolName; 1580e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev } 1590e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev}; 1600e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 161cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevclass RuntimeDyldImpl { 162cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines friend class RuntimeDyldChecker; 163cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesprivate: 164cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 165cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint64_t getAnySymbolRemoteAddress(StringRef Symbol) { 166cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines if (uint64_t InternalSymbolAddr = getSymbolLoadAddress(Symbol)) 167cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return InternalSymbolAddr; 168cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return MemMgr->getSymbolAddress(Symbol); 169cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 170cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 171cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevprotected: 172cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // The MemoryManager to load objects into. 173cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev RTDyldMemoryManager *MemMgr; 174cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 1756d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky // A list of all sections emitted by the dynamic linker. These sections are 1766d15e8717767af9a6a20c6ea456119c15c77dd00Eli Bendersky // referenced in the code by means of their index in this list - SectionID. 1770e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev typedef SmallVector<SectionEntry, 64> SectionList; 1780e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev SectionList Sections; 179cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 180528f6d787b1a847e61eb2f1114559f423fdeb68cAndrew Kaylor typedef unsigned SID; // Type for SectionIDs 18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) 182528f6d787b1a847e61eb2f1114559f423fdeb68cAndrew Kaylor 1830e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // Keep a map of sections from object file to the SectionID which 1840e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // references it. 1850e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev typedef std::map<SectionRef, unsigned> ObjSectionToIDMap; 186020f4e861a9a32059f76377e787703c92ba55a98Jim Grosbach 187d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky // A global symbol table for symbols from all loaded modules. Maps the 188d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky // symbol name to a (SectionID, offset in section) pair. 1890e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev typedef std::pair<unsigned, uintptr_t> SymbolLoc; 190d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky typedef StringMap<SymbolLoc> SymbolTableMap; 191d98c9e918c9750d965c1efe9efcc9e13feacbe13Eli Bendersky SymbolTableMap GlobalSymbolTable; 1920e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 193f00677d74f1be5b4c7c73e1681a64c9062f4c7eeTim Northover // Pair representing the size and alignment requirement for a common symbol. 194f00677d74f1be5b4c7c73e1681a64c9062f4c7eeTim Northover typedef std::pair<unsigned, unsigned> CommonSymbolInfo; 195f00677d74f1be5b4c7c73e1681a64c9062f4c7eeTim Northover // Keep a map of common symbols to their info pairs 196f00677d74f1be5b4c7c73e1681a64c9062f4c7eeTim Northover typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap; 197c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd 1980e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // For each symbol, keep a list of relocations based on it. Anytime 1990e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // its address is reassigned (the JIT re-compiled the function, e.g.), 2000e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // the relocations get re-resolved. 2010e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // The symbol (or section) the relocation is sourced from is the Key 2020e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // in the relocation list where it's stored. 2030e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev typedef SmallVector<RelocationEntry, 64> RelocationList; 2040e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // Relocations to sections already loaded. Indexed by SectionID which is the 205d9b0b025612992a0b724eeca8bdf10b1d7a5c355Benjamin Kramer // source of the address. The target where the address will be written is 2060e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev // SectionID/Offset in the relocation itself. 2070e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev DenseMap<unsigned, RelocationList> Relocations; 20837bc5a200092f1b41da799c75da70258015e43a4Eli Bendersky 20937bc5a200092f1b41da799c75da70258015e43a4Eli Bendersky // Relocations to external symbols that are not yet resolved. Symbols are 21037bc5a200092f1b41da799c75da70258015e43a4Eli Bendersky // external when they aren't found in the global symbol table of all loaded 21137bc5a200092f1b41da799c75da70258015e43a4Eli Bendersky // modules. This map is indexed by symbol name. 21237bc5a200092f1b41da799c75da70258015e43a4Eli Bendersky StringMap<RelocationList> ExternalSymbolRelocations; 2130e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 2140e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev typedef std::map<RelocationValueRef, uintptr_t> StubMap; 2150e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 2160e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev Triple::ArchType Arch; 217ab950f5f334d30a7b5bfb1e009846dfb0b47f61cAndrew Kaylor bool IsTargetLittleEndian; 2180e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // True if all sections should be passed to the memory manager, false if only 22036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // sections containing relocations should be. Defaults to 'false'. 22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool ProcessAllSections; 22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2236169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // This mutex prevents simultaneously loading objects from two different 2246169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // threads. This keeps us from having to protect individual data structures 2256169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // and guarantees that section allocation requests to the memory manager 2266169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // won't be interleaved between modules. It is also used in mapSectionAddress 2276169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // and resolveRelocations to protect write access to internal data structures. 2286169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // 2296169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // loadObject may be called on the same thread during the handling of of 2306169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // processRelocations, and that's OK. The handling of the relocation lists 2316169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // is written in such a way as to work correctly if new elements are added to 2326169453ba37ac353655f2475f336e66f31276752Andrew Kaylor // the end of the list while the list is being processed. 2336169453ba37ac353655f2475f336e66f31276752Andrew Kaylor sys::Mutex lock; 2346169453ba37ac353655f2475f336e66f31276752Andrew Kaylor 23572be32c6332ff9dd38b989d5a0dd80f40996dd10Andrew Kaylor virtual unsigned getMaxStubSize() = 0; 23672be32c6332ff9dd38b989d5a0dd80f40996dd10Andrew Kaylor virtual unsigned getStubAlignment() = 0; 2376fc2ad62e23673ef829c9c4bbf62743d30928a5bRichard Sandiford 238cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev bool HasError; 239cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev std::string ErrorStr; 240cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 241cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Set the error state and record an error string. 242cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev bool Error(const Twine &Msg) { 243cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev ErrorStr = Msg.str(); 244cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev HasError = true; 245cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev return true; 246cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 247cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 24835ed842773da41779d57d3ed23f440202d0be198Jim Grosbach uint64_t getSectionLoadAddress(unsigned SectionID) { 24935ed842773da41779d57d3ed23f440202d0be198Jim Grosbach return Sections[SectionID].LoadAddress; 25035ed842773da41779d57d3ed23f440202d0be198Jim Grosbach } 25135ed842773da41779d57d3ed23f440202d0be198Jim Grosbach 25261425c0a7f4e3608a85f7bbf254cd052a15b7446Jim Grosbach uint8_t *getSectionAddress(unsigned SectionID) { 25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return (uint8_t *)Sections[SectionID].Address; 25461425c0a7f4e3608a85f7bbf254cd052a15b7446Jim Grosbach } 255cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 2566e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella void writeInt16BE(uint8_t *Addr, uint16_t Value) { 257ab950f5f334d30a7b5bfb1e009846dfb0b47f61cAndrew Kaylor if (IsTargetLittleEndian) 258cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines sys::swapByteOrder(Value); 25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *Addr = (Value >> 8) & 0xFF; 26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 1) = Value & 0xFF; 2616e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella } 2626e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella 2636e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella void writeInt32BE(uint8_t *Addr, uint32_t Value) { 264ab950f5f334d30a7b5bfb1e009846dfb0b47f61cAndrew Kaylor if (IsTargetLittleEndian) 265cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines sys::swapByteOrder(Value); 26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *Addr = (Value >> 24) & 0xFF; 26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 1) = (Value >> 16) & 0xFF; 26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 2) = (Value >> 8) & 0xFF; 26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 3) = Value & 0xFF; 2706e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella } 2716e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella 2726e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella void writeInt64BE(uint8_t *Addr, uint64_t Value) { 273ab950f5f334d30a7b5bfb1e009846dfb0b47f61cAndrew Kaylor if (IsTargetLittleEndian) 274cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines sys::swapByteOrder(Value); 27536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *Addr = (Value >> 56) & 0xFF; 27636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 1) = (Value >> 48) & 0xFF; 27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 2) = (Value >> 40) & 0xFF; 27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 3) = (Value >> 32) & 0xFF; 27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 4) = (Value >> 24) & 0xFF; 28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 5) = (Value >> 16) & 0xFF; 28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 6) = (Value >> 8) & 0xFF; 28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *(Addr + 7) = Value & 0xFF; 2836e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella } 2846e8946c5280ad6071d21013651745a9478f063edAdhemerval Zanella 285c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky /// \brief Given the common symbols discovered in the object file, emit a 286c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky /// new section for them and update the symbol mappings in the object and 287c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky /// symbol table. 28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void emitCommonSymbols(ObjectImage &Obj, const CommonSymbolMap &CommonSymbols, 28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t TotalSize, SymbolTableMap &SymbolTable); 290c68dda815e64fb2fb463318d1eaa304e22199d50Preston Gurd 2910e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \brief Emits section data from the object file to the MemoryManager. 2920e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \param IsCode if it's true then allocateCodeSection() will be 2935fe019835c269ccbfe185276269bc53b3f9a7a86Eli Bendersky /// used for emits, else allocateDataSection() will be used. 2940e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \return SectionID. 29536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned emitSection(ObjectImage &Obj, const SectionRef &Section, 296689ff9c00f4f3dcf3491778bcdbda79e19e2285dPreston Gurd bool IsCode); 2970e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 2980e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \brief Find Section in LocalSections. If the secton is not found - emit 2990e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// it and store in LocalSections. 3000e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \param IsCode if it's true then allocateCodeSection() will be 3010e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// used for emmits, else allocateDataSection() will be used. 3020e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \return SectionID. 30336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned findOrEmitSection(ObjectImage &Obj, const SectionRef &Section, 30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool IsCode, ObjSectionToIDMap &LocalSections); 3050e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 306c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky // \brief Add a relocation entry that uses the given section. 307c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID); 308c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky 309c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky // \brief Add a relocation entry that uses the given symbol. This symbol may 310c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky // be found in the global symbol table, or it may be external. 311c201e6eaf165c83f0092c43b371e509fa8eaf4ccEli Bendersky void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName); 3120e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 3130e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \brief Emits long jump instruction to Addr. 3140e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \return Pointer to the memory area for emitting target address. 31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t *createStubFunction(uint8_t *Addr); 3160e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 3170e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \brief Resolves relocations from Relocs list with address from Value. 3180e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev void resolveRelocationList(const RelocationList &Relocs, uint64_t Value); 3190e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 3200e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \brief A object file specific relocation resolver 3211fbeecb0394a2f203fd48b699718c4f90a8870b7Rafael Espindola /// \param RE The relocation to be resolved 3220e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev /// \param Value Target symbol address to apply the relocation action 32387b5017139e9d8ac9b046b3284a9cc68c76185d6Rafael Espindola virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value) = 0; 3240e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// \brief Parses one or more object file relocations (some object files use 32636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// relocation pairs) and stores it to Relocations or SymbolRelocations 32736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// (this depends on the object file type). 32836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /// \return Iterator to the next relocation that needs to be parsed. 32936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines virtual relocation_iterator 33036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines processRelocationRef(unsigned SectionID, relocation_iterator RelI, 33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, 33236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const SymbolTableMap &Symbols, StubMap &Stubs) = 0; 3330e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev 33437bc5a200092f1b41da799c75da70258015e43a4Eli Bendersky /// \brief Resolve relocations to external symbols. 33537bc5a200092f1b41da799c75da70258015e43a4Eli Bendersky void resolveExternalSymbols(); 336ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor 337ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor /// \brief Update GOT entries for external symbols. 338ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor // The base class does nothing. ELF overrides this. 339ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {} 340ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor 34136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // \brief Compute an upper bound of the memory that is required to load all 34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // sections 34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize, 34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t &DataSizeRO, uint64_t &DataSizeRW); 34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // \brief Compute the stub buffer size required for a section 34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned computeSectionStubBufSize(ObjectImage &Obj, 34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const SectionRef &Section); 34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 350cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshevpublic: 35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RuntimeDyldImpl(RTDyldMemoryManager *mm) 352cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines : MemMgr(mm), ProcessAllSections(false), HasError(false) { 353cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines } 354cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 355cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev virtual ~RuntimeDyldImpl(); 356cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void setProcessAllSections(bool ProcessAllSections) { 35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines this->ProcessAllSections = ProcessAllSections; 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ObjectImage *loadObject(ObjectImage *InputObject); 362cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 363cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines uint8_t* getSymbolAddress(StringRef Name) { 364cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // FIXME: Just look up as a function for now. Overly simple of course. 365cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Work in progress. 3664805bf59b9e41a95336c066ec58194ff6801694aYaron Keren SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); 3674805bf59b9e41a95336c066ec58194ff6801694aYaron Keren if (pos == GlobalSymbolTable.end()) 368dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 3694805bf59b9e41a95336c066ec58194ff6801694aYaron Keren SymbolLoc Loc = pos->second; 37061425c0a7f4e3608a85f7bbf254cd052a15b7446Jim Grosbach return getSectionAddress(Loc.first) + Loc.second; 371cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev } 372cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 37335ed842773da41779d57d3ed23f440202d0be198Jim Grosbach uint64_t getSymbolLoadAddress(StringRef Name) { 37435ed842773da41779d57d3ed23f440202d0be198Jim Grosbach // FIXME: Just look up as a function for now. Overly simple of course. 37535ed842773da41779d57d3ed23f440202d0be198Jim Grosbach // Work in progress. 3764805bf59b9e41a95336c066ec58194ff6801694aYaron Keren SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); 3774805bf59b9e41a95336c066ec58194ff6801694aYaron Keren if (pos == GlobalSymbolTable.end()) 37835ed842773da41779d57d3ed23f440202d0be198Jim Grosbach return 0; 3794805bf59b9e41a95336c066ec58194ff6801694aYaron Keren SymbolLoc Loc = pos->second; 38035ed842773da41779d57d3ed23f440202d0be198Jim Grosbach return getSectionLoadAddress(Loc.first) + Loc.second; 38135ed842773da41779d57d3ed23f440202d0be198Jim Grosbach } 38235ed842773da41779d57d3ed23f440202d0be198Jim Grosbach 3830e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev void resolveRelocations(); 384cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 3850e4fa5ff365fccff46870b7d5d8d4d1d46e77986Danil Malyshev void reassignSectionAddress(unsigned SectionID, uint64_t Addr); 386cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 387e940c1bb6c976539f07d6f440aeaacf7c25e1ddcJim Grosbach void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); 388020f4e861a9a32059f76377e787703c92ba55a98Jim Grosbach 389cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Is the linker in an error state? 390cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev bool hasError() { return HasError; } 391cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 392cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Mark the error condition as handled and continue. 393cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev void clearError() { HasError = false; } 394cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 395cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev // Get the error message. 396cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev StringRef getErrorString() { return ErrorStr; } 397cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 3983f23cef24fc9200def464bd4bce820678b5715deAndrew Kaylor virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; 39936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0; 400a2e40fbd624916c187a95ed76939ca7f02ed3e53Rafael Espindola 401528f6d787b1a847e61eb2f1114559f423fdeb68cAndrew Kaylor virtual void registerEHFrames(); 402ff9fa05905be716435460b5f6d32689041bf895bAndrew Kaylor 40343507d026bef31100cb0c35614bcf419029a265bAndrew Kaylor virtual void deregisterEHFrames(); 40443507d026bef31100cb0c35614bcf419029a265bAndrew Kaylor 405dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines virtual void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) {} 406cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev}; 407cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 408cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev} // end namespace llvm 409cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev 410cf852dc49bfadb79a27455f8773dbfda2b96f4f6Danil Malyshev#endif 411