mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	The SectionMemoryManager now supports (and requires) applying section-specific page permissions. Clients using this memory manager must call either MCJIT::finalizeObject() or SectionMemoryManager::applyPermissions() before executing JITed code. See r168718 for changes from the previous implementation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168721 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			177 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file contains the declaration of a section-based memory manager used by
 | |
| // the MCJIT execution engine and RuntimeDyld.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
 | |
| #define LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
 | |
| 
 | |
| #include "llvm/ADT/SmallVector.h"
 | |
| #include "llvm/ExecutionEngine/JITMemoryManager.h"
 | |
| #include "llvm/Support/ErrorHandling.h"
 | |
| #include "llvm/Support/Memory.h"
 | |
| 
 | |
| namespace llvm {
 | |
| 
 | |
| /// This is a simple memory manager which implements the methods called by
 | |
| /// the RuntimeDyld class to allocate memory for section-based loading of
 | |
| /// objects, usually those generated by the MCJIT execution engine.
 | |
| ///
 | |
| /// This memory manager allocates all section memory as read-write.  The
 | |
| /// RuntimeDyld will copy JITed section memory into these allocated blocks
 | |
| /// and perform any necessary linking and relocations.
 | |
| ///
 | |
| /// Any client using this memory manager MUST ensure that section-specific
 | |
| /// page permissions have been applied before attempting to execute functions
 | |
| /// in the JITed object.  Permissions can be applied either by calling
 | |
| /// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions
 | |
| /// directly.  Clients of MCJIT should call MCJIT::finalizeObject.
 | |
| class SectionMemoryManager : public JITMemoryManager {
 | |
|   SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
 | |
|   void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION;
 | |
| 
 | |
| public:
 | |
|   SectionMemoryManager() { }
 | |
|   virtual ~SectionMemoryManager();
 | |
| 
 | |
|   /// \brief Allocates a memory block of (at least) the given size suitable for
 | |
|   /// executable code.
 | |
|   ///
 | |
|   /// The value of \p Alignment must be a power of two.  If \p Alignment is zero
 | |
|   /// a default alignment of 16 will be used.
 | |
|   virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
 | |
|                                        unsigned SectionID);
 | |
| 
 | |
|   /// \brief Allocates a memory block of (at least) the given size suitable for
 | |
|   /// executable code.
 | |
|   ///
 | |
|   /// The value of \p Alignment must be a power of two.  If \p Alignment is zero
 | |
|   /// a default alignment of 16 will be used.
 | |
|   virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
 | |
|                                        unsigned SectionID,
 | |
|                                        bool isReadOnly);
 | |
| 
 | |
|   /// \brief Applies section-specific memory permissions.
 | |
|   ///
 | |
|   /// 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.
 | |
|   ///
 | |
|   /// \returns true if an error occurred, false otherwise.
 | |
|   virtual bool applyPermissions(std::string *ErrMsg = 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 \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
 | |
|   /// explicit cache flush, otherwise JIT code manipulations (like resolved
 | |
|   /// relocations) will get to the data cache but not to the instruction cache.
 | |
|   ///
 | |
|   /// This method is not called by RuntimeDyld or MCJIT during the load
 | |
|   /// process.  Clients may call this function when needed.  See the lli
 | |
|   /// tool for example use.
 | |
|   virtual void invalidateInstructionCache();
 | |
| 
 | |
| private:
 | |
|   struct MemoryGroup {
 | |
|       SmallVector<sys::MemoryBlock, 16> AllocatedMem;
 | |
|       SmallVector<sys::MemoryBlock, 16> FreeMem;
 | |
|       sys::MemoryBlock Near;
 | |
|   };
 | |
| 
 | |
|   uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size,
 | |
|                            unsigned Alignment);
 | |
| 
 | |
|   error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
 | |
|                                          unsigned Permissions);
 | |
| 
 | |
|   MemoryGroup CodeMem;
 | |
|   MemoryGroup RWDataMem;
 | |
|   MemoryGroup RODataMem;
 | |
| 
 | |
| public:
 | |
|   ///
 | |
|   /// Functions below are not used by MCJIT or RuntimeDyld, but must be
 | |
|   /// implemented because they are declared as pure virtuals in the base class.
 | |
|   ///
 | |
| 
 | |
|   virtual void setMemoryWritable() {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
|   virtual void setMemoryExecutable() {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
|   virtual void setPoisonMemory(bool poison) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
|   virtual void AllocateGOT() {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
|   virtual uint8_t *getGOTBase() const {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|     return 0;
 | |
|   }
 | |
|   virtual uint8_t *startFunctionBody(const Function *F,
 | |
|                                      uintptr_t &ActualSize){
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|     return 0;
 | |
|   }
 | |
|   virtual uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize,
 | |
|                                 unsigned Alignment) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|     return 0;
 | |
|   }
 | |
|   virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
 | |
|                                uint8_t *FunctionEnd) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
|   virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|     return 0;
 | |
|   }
 | |
|   virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|     return 0;
 | |
|   }
 | |
|   virtual void deallocateFunctionBody(void *Body) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
|   virtual uint8_t *startExceptionTable(const Function *F,
 | |
|                                        uintptr_t &ActualSize) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|     return 0;
 | |
|   }
 | |
|   virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
 | |
|                                  uint8_t *TableEnd, uint8_t *FrameRegister) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
|   virtual void deallocateExceptionTable(void *ET) {
 | |
|     llvm_unreachable("Unexpected call!");
 | |
|   }
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
 | |
| 
 |