Search in sources :

Example 1 with DebugInfoProvider

use of com.oracle.objectfile.debuginfo.DebugInfoProvider in project graal by oracle.

the class MethodPointerInvalidHandlerFeature method build.

/**
 * Create the image sections for code, constants, and the heap.
 */
@Override
@SuppressWarnings("try")
public void build(String imageName, DebugContext debug) {
    try (DebugContext.Scope buildScope = debug.scope("NativeImage.build")) {
        final CGlobalDataFeature cGlobals = CGlobalDataFeature.singleton();
        long roSectionSize = codeCache.getAlignedConstantsSize();
        long rwSectionSize = ConfigurationValues.getObjectLayout().alignUp(cGlobals.getSize());
        ImageHeapLayoutInfo heapLayout = heap.getLayouter().layout(heap, objectFile.getPageSize());
        // after this point, the layout is final and must not be changed anymore
        assert !hasDuplicatedObjects(heap.getObjects()) : "heap.getObjects() must not contain any duplicates";
        imageHeapSize = heapLayout.getImageHeapSize();
        // Text section (code)
        final int textSectionSize = codeCache.getCodeCacheSize();
        final RelocatableBuffer textBuffer = new RelocatableBuffer(textSectionSize, objectFile.getByteOrder());
        final NativeTextSectionImpl textImpl = NativeTextSectionImpl.factory(textBuffer, objectFile, codeCache);
        textSection = objectFile.newProgbitsSection(SectionName.TEXT.getFormatDependentName(objectFile.getFormat()), objectFile.getPageSize(), false, true, textImpl);
        boolean writable = SubstrateOptions.ForceNoROSectionRelocations.getValue();
        // Read-only data section
        final RelocatableBuffer roDataBuffer = new RelocatableBuffer(roSectionSize, objectFile.getByteOrder());
        final ProgbitsSectionImpl roDataImpl = new BasicProgbitsSectionImpl(roDataBuffer.getBackingArray());
        roDataSection = objectFile.newProgbitsSection(SectionName.RODATA.getFormatDependentName(objectFile.getFormat()), objectFile.getPageSize(), writable, false, roDataImpl);
        // Read-write data section
        final RelocatableBuffer rwDataBuffer = new RelocatableBuffer(rwSectionSize, objectFile.getByteOrder());
        final ProgbitsSectionImpl rwDataImpl = new BasicProgbitsSectionImpl(rwDataBuffer.getBackingArray());
        rwDataSection = objectFile.newProgbitsSection(SectionName.DATA.getFormatDependentName(objectFile.getFormat()), objectFile.getPageSize(), true, false, rwDataImpl);
        // Define symbols for the sections.
        objectFile.createDefinedSymbol(textSection.getName(), textSection, 0, 0, false, false);
        objectFile.createDefinedSymbol("__svm_text_end", textSection, textSectionSize, 0, false, SubstrateOptions.InternalSymbolsAreGlobal.getValue());
        objectFile.createDefinedSymbol(roDataSection.getName(), roDataSection, 0, 0, false, false);
        objectFile.createDefinedSymbol(rwDataSection.getName(), rwDataSection, 0, 0, false, false);
        NativeImageHeapWriter writer = new NativeImageHeapWriter(heap, heapLayout);
        // Write the section contents and record relocations.
        // - The code goes in the text section, by itself.
        textImpl.writeTextSection(debug, textSection, entryPoints);
        // - The constants go at the beginning of the read-only data section.
        codeCache.writeConstants(writer, roDataBuffer);
        // - Non-heap global data goes at the beginning of the read-write data section.
        cGlobals.writeData(rwDataBuffer, (offset, symbolName, isGlobalSymbol) -> objectFile.createDefinedSymbol(symbolName, rwDataSection, offset + RWDATA_CGLOBALS_PARTITION_OFFSET, wordSize, false, isGlobalSymbol || SubstrateOptions.InternalSymbolsAreGlobal.getValue()), (offset, symbolName, isGlobalSymbol) -> defineRelocationForSymbol(symbolName, offset));
        defineDataSymbol(CGlobalDataInfo.CGLOBALDATA_BASE_SYMBOL_NAME, rwDataSection, RWDATA_CGLOBALS_PARTITION_OFFSET);
        /*
             * If we constructed debug info give the object file a chance to install it
             */
        if (SubstrateOptions.GenerateDebugInfo.getValue(HostedOptionValues.singleton()) > 0) {
            Timer timer = TimerCollection.singleton().get(TimerCollection.Registry.DEBUG_INFO);
            try (Timer.StopTimer t = timer.start()) {
                ImageSingletons.add(SourceManager.class, new SourceManager());
                DebugInfoProvider provider = new NativeImageDebugInfoProvider(debug, codeCache, heap);
                objectFile.installDebugInfo(provider);
            }
            ProgressReporter.singleton().setDebugInfoTimer(timer);
        }
        // - Write the heap to its own section.
        // Dynamic linkers/loaders generally don't ensure any alignment to more than page
        // boundaries, so we take care of this ourselves in CommittedMemoryProvider, if we can.
        int alignment = objectFile.getPageSize();
        RelocatableBuffer heapSectionBuffer = new RelocatableBuffer(imageHeapSize, objectFile.getByteOrder());
        ProgbitsSectionImpl heapSectionImpl = new BasicProgbitsSectionImpl(heapSectionBuffer.getBackingArray());
        heapSection = objectFile.newProgbitsSection(SectionName.SVM_HEAP.getFormatDependentName(objectFile.getFormat()), alignment, writable, false, heapSectionImpl);
        objectFile.createDefinedSymbol(heapSection.getName(), heapSection, 0, 0, false, false);
        long offsetOfARelocatablePointer = writer.writeHeap(debug, heapSectionBuffer);
        assert !SubstrateOptions.SpawnIsolates.getValue() || heapSectionBuffer.getByteBuffer().getLong((int) offsetOfARelocatablePointer) == 0L;
        defineDataSymbol(Isolates.IMAGE_HEAP_BEGIN_SYMBOL_NAME, heapSection, 0);
        defineDataSymbol(Isolates.IMAGE_HEAP_END_SYMBOL_NAME, heapSection, imageHeapSize);
        defineDataSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME, heapSection, heapLayout.getReadOnlyRelocatableOffset());
        defineDataSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME, heapSection, heapLayout.getReadOnlyRelocatableOffset() + heapLayout.getReadOnlyRelocatableSize());
        defineDataSymbol(Isolates.IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME, heapSection, offsetOfARelocatablePointer);
        defineDataSymbol(Isolates.IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME, heapSection, heapLayout.getWritableOffset());
        defineDataSymbol(Isolates.IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME, heapSection, heapLayout.getWritableOffset() + heapLayout.getWritableSize());
        // Mark the sections with the relocations from the maps.
        markRelocationSitesFromBuffer(textBuffer, textImpl);
        markRelocationSitesFromBuffer(roDataBuffer, roDataImpl);
        markRelocationSitesFromBuffer(rwDataBuffer, rwDataImpl);
        markRelocationSitesFromBuffer(heapSectionBuffer, heapSectionImpl);
        // We print the heap statistics after the heap was successfully written because this
        // could modify objects that will be part of the image heap.
        printHeapStatistics(heap.getLayouter().getPartitions());
    }
