use of com.oracle.objectfile.BasicProgbitsSectionImpl 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
}
use of com.oracle.objectfile.BasicProgbitsSectionImpl in project graal by oracle.
the class MachOObjectFile method newUserDefinedSection.
@Override
public MachOUserDefinedSection newUserDefinedSection(Segment segment, String name, int alignment, ElementImpl impl) {
assert segment != null;
ElementImpl ourImpl;
if (impl == null) {
ourImpl = new BasicProgbitsSectionImpl((Section) null);
} else {
ourImpl = impl;
}
MachOUserDefinedSection userDefined = new MachOUserDefinedSection(this, name, alignment, (Segment64Command) segment, SectionType.REGULAR, ourImpl);
ourImpl.setElement(userDefined);
return userDefined;
}
use of com.oracle.objectfile.BasicProgbitsSectionImpl 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
}
Aggregations