[llvm] r234839 - [RuntimeDyldELF] Improve GOT support
Lang Hames
lhames at gmail.com
Mon Apr 13 19:48:31 PDT 2015
This is great. Thanks Keno!
- Lang.
On Mon, Apr 13, 2015 at 7:10 PM, Keno Fischer <kfischer at college.harvard.edu>
wrote:
> Author: kfischer
> Date: Mon Apr 13 21:10:35 2015
> New Revision: 234839
>
> URL: http://llvm.org/viewvc/llvm-project?rev=234839&view=rev
> Log:
> [RuntimeDyldELF] Improve GOT support
>
> Summary:
> This is the first in a series of patches to eventually add support for TLS
> relocations to RuntimeDyld. This patch resolves an issue in the current GOT
> handling, where GOT entries would be reused between object files, which
> leads to the same situation that necessitates the GOT in the first place,
> i.e. that the 32-bit offset can not cover all of the address space. Thus
> this patch makes the GOT object-file-local.
> Unfortunately, this still isn't quite enough, because the MemoryManager
> does not yet guarantee that sections are allocated sufficiently close to
> each other, even if they belong to the same object file. To address this
> concern, this patch also adds a small API abstraction on top of the GOT
> allocation mechanism that will allow (temporarily, until the MemoryManager
> is improved) using the stub mechanism instead of allocating a different
> section. The actual switch from separate section to stub mechanism will be
> part of a follow-on commit, so that it can be easily reverted independently
> at the appropriate time.
>
> Test Plan: Includes a test case where the GOT of two object files is
> artificially forced to be apart by several GB.
>
> Reviewers: lhames
>
> Reviewed By: lhames
>
> Subscribers: llvm-commits
>
> Differential Revision: http://reviews.llvm.org/D8813
>
> Added:
>
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/ELF_x64-64_PIC_relocations.s
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/Inputs/
>
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/Inputs/ExternalGlobal.ll
> Modified:
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
> llvm/trunk/test/ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll
>
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=234839&r1=234838&r2=234839&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Mon Apr 13
> 21:10:35 2015
> @@ -814,7 +814,6 @@ void RuntimeDyldImpl::resolveExternalSym
> report_fatal_error("Program used external function '" + Name +
> "' which could not be resolved!");
>
> - updateGOTEntries(Name, Addr);
> DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t"
> << format("0x%lx", Addr) << "\n");
> // This list may have been updated when we called getSymbolAddress,
> so
>
> Modified:
> llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h?rev=234839&r1=234838&r2=234839&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
> (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
> Mon Apr 13 21:10:35 2015
> @@ -19,6 +19,7 @@ class RuntimeDyldCheckerImpl {
> friend class RuntimeDyldChecker;
> friend class RuntimeDyldImpl;
> friend class RuntimeDyldCheckerExprEval;
> + friend class RuntimeDyldELF;
>
> public:
> RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler
> *Disassembler,
>
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp?rev=234839&r1=234838&r2=234839&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
> (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp Mon Apr
> 13 21:10:35 2015
> @@ -12,6 +12,7 @@
>
> //===----------------------------------------------------------------------===//
>
> #include "RuntimeDyldELF.h"
> +#include "RuntimeDyldCheckerImpl.h"
> #include "llvm/ADT/IntervalMap.h"
> #include "llvm/ADT/STLExtras.h"
> #include "llvm/ADT/StringRef.h"
> @@ -185,7 +186,7 @@ namespace llvm {
>
> RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr,
> RuntimeDyld::SymbolResolver &Resolver)
> - : RuntimeDyldImpl(MemMgr, Resolver) {}
> + : RuntimeDyldImpl(MemMgr, Resolver), GOTSectionID(0),
> CurrentGOTIndex(0) {}
> RuntimeDyldELF::~RuntimeDyldELF() {}
>
> void RuntimeDyldELF::registerEHFrames() {
> @@ -245,27 +246,16 @@ void RuntimeDyldELF::resolveX86_64Reloca
> << format("%p\n", Section.Address + Offset));
> break;
> }
> - case ELF::R_X86_64_GOTPCREL: {
> - // findGOTEntry returns the 'G + GOT' part of the relocation
> calculation
> - // based on the load/target address of the GOT (not the current/local
> addr).
> - uint64_t GOTAddr = findGOTEntry(Value, SymOffset);
> - uint64_t FinalAddress = Section.LoadAddress + Offset;
> - // The processRelocationRef method combines the symbol offset and the
> addend
> - // and in most cases that's what we want. For this relocation type,
> we need
> - // the raw addend, so we subtract the symbol offset to get it.
> - int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress;
> - assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
> - int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
> - support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset;
> - break;
> - }
> case ELF::R_X86_64_PC32: {
> // Get the placeholder value from the generated object since
> // a previous relocation attempt may have overwritten the loaded
> version
> support::ulittle32_t::ref Placeholder(
> (void *)(Section.ObjAddress + Offset));
> uint64_t FinalAddress = Section.LoadAddress + Offset;
> - int64_t RealOffset = Placeholder + Value + Addend - FinalAddress;
> + int64_t RealOffset = Value + Addend - FinalAddress;
> + // Don't add the placeholder if this is a stub
> + if (Offset < Section.Size)
> + RealOffset += Placeholder;
> assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
> int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
> support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset;
> @@ -277,8 +267,10 @@ void RuntimeDyldELF::resolveX86_64Reloca
> support::ulittle64_t::ref Placeholder(
> (void *)(Section.ObjAddress + Offset));
> uint64_t FinalAddress = Section.LoadAddress + Offset;
> - support::ulittle64_t::ref(Section.Address + Offset) =
> - Placeholder + Value + Addend - FinalAddress;
> + int64_t RealOffset = Value + Addend - FinalAddress;
> + if (Offset < Section.Size)
> + RealOffset += Placeholder;
> + support::ulittle64_t::ref(Section.Address + Offset) = RealOffset;
> break;
> }
> }
> @@ -1323,16 +1315,18 @@ relocation_iterator RuntimeDyldELF::proc
> Stubs[Value] = StubOffset;
> createStubFunction((uint8_t *)StubAddress);
>
> - // Create a GOT entry for the external function.
> - GOTEntries.push_back(Value);
> -
> - // Make our stub function a relative call to the GOT entry.
> - RelocationEntry RE(SectionID, StubOffset + 2,
> ELF::R_X86_64_GOTPCREL,
> - -4);
> - addRelocationForSymbol(RE, Value.SymbolName);
> -
> // Bump our stub offset counter
> Section.StubOffset = StubOffset + getMaxStubSize();
> +
> + // Allocate a GOT Entry
> + uint64_t GOTOffset = allocateGOTEntries(SectionID, 1);
> +
> + // The load of the GOT address has an addend of -4
> + resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset -
> 4);
> +
> + // Fill in the value of the symbol we're targeting into the GOT
> +
> addRelocationForSymbol(computeGOTOffsetRE(SectionID,GOTOffset,0,ELF::R_X86_64_64),
> + Value.SymbolName);
> }
>
> // Make the target call a call into the stub table.
> @@ -1343,10 +1337,17 @@ relocation_iterator RuntimeDyldELF::proc
> Value.Offset);
> addRelocationForSection(RE, Value.SectionID);
> }
> + } else if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL)
> {
> + uint64_t GOTOffset = allocateGOTEntries(SectionID, 1);
> + resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend);
> +
> + // Fill in the value of the symbol we're targeting into the GOT
> + RelocationEntry RE = computeGOTOffsetRE(SectionID, GOTOffset,
> Value.Offset, ELF::R_X86_64_64);
> + if (Value.SymbolName)
> + addRelocationForSymbol(RE, Value.SymbolName);
> + else
> + addRelocationForSection(RE, Value.SectionID);
> } else {
> - if (Arch == Triple::x86_64 && RelType == ELF::R_X86_64_GOTPCREL) {
> - GOTEntries.push_back(Value);
> - }
> RelocationEntry RE(SectionID, Offset, RelType, Value.Addend,
> Value.Offset);
> if (Value.SymbolName)
> addRelocationForSymbol(RE, Value.SymbolName);
> @@ -1356,22 +1357,6 @@ relocation_iterator RuntimeDyldELF::proc
> return ++RelI;
> }
>
> -void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) {
> -
> - SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator it;
> - SmallVectorImpl<std::pair<SID, GOTRelocations>>::iterator end =
> GOTs.end();
> -
> - for (it = GOTs.begin(); it != end; ++it) {
> - GOTRelocations &GOTEntries = it->second;
> - for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
> - if (GOTEntries[i].SymbolName != nullptr &&
> - GOTEntries[i].SymbolName == Name) {
> - GOTEntries[i].Offset = Addr;
> - }
> - }
> - }
> -}
> -
> size_t RuntimeDyldELF::getGOTEntrySize() {
> // We don't use the GOT in all of these cases, but it's essentially free
> // to put them all here.
> @@ -1398,75 +1383,50 @@ size_t RuntimeDyldELF::getGOTEntrySize()
> return Result;
> }
>
> -uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t
> Offset) {
> -
> - const size_t GOTEntrySize = getGOTEntrySize();
> -
> - SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator it;
> - SmallVectorImpl<std::pair<SID, GOTRelocations>>::const_iterator end =
> - GOTs.end();
> -
> - int GOTIndex = -1;
> - for (it = GOTs.begin(); it != end; ++it) {
> - SID GOTSectionID = it->first;
> - const GOTRelocations &GOTEntries = it->second;
> -
> - // Find the matching entry in our vector.
> - uint64_t SymbolOffset = 0;
> - for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
> - if (!GOTEntries[i].SymbolName) {
> - if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress
> &&
> - GOTEntries[i].Offset == Offset) {
> - GOTIndex = i;
> - SymbolOffset = GOTEntries[i].Offset;
> - break;
> - }
> - } else {
> - // GOT entries for external symbols use the addend as the address
> when
> - // the external symbol has been resolved.
> - if (GOTEntries[i].Offset == LoadAddress) {
> - GOTIndex = i;
> - // Don't use the Addend here. The relocation handler will use
> it.
> - break;
> - }
> - }
> - }
> -
> - if (GOTIndex != -1) {
> - if (GOTEntrySize == sizeof(uint64_t)) {
> - uint64_t *LocalGOTAddr = (uint64_t
> *)getSectionAddress(GOTSectionID);
> - // Fill in this entry with the address of the symbol being
> referenced.
> - LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset;
> - } else {
> - uint32_t *LocalGOTAddr = (uint32_t
> *)getSectionAddress(GOTSectionID);
> - // Fill in this entry with the address of the symbol being
> referenced.
> - LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset);
> - }
> -
> - // Calculate the load address of this entry
> - return getSectionLoadAddress(GOTSectionID) + (GOTIndex *
> GOTEntrySize);
> - }
> - }
> -
> - assert(GOTIndex != -1 && "Unable to find requested GOT entry.");
> - return 0;
> +uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned SectionID, unsigned
> no)
> +{
> + (void)SectionID; // The GOT Section is the same for all section in the
> object file
> + if (GOTSectionID == 0) {
> + GOTSectionID = Sections.size();
> + // Reserve a section id. We'll allocate the section later
> + // once we know the total size
> + Sections.push_back(SectionEntry(".got", 0, 0, 0));
> + }
> + uint64_t StartOffset = CurrentGOTIndex * getGOTEntrySize();
> + CurrentGOTIndex += no;
> + return StartOffset;
> +}
> +
> +void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID,
> uint64_t Offset, uint64_t GOTOffset)
> +{
> + // Fill in the relative address of the GOT Entry into the stub
> + RelocationEntry GOTRE(SectionID, Offset, ELF::R_X86_64_PC32, GOTOffset);
> + addRelocationForSection(GOTRE, GOTSectionID);
> +}
> +
> +RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(unsigned SectionID,
> uint64_t GOTOffset, uint64_t SymbolOffset,
> + uint32_t Type)
> +{
> + (void)SectionID; // The GOT Section is the same for all section in the
> object file
> + return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset);
> }
>
> void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
> ObjSectionToIDMap &SectionMap) {
> // If necessary, allocate the global offset table
> - size_t numGOTEntries = GOTEntries.size();
> - if (numGOTEntries != 0) {
> + if (GOTSectionID != 0) {
> // Allocate memory for the section
> - unsigned SectionID = Sections.size();
> - size_t TotalSize = numGOTEntries * getGOTEntrySize();
> + size_t TotalSize = CurrentGOTIndex * getGOTEntrySize();
> uint8_t *Addr = MemMgr.allocateDataSection(TotalSize,
> getGOTEntrySize(),
> - SectionID, ".got", false);
> + GOTSectionID, ".got",
> false);
> if (!Addr)
> report_fatal_error("Unable to allocate memory for GOT!");
>
> - GOTs.push_back(std::make_pair(SectionID, GOTEntries));
> - Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0));
> + Sections[GOTSectionID] = SectionEntry(".got", Addr, TotalSize, 0);
> +
> + if (Checker)
> + Checker->registerSection(Obj.getFileName(), GOTSectionID);
> +
> // For now, initialize all GOT entries to zero. We'll fill them in as
> // needed when GOT-based relocations are applied.
> memset(Addr, 0, TotalSize);
> @@ -1483,6 +1443,9 @@ void RuntimeDyldELF::finalizeLoad(const
> break;
> }
> }
> +
> + GOTSectionID = 0;
> + CurrentGOTIndex = 0;
> }
>
> bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj)
> const {
>
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h?rev=234839&r1=234838&r2=234839&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h Mon Apr 13
> 21:10:35 2015
> @@ -80,16 +80,32 @@ class RuntimeDyldELF : public RuntimeDyl
> ObjSectionToIDMap &LocalSections,
> RelocationValueRef &Rel);
>
> - uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset);
> size_t getGOTEntrySize();
>
> - void updateGOTEntries(StringRef Name, uint64_t Addr) override;
> + SectionEntry &getSection(unsigned SectionID) { return
> Sections[SectionID]; }
>
> - // Relocation entries for symbols whose position-independent offset is
> - // updated in a global offset table.
> - typedef SmallVector<RelocationValueRef, 2> GOTRelocations;
> - GOTRelocations GOTEntries; // List of entries requiring finalization.
> - SmallVector<std::pair<SID, GOTRelocations>, 8> GOTs; // Allocated
> tables.
> + // Allocate no GOT entries for use in the given section.
> + uint64_t allocateGOTEntries(unsigned SectionID, unsigned no);
> +
> + // Resolve the relvative address of GOTOffset in Section ID and place
> + // it at the given Offset
> + void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset,
> + uint64_t GOTOffset);
> +
> + // For a GOT entry referenced from SectionID, compute a relocation entry
> + // that will place the final resolved value in the GOT slot
> + RelocationEntry computeGOTOffsetRE(unsigned SectionID,
> + uint64_t GOTOffset,
> + uint64_t SymbolOffset,
> + unsigned Type);
> +
> + // The tentative ID for the GOT section
> + unsigned GOTSectionID;
> +
> + // Records the current number of allocated slots in the GOT
> + // (This would be equivalent to GOTEntries.size() were it not for
> relocations
> + // that consume more than one slot)
> + unsigned CurrentGOTIndex;
>
> // When a module is loaded we save the SectionID of the EH frame section
> // in a table until we receive a request to register all unregistered
>
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h?rev=234839&r1=234838&r2=234839&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h Mon Apr
> 13 21:10:35 2015
> @@ -361,10 +361,6 @@ protected:
> /// \brief Resolve relocations to external symbols.
> void resolveExternalSymbols();
>
> - /// \brief Update GOT entries for external symbols.
> - // The base class does nothing. ELF overrides this.
> - virtual void updateGOTEntries(StringRef Name, uint64_t Addr) {}
> -
> // \brief Compute an upper bound of the memory that is required to load
> all
> // sections
> void computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize,
>
> Modified: llvm/trunk/test/ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll?rev=234839&r1=234838&r2=234839&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll
> (original)
> +++ llvm/trunk/test/ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll Mon Apr
> 13 21:10:35 2015
> @@ -1,4 +1,5 @@
> ; RUN: %lli -extra-module=%p/Inputs/cross-module-b.ll
> -relocation-model=pic -code-model=small %s > /dev/null
> +; RUN: %lli -mtriple=x86_64-pc-linux
> -extra-module=%p/Inputs/cross-module-b.ll -relocation-model=pic
> -code-model=small %s > /dev/null
> ; XFAIL: mips, i686, i386
>
> declare i32 @FB()
>
> Added:
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/ELF_x64-64_PIC_relocations.s
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/ELF_x64-64_PIC_relocations.s?rev=234839&view=auto
>
> ==============================================================================
> ---
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/ELF_x64-64_PIC_relocations.s
> (added)
> +++
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/ELF_x64-64_PIC_relocations.s
> Mon Apr 13 21:10:35 2015
> @@ -0,0 +1,31 @@
> +# RUN: llvm-mc -triple=x86_64-pc-linux -relocation-model=pic
> -filetype=obj -o %T/test_ELF1_x86-64.o %s
> +# RUN: llvm-mc -triple=x86_64-pc-linux -relocation-model=pic
> -filetype=obj -o %T/test_ELF2_x86-64.o %s
> +# RUN: llc -mtriple=x86_64-pc-linux -relocation-model=pic -filetype=obj
> -o %T/test_ELF_ExternalGlobal_x86-64.o %S/Inputs/ExternalGlobal.ll
> +# RUN: llvm-rtdyld -triple=x86_64-pc-linux -verify %T/test_ELF1_x86-64.o
> %T/test_ELF_ExternalGlobal_x86-64.o
> +# Test that we can load this code twice at memory locations more than 2GB
> apart
> +# RUN: llvm-rtdyld -triple=x86_64-pc-linux -verify -map-section
> test_ELF1_x86-64.o,.got=0x10000 -map-section
> test_ELF2_x86-64.o,.text=0x100000000 -map-section
> test_ELF2_x86-64.o,.got=0x100010000 %T/test_ELF1_x86-64.o
> %T/test_ELF2_x86-64.o %T/test_ELF_ExternalGlobal_x86-64.o
> +
> +# Assembly obtained by compiling the following and adding checks:
> +# @G = external global i8*
> +#
> +# define i8* @foo() {
> +# %ret = load i8** @G
> +# ret i32 %ret
> +# }
> +#
> +
> +#
> + .text
> + .file "ELF_x64-64_PIC_relocations.ll"
> + .align 16, 0x90
> + .type foo, at function
> +foo: # @foo
> +# BB#0:
> + movq G at GOTPCREL(%rip), %rax
> + movl (%rax), %eax
> + retq
> +.Ltmp0:
> + .size foo, .Ltmp0-foo
> +
> +
> + .section ".note.GNU-stack","", at progbits
>
> Added:
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/Inputs/ExternalGlobal.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/Inputs/ExternalGlobal.ll?rev=234839&view=auto
>
> ==============================================================================
> ---
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/Inputs/ExternalGlobal.ll
> (added)
> +++
> llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/Inputs/ExternalGlobal.ll
> Mon Apr 13 21:10:35 2015
> @@ -0,0 +1,2 @@
> + at F = global i8 0
> + at G = global i8* @F
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150413/4c2b3d4a/attachment.html>
More information about the llvm-commits
mailing list