brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · ca38cba Raw
180 lines · plain
1===============================2MCJIT Design and Implementation3===============================4 5Introduction6============7 8This document describes the internal workings of the MCJIT execution9engine and the RuntimeDyld component.  It is intended as a high level10overview of the implementation, showing the flow and interactions of11objects throughout the code generation and dynamic loading process.12 13Engine Creation14===============15 16In most cases, an EngineBuilder object is used to create an instance of17the MCJIT execution engine.  The EngineBuilder takes an llvm::Module18object as an argument to its constructor.  The client may then set various19options that we control the later be passed along to the MCJIT engine,20including the selection of MCJIT as the engine type to be created.21Of particular interest is the EngineBuilder::setMCJITMemoryManager22function.  If the client does not explicitly create a memory manager at23this time, a default memory manager (specifically SectionMemoryManager)24will be created when the MCJIT engine is instantiated.25 26Once the options have been set, a client calls EngineBuilder::create to27create an instance of the MCJIT engine.  If the client does not use the28form of this function that takes a TargetMachine as a parameter, a new29TargetMachine will be created based on the target triple associated with30the Module that was used to create the EngineBuilder.31 32.. image:: MCJIT-engine-builder.png33 34EngineBuilder::create will call the static MCJIT::createJIT function,35passing in its pointers to the module, memory manager and target machine36objects, all of which will subsequently be owned by the MCJIT object.37 38The MCJIT class has a member variable, Dyld, which contains an instance of39the RuntimeDyld wrapper class.  This member will be used for40communications between MCJIT and the actual RuntimeDyldImpl object that41gets created when an object is loaded.42 43.. image:: MCJIT-creation.png44 45Upon creation, MCJIT holds a pointer to the Module object that it received46from EngineBuilder but it does not immediately generate code for this47module.  Code generation is deferred until either the48MCJIT::finalizeObject method is called explicitly or a function such as49MCJIT::getPointerToFunction is called which requires the code to have been50generated.51 52Code Generation53===============54 55When code generation is triggered, as described above, MCJIT will first56attempt to retrieve an object image from its ObjectCache member, if one57has been set.  If a cached object image cannot be retrieved, MCJIT will58call its emitObject method.  MCJIT::emitObject uses a local PassManager59instance and creates a new ObjectBufferStream instance, both of which it60passes to TargetMachine::addPassesToEmitMC before calling PassManager::run61on the Module with which it was created.62 63.. image:: MCJIT-load.png64 65The PassManager::run call causes the MC code generation mechanisms to emit66a complete relocatable binary object image (either in either ELF or MachO67format, depending on the target) into the ObjectBufferStream object, which68is flushed to complete the process.  If an ObjectCache is being used, the69image will be passed to the ObjectCache here.70 71At this point, the ObjectBufferStream contains the raw object image.72Before the code can be executed, the code and data sections from this73image must be loaded into suitable memory, relocations must be applied and74memory permission and code cache invalidation (if required) must be completed.75 76Object Loading77==============78 79Once an object image has been obtained, either through code generation or80having been retrieved from an ObjectCache, it is passed to RuntimeDyld to81be loaded.  The RuntimeDyld wrapper class examines the object to determine82its file format and creates an instance of either RuntimeDyldELF or83RuntimeDyldMachO (both of which derive from the RuntimeDyldImpl base84class) and calls the RuntimeDyldImpl::loadObject method to perform that85actual loading.86 87.. image:: MCJIT-dyld-load.png88 89RuntimeDyldImpl::loadObject begins by creating an ObjectImage instance90from the ObjectBuffer it received.  ObjectImage, which wraps the91ObjectFile class, is a helper class which parses the binary object image92and provides access to the information contained in the format-specific93headers, including section, symbol and relocation information.94 95RuntimeDyldImpl::loadObject then iterates through the symbols in the96image.  Information about common symbols is collected for later use.  For97each function or data symbol, the associated section is loaded into memory98and the symbol is stored in a symbol table map data structure.  When the99iteration is complete, a section is emitted for the common symbols.100 101Next, RuntimeDyldImpl::loadObject iterates through the sections in the102object image and for each section iterates through the relocations for103that sections.  For each relocation, it calls the format-specific104processRelocationRef method, which will examine the relocation and store105it in one of two data structures, a section-based relocation list map and106an external symbol relocation map.107 108.. image:: MCJIT-load-object.png109 110When RuntimeDyldImpl::loadObject returns, all of the code and data111sections for the object will have been loaded into memory allocated by the112memory manager and relocation information will have been prepared, but the113relocations have not yet been applied and the generated code is still not114ready to be executed.115 116[Currently (as of August 2013) the MCJIT engine will immediately apply117relocations when loadObject completes.  However, this shouldn't be118happening.  Because the code may have been generated for a remote target,119the client should be given a chance to re-map the section addresses before120relocations are applied.  It is possible to apply relocations multiple121times, but in the case where addresses are to be re-mapped, this first122application is wasted effort.]123 124Address Remapping125=================126 127At any time after initial code has been generated and before128finalizeObject is called, the client can remap the address of sections in129the object.  Typically this is done because the code was generated for an130external process and is being mapped into that process' address space.131The client remaps the section address by calling MCJIT::mapSectionAddress.132This should happen before the section memory is copied to its new133location.134 135When MCJIT::mapSectionAddress is called, MCJIT passes the call on to136RuntimeDyldImpl (via its Dyld member).  RuntimeDyldImpl stores the new137address in an internal data structure but does not update the code at this138time, since other sections are likely to change.139 140When the client is finished remapping section addresses, it will call141MCJIT::finalizeObject to complete the remapping process.142 143Final Preparations144==================145 146When MCJIT::finalizeObject is called, MCJIT calls147RuntimeDyld::resolveRelocations.  This function will attempt to locate any148external symbols and then apply all relocations for the object.149 150External symbols are resolved by calling the memory manager's151getPointerToNamedFunction method.  The memory manager will return the152address of the requested symbol in the target address space.  (Note, this153may not be a valid pointer in the host process.)  RuntimeDyld will then154iterate through the list of relocations it has stored which are associated155with this symbol and invoke the resolveRelocation method which, through an156format-specific implementation, will apply the relocation to the loaded157section memory.158 159Next, RuntimeDyld::resolveRelocations iterates through the list of160sections and for each section iterates through a list of relocations that161have been saved which reference that symbol and call resolveRelocation for162each entry in this list.  The relocation list here is a list of163relocations for which the symbol associated with the relocation is located164in the section associated with the list.  Each of these locations will165have a target location at which the relocation will be applied that is166likely located in a different section.167 168.. image:: MCJIT-resolve-relocations.png169 170Once relocations have been applied as described above, MCJIT calls171RuntimeDyld::getEHFrameSection, and if a non-zero result is returned172passes the section data to the memory manager's registerEHFrames method.173This allows the memory manager to call any desired target-specific174functions, such as registering the EH frame information with a debugger.175 176Finally, MCJIT calls the memory manager's finalizeMemory method.  In this177method, the memory manager will invalidate the target code cache, if178necessary, and apply final permissions to the memory pages it has179allocated for code and data memory.180