// [Footnote 1]
// 
// Subject: Re: Do you know why text references can only be to constants?
// Date: Fri, 09 Jan 2015 12:51:15 -0800
// From: Christian Wimmer <christian.wimmer@oracle.com>
// To: Peter B. Kessler <Peter.B.Kessler@Oracle.COM>
// 
// Code (i.e. the text section) needs to load the address of objects. So
// the read-only section contains a 8-byte slot with the address of the
// object that you actually want to load. A RIP-relative move instruction
// is used to load this 8-byte slot. The relocation for the move ensures
// the offset of the move is patched. And then a relocation from the
// read-only section to the actual native image heap ensures the 8-byte slot
// contains the actual address of the object to be loaded.
// 
// Therefore, relocations in .text go only to things in .rodata; and
// relocations in .rodata go to .data in the current implementation
// 
// It might be possible to have a RIP-relative load-effective-address (LEA)
// instruction to go directly from .text to .data, eliminating the memory
// access to load the address of an object. So I agree that allowing
// relocation from .text only to .rodata is an arbitrary restriction that
// could prevent future optimizations.
// 
// -Christian
}
Also used : DebugContext(org.graalvm.compiler.debug.DebugContext) DebugInfoProvider(com.oracle.objectfile.debuginfo.DebugInfoProvider) ProgbitsSectionImpl(com.oracle.objectfile.ObjectFile.ProgbitsSectionImpl) BasicProgbitsSectionImpl(com.oracle.objectfile.BasicProgbitsSectionImpl) ImageHeapLayoutInfo(com.oracle.svm.core.image.ImageHeapLayoutInfo) Timer(com.oracle.graal.pointsto.util.Timer) BasicProgbitsSectionImpl(com.oracle.objectfile.BasicProgbitsSectionImpl) SourceManager(com.oracle.svm.hosted.image.sources.SourceManager) CGlobalDataFeature(com.oracle.svm.hosted.c.CGlobalDataFeature)

Aggregations

Timer (com.oracle.graal.pointsto.util.Timer)1 BasicProgbitsSectionImpl (com.oracle.objectfile.BasicProgbitsSectionImpl)1 ProgbitsSectionImpl (com.oracle.objectfile.ObjectFile.ProgbitsSectionImpl)1 DebugInfoProvider (com.oracle.objectfile.debuginfo.DebugInfoProvider)1 ImageHeapLayoutInfo (com.oracle.svm.core.image.ImageHeapLayoutInfo)1 CGlobalDataFeature (com.oracle.svm.hosted.c.CGlobalDataFeature)1 SourceManager (com.oracle.svm.hosted.image.sources.SourceManager)1 DebugContext (org.graalvm.compiler.debug.DebugContext)1