Search in sources :

Example 1 with CGlobalDataFeature

use of com.oracle.svm.hosted.c.CGlobalDataFeature in project graal by oracle.

the class NativeBootImage method build.

/**
 * Create the image sections for code, constants, and the heap.
 */
@Override
@SuppressWarnings("try")
public void build(DebugContext debug) {
    try (DebugContext.Scope buildScope = debug.scope("NativeBootImage.build")) {
        final CGlobalDataFeature cGlobals = CGlobalDataFeature.singleton();
        final int textSectionSize = codeCache.getCodeCacheSize();
        final int roConstantsSize = codeCache.getAlignedConstantsSize();
        final int cglobalsSize = ConfigurationValues.getObjectLayout().alignUp(cGlobals.getSize());
        long roSectionSize = roConstantsSize;
        long rwSectionSize = cglobalsSize;
        if (!SubstrateOptions.UseHeapBaseRegister.getValue()) {
            roSectionSize += heap.getReadOnlySectionSize();
            rwSectionSize += heap.getWritableSectionSize();
        }
        // Text section (code)
        final RelocatableBuffer textBuffer = RelocatableBuffer.factory("text", textSectionSize, objectFile.getByteOrder());
        final TextImpl textImpl = TextImpl.factory(textBuffer, objectFile, codeCache);
        final String textSectionName = SectionName.TEXT.getFormatDependentName(objectFile.getFormat());
        textSection = objectFile.newProgbitsSection(textSectionName, objectFile.getPageSize(), false, true, textImpl);
        // Read-only data section
        final RelocatableBuffer roDataBuffer = RelocatableBuffer.factory("roData", roSectionSize, objectFile.getByteOrder());
        final ProgbitsSectionImpl roDataImpl = new BasicProgbitsSectionImpl(roDataBuffer.getBytes());
        final String roDataSectionName = SectionName.RODATA.getFormatDependentName(objectFile.getFormat());
        roDataSection = objectFile.newProgbitsSection(roDataSectionName, objectFile.getPageSize(), false, false, roDataImpl);
        // Read-write data section
        final RelocatableBuffer rwDataBuffer = RelocatableBuffer.factory("rwData", rwSectionSize, objectFile.getByteOrder());
        final ProgbitsSectionImpl rwDataImpl = new BasicProgbitsSectionImpl(rwDataBuffer.getBytes());
        final String rwDataSectionName = SectionName.DATA.getFormatDependentName(objectFile.getFormat());
        rwDataSection = objectFile.newProgbitsSection(rwDataSectionName, 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, codeCache.getCodeCacheSize(), 0, false, true);
        objectFile.createDefinedSymbol(roDataSection.getName(), roDataSection, 0, 0, false, false);
        objectFile.createDefinedSymbol(rwDataSection.getName(), rwDataSection, 0, 0, false, false);
        final long constantsPartitionOffset = 0L;
        final long roConstantsEndOffset = constantsPartitionOffset + roConstantsSize;
        final long rwGlobalsEndOffset = RWDATA_CGLOBALS_PARTITION_OFFSET + ConfigurationValues.getObjectLayout().alignUp(cGlobals.getSize());
        final RelocatableBuffer heapSectionBuffer;
        final ProgbitsSectionImpl heapSectionImpl;
        if (SubstrateOptions.UseHeapBaseRegister.getValue()) {
            boolean writable = !SubstrateOptions.SpawnIsolates.getValue();
            final long heapSize = heap.getReadOnlySectionSize() + heap.getWritableSectionSize();
            heapSectionBuffer = RelocatableBuffer.factory("heap", heapSize, objectFile.getByteOrder());
            heapSectionImpl = new BasicProgbitsSectionImpl(heapSectionBuffer.getBytes());
            final String heapSectionName = SectionName.SVM_HEAP.getFormatDependentName(objectFile.getFormat());
            heapSection = objectFile.newProgbitsSection(heapSectionName, objectFile.getPageSize(), writable, false, heapSectionImpl);
            heap.setReadOnlySection(heapSection.getName(), 0);
            heap.setWritableSection(heapSection.getName(), heap.getReadOnlySectionSize());
            defineDataSymbol(PosixIsolates.IMAGE_HEAP_BEGIN_SYMBOL_NAME, heapSection, 0);
            defineDataSymbol(PosixIsolates.IMAGE_HEAP_END_SYMBOL_NAME, heapSection, heapSize);
        } else {
            heapSectionBuffer = null;
            heapSectionImpl = null;
            heap.setReadOnlySection(roDataSection.getName(), roConstantsEndOffset);
            heap.setWritableSection(rwDataSection.getName(), rwGlobalsEndOffset);
        }
        // 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(roDataBuffer);
        // - Non-heap global data goes at the beginning of the read-write data section.
        cGlobals.writeData(rwDataBuffer, (offset, symbolName) -> defineDataSymbol(symbolName, rwDataSection, offset + RWDATA_CGLOBALS_PARTITION_OFFSET));
        defineDataSymbol(CGlobalDataInfo.CGLOBALDATA_BASE_SYMBOL_NAME, rwDataSection, RWDATA_CGLOBALS_PARTITION_OFFSET);
        // - Write the heap, either to its own section, or to the ro and rw data sections.
        if (heapSectionBuffer != null) {
            heap.writeHeap(debug, heapSectionBuffer, heapSectionBuffer);
        } else {
            heap.writeHeap(debug, roDataBuffer, rwDataBuffer);
        }
        // Mark the sections with the relocations from the maps.
        // - "null" as the objectMap is because relocations from text are always to constants.
        markRelocationSitesFromMaps(textBuffer, textImpl, null);
        markRelocationSitesFromMaps(roDataBuffer, roDataImpl, heap.objects);
        markRelocationSitesFromMaps(rwDataBuffer, rwDataImpl, heap.objects);
        if (heapSectionBuffer != null) {
            markRelocationSitesFromMaps(heapSectionBuffer, heapSectionImpl, heap.objects);
        }
    }
// [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 : ProgbitsSectionImpl(com.oracle.objectfile.ObjectFile.ProgbitsSectionImpl) BasicProgbitsSectionImpl(com.oracle.objectfile.BasicProgbitsSectionImpl) BasicProgbitsSectionImpl(com.oracle.objectfile.BasicProgbitsSectionImpl) DebugContext(org.graalvm.compiler.debug.DebugContext) CGlobalDataFeature(com.oracle.svm.hosted.c.CGlobalDataFeature)

Example 2 with CGlobalDataFeature

use of com.oracle.svm.hosted.c.CGlobalDataFeature 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

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