mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 12:50:00 +00:00
Put RTDyldMemoryManager into its own file, and make it linked into
libExecutionEngine. Move method implementations that aren't specific to allocation out of SectionMemoryManager and into RTDyldMemoryManager. This is in preparation for exposing RTDyldMemoryManager through the C API. This is a fixed version of r182407 and r182411. That first revision broke builds because I forgot to move the conditional includes of various POSIX headers from SectionMemoryManager into RTDyldMemoryManager. Those includes are necessary because of how getPointerToNamedFunction works around the glibc libc_nonshared.a thing. The latter revision still broke things because I forgot to include llvm/Config/config.h. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182418 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
50f19a906a
commit
a4ea4a7203
76
include/llvm/ExecutionEngine/RTDyldMemoryManager.h
Normal file
76
include/llvm/ExecutionEngine/RTDyldMemoryManager.h
Normal file
@ -0,0 +1,76 @@
|
||||
//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Interface of the runtime dynamic memory manager base class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H
|
||||
#define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#include "llvm/Support/Memory.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// RuntimeDyld clients often want to handle the memory management of
|
||||
// what gets placed where. For JIT clients, this is the subset of
|
||||
// JITMemoryManager required for dynamic loading of binaries.
|
||||
//
|
||||
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
|
||||
// for the varying types of objects to be allocated.
|
||||
class RTDyldMemoryManager {
|
||||
RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
RTDyldMemoryManager() {}
|
||||
virtual ~RTDyldMemoryManager();
|
||||
|
||||
/// Allocate a memory block of (at least) the given size suitable for
|
||||
/// executable code. The SectionID is a unique identifier assigned by the JIT
|
||||
/// engine, and optionally recorded by the memory manager to access a loaded
|
||||
/// section.
|
||||
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
|
||||
unsigned SectionID) = 0;
|
||||
|
||||
/// Allocate a memory block of (at least) the given size suitable for data.
|
||||
/// The SectionID is a unique identifier assigned by the JIT engine, and
|
||||
/// optionally recorded by the memory manager to access a loaded section.
|
||||
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||
unsigned SectionID, bool IsReadOnly) = 0;
|
||||
|
||||
/// Register the EH frames with the runtime so that c++ exceptions work.
|
||||
virtual void registerEHFrames(StringRef SectionData);
|
||||
|
||||
/// This method returns the address of the specified function. As such it is
|
||||
/// only useful for resolving library symbols, not code generated symbols.
|
||||
///
|
||||
/// If \p AbortOnFailure is false and no function with the given name is
|
||||
/// found, this function returns a null pointer. Otherwise, it prints a
|
||||
/// message to stderr and aborts.
|
||||
virtual void *getPointerToNamedFunction(const std::string &Name,
|
||||
bool AbortOnFailure = true);
|
||||
|
||||
/// This method is called when object loading is complete and section page
|
||||
/// permissions can be applied. It is up to the memory manager implementation
|
||||
/// to decide whether or not to act on this method. The memory manager will
|
||||
/// typically allocate all sections as read-write and then apply specific
|
||||
/// permissions when this method is called. Code sections cannot be executed
|
||||
/// until this function has been called. In addition, any cache coherency
|
||||
/// operations needed to reliably use the memory are also performed.
|
||||
///
|
||||
/// Returns true if an error occurred, false otherwise.
|
||||
virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ExecutionEngine/ObjectBuffer.h"
|
||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||
#include "llvm/Support/Memory.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -23,58 +24,6 @@ namespace llvm {
|
||||
class RuntimeDyldImpl;
|
||||
class ObjectImage;
|
||||
|
||||
// RuntimeDyld clients often want to handle the memory management of
|
||||
// what gets placed where. For JIT clients, this is the subset of
|
||||
// JITMemoryManager required for dynamic loading of binaries.
|
||||
//
|
||||
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
|
||||
// for the varying types of objects to be allocated.
|
||||
class RTDyldMemoryManager {
|
||||
RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
RTDyldMemoryManager() {}
|
||||
virtual ~RTDyldMemoryManager();
|
||||
|
||||
/// Allocate a memory block of (at least) the given size suitable for
|
||||
/// executable code. The SectionID is a unique identifier assigned by the JIT
|
||||
/// engine, and optionally recorded by the memory manager to access a loaded
|
||||
/// section.
|
||||
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
|
||||
unsigned SectionID) = 0;
|
||||
|
||||
/// Allocate a memory block of (at least) the given size suitable for data.
|
||||
/// The SectionID is a unique identifier assigned by the JIT engine, and
|
||||
/// optionally recorded by the memory manager to access a loaded section.
|
||||
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
||||
unsigned SectionID, bool IsReadOnly) = 0;
|
||||
|
||||
/// This method returns the address of the specified function. As such it is
|
||||
/// only useful for resolving library symbols, not code generated symbols.
|
||||
///
|
||||
/// If AbortOnFailure is false and no function with the given name is
|
||||
/// found, this function returns a null pointer. Otherwise, it prints a
|
||||
/// message to stderr and aborts.
|
||||
virtual void *getPointerToNamedFunction(const std::string &Name,
|
||||
bool AbortOnFailure = true) = 0;
|
||||
|
||||
/// This method is called when object loading is complete and section page
|
||||
/// permissions can be applied. It is up to the memory manager implementation
|
||||
/// to decide whether or not to act on this method. The memory manager will
|
||||
/// typically allocate all sections as read-write and then apply specific
|
||||
/// permissions when this method is called. Code sections cannot be executed
|
||||
/// until this function has been called. In addition, any cache coherency
|
||||
/// operations needed to reliably use the memory are also performed.
|
||||
///
|
||||
/// Returns true if an error occurred, false otherwise.
|
||||
virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0;
|
||||
|
||||
/// Register the EH frames with the runtime so that c++ exceptions work. The
|
||||
/// default implementation does nothing. Look at SectionMemoryManager for one
|
||||
/// that uses __register_frame.
|
||||
virtual void registerEHFrames(StringRef SectionData);
|
||||
};
|
||||
|
||||
class RuntimeDyld {
|
||||
RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
|
||||
|
@ -73,17 +73,6 @@ public:
|
||||
/// \returns true if an error occurred, false otherwise.
|
||||
virtual bool finalizeMemory(std::string *ErrMsg = 0);
|
||||
|
||||
void registerEHFrames(StringRef SectionData);
|
||||
|
||||
/// This method returns the address of the specified function. As such it is
|
||||
/// only useful for resolving library symbols, not code generated symbols.
|
||||
///
|
||||
/// If \p AbortOnFailure is false and no function with the given name is
|
||||
/// found, this function returns a null pointer. Otherwise, it prints a
|
||||
/// message to stderr and aborts.
|
||||
virtual void *getPointerToNamedFunction(const std::string &Name,
|
||||
bool AbortOnFailure = true);
|
||||
|
||||
/// \brief Invalidate instruction cache for code sections.
|
||||
///
|
||||
/// Some platforms with separate data cache and instruction cache require
|
||||
|
@ -3,6 +3,7 @@
|
||||
add_llvm_library(LLVMExecutionEngine
|
||||
ExecutionEngine.cpp
|
||||
ExecutionEngineBindings.cpp
|
||||
RTDyldMemoryManager.cpp
|
||||
TargetSelect.cpp
|
||||
)
|
||||
|
||||
|
@ -14,19 +14,8 @@
|
||||
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
|
||||
#ifdef __linux__
|
||||
// These includes used by SectionMemoryManager::getPointerToNamedFunction()
|
||||
// for Glibc trickery. See comments in this function for more information.
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size,
|
||||
@ -146,38 +135,6 @@ bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine whether we can register EH tables.
|
||||
#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \
|
||||
!defined(__USING_SJLJ_EXCEPTIONS__))
|
||||
#define HAVE_EHTABLE_SUPPORT 1
|
||||
#else
|
||||
#define HAVE_EHTABLE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#if HAVE_EHTABLE_SUPPORT
|
||||
extern "C" void __register_frame(void*);
|
||||
|
||||
static const char *processFDE(const char *Entry) {
|
||||
const char *P = Entry;
|
||||
uint32_t Length = *((uint32_t*)P);
|
||||
P += 4;
|
||||
uint32_t Offset = *((uint32_t*)P);
|
||||
if (Offset != 0)
|
||||
__register_frame((void*)Entry);
|
||||
return P + Length;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SectionMemoryManager::registerEHFrames(StringRef SectionData) {
|
||||
#if HAVE_EHTABLE_SUPPORT
|
||||
const char *P = SectionData.data();
|
||||
const char *End = SectionData.data() + SectionData.size();
|
||||
do {
|
||||
P = processFDE(P);
|
||||
} while(P != End);
|
||||
#endif
|
||||
}
|
||||
|
||||
error_code SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup,
|
||||
unsigned Permissions) {
|
||||
|
||||
@ -199,57 +156,6 @@ void SectionMemoryManager::invalidateInstructionCache() {
|
||||
CodeMem.AllocatedMem[i].size());
|
||||
}
|
||||
|
||||
static int jit_noop() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *SectionMemoryManager::getPointerToNamedFunction(const std::string &Name,
|
||||
bool AbortOnFailure) {
|
||||
#if defined(__linux__)
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Function stubs that are invoked instead of certain library calls
|
||||
//
|
||||
// Force the following functions to be linked in to anything that uses the
|
||||
// JIT. This is a hack designed to work around the all-too-clever Glibc
|
||||
// strategy of making these functions work differently when inlined vs. when
|
||||
// not inlined, and hiding their real definitions in a separate archive file
|
||||
// that the dynamic linker can't see. For more info, search for
|
||||
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
|
||||
if (Name == "stat") return (void*)(intptr_t)&stat;
|
||||
if (Name == "fstat") return (void*)(intptr_t)&fstat;
|
||||
if (Name == "lstat") return (void*)(intptr_t)&lstat;
|
||||
if (Name == "stat64") return (void*)(intptr_t)&stat64;
|
||||
if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
|
||||
if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
|
||||
if (Name == "atexit") return (void*)(intptr_t)&atexit;
|
||||
if (Name == "mknod") return (void*)(intptr_t)&mknod;
|
||||
#endif // __linux__
|
||||
|
||||
// We should not invoke parent's ctors/dtors from generated main()!
|
||||
// On Mingw and Cygwin, the symbol __main is resolved to
|
||||
// callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
|
||||
// (and register wrong callee's dtors with atexit(3)).
|
||||
// We expect ExecutionEngine::runStaticConstructorsDestructors()
|
||||
// is called before ExecutionEngine::runFunctionAsMain() is called.
|
||||
if (Name == "__main") return (void*)(intptr_t)&jit_noop;
|
||||
|
||||
const char *NameStr = Name.c_str();
|
||||
void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
|
||||
if (Ptr) return Ptr;
|
||||
|
||||
// If it wasn't found and if it starts with an underscore ('_') character,
|
||||
// try again without the underscore.
|
||||
if (NameStr[0] == '_') {
|
||||
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
|
||||
if (Ptr) return Ptr;
|
||||
}
|
||||
|
||||
if (AbortOnFailure)
|
||||
report_fatal_error("Program used external function '" + Name +
|
||||
"' which could not be resolved!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SectionMemoryManager::~SectionMemoryManager() {
|
||||
for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i)
|
||||
sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]);
|
||||
|
116
lib/ExecutionEngine/RTDyldMemoryManager.cpp
Normal file
116
lib/ExecutionEngine/RTDyldMemoryManager.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementation of the runtime dynamic memory manager base class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
#ifdef __linux__
|
||||
// These includes used by RTDyldMemoryManager::getPointerToNamedFunction()
|
||||
// for Glibc trickery. See comments in this function for more information.
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
RTDyldMemoryManager::~RTDyldMemoryManager() {}
|
||||
|
||||
// Determine whether we can register EH tables.
|
||||
#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \
|
||||
!defined(__USING_SJLJ_EXCEPTIONS__))
|
||||
#define HAVE_EHTABLE_SUPPORT 1
|
||||
#else
|
||||
#define HAVE_EHTABLE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#if HAVE_EHTABLE_SUPPORT
|
||||
extern "C" void __register_frame(void*);
|
||||
|
||||
static const char *processFDE(const char *Entry) {
|
||||
const char *P = Entry;
|
||||
uint32_t Length = *((uint32_t*)P);
|
||||
P += 4;
|
||||
uint32_t Offset = *((uint32_t*)P);
|
||||
if (Offset != 0)
|
||||
__register_frame((void*)Entry);
|
||||
return P + Length;
|
||||
}
|
||||
#endif
|
||||
|
||||
void RTDyldMemoryManager::registerEHFrames(StringRef SectionData) {
|
||||
#if HAVE_EHTABLE_SUPPORT
|
||||
const char *P = SectionData.data();
|
||||
const char *End = SectionData.data() + SectionData.size();
|
||||
do {
|
||||
P = processFDE(P);
|
||||
} while(P != End);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int jit_noop() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *RTDyldMemoryManager::getPointerToNamedFunction(const std::string &Name,
|
||||
bool AbortOnFailure) {
|
||||
#if defined(__linux__)
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Function stubs that are invoked instead of certain library calls
|
||||
//
|
||||
// Force the following functions to be linked in to anything that uses the
|
||||
// JIT. This is a hack designed to work around the all-too-clever Glibc
|
||||
// strategy of making these functions work differently when inlined vs. when
|
||||
// not inlined, and hiding their real definitions in a separate archive file
|
||||
// that the dynamic linker can't see. For more info, search for
|
||||
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
|
||||
if (Name == "stat") return (void*)(intptr_t)&stat;
|
||||
if (Name == "fstat") return (void*)(intptr_t)&fstat;
|
||||
if (Name == "lstat") return (void*)(intptr_t)&lstat;
|
||||
if (Name == "stat64") return (void*)(intptr_t)&stat64;
|
||||
if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
|
||||
if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
|
||||
if (Name == "atexit") return (void*)(intptr_t)&atexit;
|
||||
if (Name == "mknod") return (void*)(intptr_t)&mknod;
|
||||
#endif // __linux__
|
||||
|
||||
// We should not invoke parent's ctors/dtors from generated main()!
|
||||
// On Mingw and Cygwin, the symbol __main is resolved to
|
||||
// callee's(eg. tools/lli) one, to invoke wrong duplicated ctors
|
||||
// (and register wrong callee's dtors with atexit(3)).
|
||||
// We expect ExecutionEngine::runStaticConstructorsDestructors()
|
||||
// is called before ExecutionEngine::runFunctionAsMain() is called.
|
||||
if (Name == "__main") return (void*)(intptr_t)&jit_noop;
|
||||
|
||||
const char *NameStr = Name.c_str();
|
||||
void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
|
||||
if (Ptr) return Ptr;
|
||||
|
||||
// If it wasn't found and if it starts with an underscore ('_') character,
|
||||
// try again without the underscore.
|
||||
if (NameStr[0] == '_') {
|
||||
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
|
||||
if (Ptr) return Ptr;
|
||||
}
|
||||
|
||||
if (AbortOnFailure)
|
||||
report_fatal_error("Program used external function '" + Name +
|
||||
"' which could not be resolved!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace llvm
|
@ -24,8 +24,6 @@ using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
// Empty out-of-line virtual destructor as the key function.
|
||||
RTDyldMemoryManager::~RTDyldMemoryManager() {}
|
||||
void RTDyldMemoryManager::registerEHFrames(StringRef SectionData) {}
|
||||
RuntimeDyldImpl::~RuntimeDyldImpl() {}
|
||||
|
||||
namespace llvm {
|
||||
|
Loading…
Reference in New Issue
Block a user