/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.build.x86; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.tools.ant.Project; import org.jnode.assembler.Label; import org.jnode.assembler.NativeStream; import org.jnode.assembler.UnresolvedObjectRefException; import org.jnode.assembler.NativeStream.ObjectInfo; import org.jnode.assembler.x86.X86Assembler; import org.jnode.assembler.x86.X86BinaryAssembler; import org.jnode.assembler.x86.X86Constants; import org.jnode.assembler.x86.X86Register; import org.jnode.assembler.x86.X86Register.GPR; import org.jnode.assembler.x86.X86TextAssembler; import org.jnode.boot.Main; import org.jnode.build.AbstractBootImageBuilder; import org.jnode.build.AsmSourceInfo; import org.jnode.build.BuildException; import org.jnode.jnasm.JNAsm; import org.jnode.jnasm.util.X86DualAssemblerFactory; import org.jnode.linker.Elf; import org.jnode.linker.ElfLinker; import org.jnode.plugin.PluginRegistry; import org.jnode.util.NumberUtils; import org.jnode.vm.BaseVmArchitecture; import org.jnode.vm.SoftByteCodes; import org.jnode.vm.VmImpl; import org.jnode.vm.VmSystem; import org.jnode.vm.classmgr.ObjectLayout; import org.jnode.vm.classmgr.VmArray; import org.jnode.vm.classmgr.VmClassType; import org.jnode.vm.classmgr.VmInstanceField; import org.jnode.vm.classmgr.VmIsolatedStatics; import org.jnode.vm.classmgr.VmMethod; import org.jnode.vm.classmgr.VmMethodCode; import org.jnode.vm.classmgr.VmSharedStatics; import org.jnode.vm.classmgr.VmStaticField; import org.jnode.vm.classmgr.VmType; import org.jnode.vm.facade.Vm; import org.jnode.vm.facade.VmUtils; import org.jnode.vm.objects.VmSystemObject; import org.jnode.vm.scheduler.MonitorManager; import org.jnode.vm.scheduler.VmProcessor; import org.jnode.vm.scheduler.VmScheduler; import org.jnode.vm.scheduler.VmThread; import org.jnode.vm.x86.VmX86Architecture; import org.jnode.vm.x86.VmX86Architecture32; import org.jnode.vm.x86.VmX86Architecture64; import org.jnode.vm.x86.VmX86Processor; import org.jnode.vm.x86.VmX86Processor32; import org.jnode.vm.x86.VmX86Processor64; import org.jnode.vm.x86.X86CpuID; import org.jnode.vm.x86.compiler.X86JumpTable; /** * @author epr */ public class BootImageBuilder extends AbstractBootImageBuilder { public static final int LOAD_ADDR = 1024 * 1024; public static final int INITIAL_OBJREFS_CAPACITY = 750000; public static final int INITIAL_SIZE = 64 * 1024 * 1024; private File archClassListFile; private VmX86Processor processor; private String processorId; private VmX86Architecture arch; private VmSharedStatics sharedStatics; private int bits = 32; /** * The offset in our (java) image file to the initial jump to our * main-method. */ public static final int JUMP_MAIN_OFFSET32 = ObjectLayout.objectAlign((ObjectLayout.HEADER_SLOTS + 1) * VmX86Architecture32.SLOT_SIZE); public static final int JUMP_MAIN_OFFSET64 = ObjectLayout.objectAlign((ObjectLayout.HEADER_SLOTS + 1) * VmX86Architecture64.SLOT_SIZE); public final int JUMP_MAIN_OFFSET() { switch (bits) { case 32: return JUMP_MAIN_OFFSET32; case 64: return JUMP_MAIN_OFFSET64; default: throw new IllegalArgumentException("Unknown bits " + bits); } } public static final int INITIALIZE_METHOD_OFFSET = 8; // private final Label vmInvoke = new Label("vm_invoke"); private final Label vmFindThrowableHandler = new Label("vm_findThrowableHandler"); private final Label vmReschedule = new Label("VmProcessor_reschedule"); private final Label sbcSystemException = new Label("SoftByteCodes_systemException"); private final Label vmThreadRunThread = new Label("VmThread_runThread"); private final Label vmCurProcessor = new Label("vmCurProcessor"); /** * Construct a new BootImageBuilder. */ public BootImageBuilder() { System.setProperty("file.encoding", "8859_1"); } /** * Create a platform specific native stream. * * @return The native stream */ protected NativeStream createNativeStream() { X86Constants.Mode mode = ((VmX86Architecture) getArchitecture()).getMode(); X86BinaryAssembler x86BinaryAssembler = new X86BinaryAssembler(getCPUID(), mode, LOAD_ADDR, INITIAL_OBJREFS_CAPACITY, INITIAL_SIZE, INITIAL_SIZE); if (!debug) { return x86BinaryAssembler; } else { //in debug mode write bootimage also in text format try { x86BinaryAssembler.setByteValueEnabled(true); x86BinaryAssembler.setRelJumpEnabled(false); X86TextAssembler x86TextAssembler = new X86TextAssembler(new BufferedWriter( new FileWriter(getTextFile())), getCPUID(), mode); return X86DualAssemblerFactory.create(x86TextAssembler, x86BinaryAssembler); } catch (IOException x) { throw new RuntimeException(x); } } } /** * Create the default processor for this architecture. * * @return The processor * @throws BuildException */ protected VmProcessor createProcessor(VmImpl vm, VmSharedStatics statics, VmIsolatedStatics isolatedStatics) throws BuildException { this.sharedStatics = statics; VmScheduler scheduler = new VmScheduler(getArchitecture()); vm.setScheduler(scheduler); if (processor == null) { switch (bits) { case 32: processor = new VmX86Processor32(0, (VmX86Architecture32) getArchitecture(), statics, isolatedStatics, scheduler, getCPUID()); break; case 64: processor = new VmX86Processor64(0, (VmX86Architecture64) getArchitecture(), statics, isolatedStatics, scheduler, getCPUID()); break; default: throw new BuildException("Unknown bits " + bits); } } return processor; } /** * Gets the target architecture. * * @return The target architecture * @throws BuildException */ protected final BaseVmArchitecture getArchitecture() throws BuildException { if (arch == null) { switch (bits) { case 32: arch = new VmX86Architecture32(getJnodeCompiler()); break; case 64: arch = new VmX86Architecture64(getJnodeCompiler()); break; default: throw new BuildException("Unknown bits " + bits); } } return arch; } /** * Copy the kernel native code into the native stream. * * @param os * @throws BuildException */ protected void copyKernel(NativeStream os) throws BuildException { try { Elf elf = Elf.newFromFile(getKernelFile().getCanonicalPath()); // elf.print(); new ElfLinker((X86Assembler) os).loadElfObject(elf); } catch (IOException ex) { throw new BuildException(ex); } // Link the jump table entries for (int i = 0; i < X86JumpTable.TABLE_LENGTH; i++) { final Label lbl = new Label(X86JumpTable.TABLE_ENTRY_LABELS[i]); final int idx = (arch.getMode().is32()) ? i : i * 2; sharedStatics.setAddress(idx, lbl); } } /** * Align the stream on a page boundary. * * @param os * @throws BuildException */ protected void pageAlign(NativeStream os) throws BuildException { ((X86Assembler) os).align(4096); } /** * Emit code to bootstrap the java image. * * @param os * @param clInitCaller * @param pluginRegistry * @throws BuildException */ protected void initImageHeader(NativeStream os, Label clInitCaller, Vm vm, PluginRegistry pluginRegistry) throws BuildException { try { int startLength = os.getLength(); VmType<?> vmCodeClass = loadClass(VmMethodCode.class); final NativeStream.ObjectInfo initObject = os.startObject(vmCodeClass); final int offset = os.getLength() - startLength; if (offset != JUMP_MAIN_OFFSET()) { throw new BuildException("JUMP_MAIN_OFFSET is incorrect [" + offset + " instead of " + JUMP_MAIN_OFFSET() + "] (set to Object headersize)"); } final X86Assembler os86 = (X86Assembler) os; final Label introCode = new Label("_$$introCode"); os86.setObjectRef(new Label("_$$jmp_introCode")); os86.writeJMP(introCode); initObject.markEnd(); // The loading of class can emit object in between, so first load // all required classes here. loadClass(Main.class); loadClass(MonitorManager.class); loadClass(SoftByteCodes.class); loadClass(Vm.class); loadClass(VmMethod.class); loadClass(VmProcessor.class); loadClass(VmThread.class); loadClass(VmType.class); loadClass(VmSystem.class); loadClass(VmSystemObject.class); final NativeStream.ObjectInfo initCodeObject = os.startObject(vmCodeClass); os86.setObjectRef(introCode); initMain(os86, pluginRegistry); initVm(os86, vm); // initHeapManager(os86, vm); initVmThread(os86); os.setObjectRef(new Label("_$$Initial_call_to_clInitCaller")); os86.writeCALL(clInitCaller); initCallMain(os86); initCodeObject.markEnd(); } catch (ClassNotFoundException ex) { throw new BuildException(ex); } } /** * Link all undefined symbols from the kernel native code. * * @param os * @throws ClassNotFoundException * @throws UnresolvedObjectRefException */ protected void linkNativeSymbols(NativeStream os) throws ClassNotFoundException, UnresolvedObjectRefException { NativeStream.ObjectRef refJava; /* Link VmMethod_compile */ VmType<?> vmMethodClass = loadClass(VmMethod.class); refJava = os.getObjectRef(vmMethodClass.getMethod("recompile", "()V")); os.getObjectRef(new Label("VmMethod_recompile")).link(refJava); final VmType<?> vmThreadClass = loadClass(VmThread.class); /* Link VmThread_systemException */ refJava = os.getObjectRef(vmThreadClass.getMethod("systemException", "(II)Ljava/lang/Throwable;")); os.getObjectRef(sbcSystemException).link(refJava); /* Link VmThread_runThread */ refJava = os.getObjectRef(vmThreadClass.getMethod("runThread", "(Lorg/jnode/vm/scheduler/VmThread;)V")); os.getObjectRef(vmThreadRunThread).link(refJava); /* Link VmProcessor_reschedule */ VmType<?> vmProcClass = loadClass(VmProcessor.class); refJava = os.getObjectRef(vmProcClass.getMethod("reschedule", "()V")); os.getObjectRef(vmReschedule).link(refJava); /* Link vmCurProcessor */ refJava = os.getObjectRef(processor); os.getObjectRef(vmCurProcessor).link(refJava); /* Set statics index of VmSystem_currentTimeMillis */ final VmType<?> vmSystemClass = loadClass(VmSystem.class); final int staticsIdx = ((VmStaticField) vmSystemClass.getField("currentTimeMillis")).getSharedStaticsIndex(); final X86Assembler os86 = (X86Assembler) os; os86.set32(os.getObjectRef(new Label("currentTimeMillisStaticsIdx")).getOffset(), staticsIdx); /* Link vm_findThrowableHandler */ refJava = os.getObjectRef(vmSystemClass.getMethod("findThrowableHandler", "(Ljava/lang/Throwable;Lorg/vmmagic/unboxed/Address;Lorg/vmmagic/unboxed/Address;)" + "Lorg/vmmagic/unboxed/Address;")); os.getObjectRef(vmFindThrowableHandler).link(refJava); // Link Luser_esp refJava = os.getObjectRef(initialStackPtr); os.getObjectRef(new Label("Luser_esp")).link(refJava); // Link freeMemoryStart refJava = os.getObjectRef(imageEnd); os.getObjectRef(new Label("freeMemoryStart")).link(refJava); // Link bootHeapStart refJava = os.getObjectRef(bootHeapStart); os.getObjectRef(new Label("bootHeapStart")).link(refJava); // Link bootHeapEnd refJava = os.getObjectRef(bootHeapEnd); os.getObjectRef(new Label("bootHeapEnd")).link(refJava); // Link VmX86Processor_applicationProcessorMain final VmType<?> x86ProcessorClass = loadClass(VmX86Processor.class); refJava = os.getObjectRef(x86ProcessorClass.getMethod("applicationProcessorMain", "()V")); os.getObjectRef(new Label("VmX86Processor_applicationProcessorMain")).link(refJava); // Link VmX86Processor_broadcastTimeSliceInterrupt refJava = os.getObjectRef(x86ProcessorClass.getMethod("broadcastTimeSliceInterrupt", "()V")); os.getObjectRef(new Label("VmX86Processor_broadcastTimeSliceInterrupt")).link(refJava); } /** * Emit code to call Main.vmMain. * * @param os * @throws BuildException * @throws ClassNotFoundException */ protected void initCallMain(X86Assembler os) throws BuildException, ClassNotFoundException { final VmType<?> vmMethodClass = loadClass(VmMethod.class); final VmType<?> vmMainClass = loadClass(Main.class); final VmMethod mainMethod = vmMainClass.getMethod( Main.MAIN_METHOD_NAME, Main.MAIN_METHOD_SIGNATURE); final VmInstanceField nativeCodeField = (VmInstanceField) vmMethodClass.getField("nativeCode"); final GPR aax = os.isCode32() ? (GPR) X86Register.EAX : X86Register.RAX; os.writeMOV_Const(aax, mainMethod); os.writeCALL(aax, nativeCodeField.getOffset()); os.writeRET(); // RET instruction } /** * Emit code to initialize VmThread. * * @param os * @throws BuildException * @throws ClassNotFoundException */ protected void initVmThread(X86Assembler os) throws BuildException, ClassNotFoundException { final VmType<?> vmThreadClass = loadClass(VmThread.class); final VmInstanceField threadStackField = (VmInstanceField) vmThreadClass.getField("stack"); final VmInstanceField threadStackEndField = (VmInstanceField) vmThreadClass.getField("stackEnd"); final VmType<?> vmProcessorClass = loadClass(VmProcessor.class); final VmInstanceField procStackEndField = (VmInstanceField) vmProcessorClass.getField("stackEnd"); final VmThread initialThread = processor.getCurrentThread(); final GPR abx = os.isCode32() ? X86Register.EBX : X86Register.RBX; final GPR adx = os.isCode32() ? X86Register.EDX : X86Register.RDX; final int slotSize = arch.getReferenceSize(); os.setObjectRef(new Label("_$$Setup_initial_thread")); os.writeMOV_Const(abx, initialThread); /** Initialize initialStack.stack to Luser_stack */ os.writeMOV_Const(adx, initialStack); os.writeMOV(adx.getSize(), abx, threadStackField.getOffset(), adx); // Calculate and set stackEnd os.writeLEA(adx, adx, VmThread.STACK_OVERFLOW_LIMIT_SLOTS * slotSize); os.writeMOV(adx.getSize(), abx, threadStackEndField.getOffset(), adx); // Set stackend in current processor os.writeMOV_Const(abx, processor); os.writeMOV(adx.getSize(), abx, procStackEndField.getOffset(), adx); } /** * Create the initial stack space. * * @param os * @param stackLabel Label to the start of the stack space (low address) * @param stackPtrLabel Label to the initial stack pointer (on x86 high address) * @throws BuildException * @throws ClassNotFoundException * @throws UnresolvedObjectRefException */ protected void createInitialStack(NativeStream os, Label stackLabel, Label stackPtrLabel) throws BuildException, ClassNotFoundException, UnresolvedObjectRefException { final ObjectInfo objectInfo = os.startObject(loadClass(VmSystemObject.class)); final int stackOffset = os.setObjectRef(stackLabel).getOffset(); final int stackAddr = stackOffset + (int) os.getBaseAddr(); final int slotSize = arch.getReferenceSize(); // Low stack address os.writeWord(stackAddr + VmThread.STACK_OVERFLOW_LIMIT_SLOTS * slotSize); // High stack address os.writeWord(stackAddr + VmThread.DEFAULT_STACK_SLOTS * slotSize); // The actual stack space for (int i = 2; i < VmThread.DEFAULT_STACK_SLOTS; i++) { os.writeWord(0); } os.setObjectRef(stackPtrLabel); objectInfo.markEnd(); } /** * Emit code to initialize Vm. * * @param os * @throws BuildException * @throws ClassNotFoundException */ protected void initVm(X86Assembler os, Vm vm) throws BuildException, ClassNotFoundException { os.setObjectRef(new Label("_$$Initialize_Vm")); VmType<?> vmClass = loadClass(VmUtils.class); VmStaticField vmField = (VmStaticField) vmClass.getField("VM_INSTANCE"); final GPR abx = os.isCode32() ? X86Register.EBX : X86Register.RBX; final GPR adi = os.isCode32() ? X86Register.EDI : X86Register.RDI; final int slotSize = os.isCode32() ? 4 : 8; // Setup STATICS register (EDI/RDI) os.writeMOV_Const(adi, sharedStatics.getTable()); /* Set Vm.instance */ os.writeMOV_Const(abx, vm); final int vmOffset = (VmArray.DATA_OFFSET * slotSize) + (vmField.getSharedStaticsIndex() << 2); log("vmOffset " + NumberUtils.hex(vmOffset), Project.MSG_VERBOSE); os.writeMOV(abx.getSize(), adi, vmOffset, abx); } /** * Emit code to initialize org.jnode.boot.Main. * * @param os * @param registry * @throws BuildException * @throws ClassNotFoundException */ protected void initMain(X86Assembler os, PluginRegistry registry) throws BuildException, ClassNotFoundException { os.setObjectRef(new Label("_$$Initialize_Main")); final VmType<?> mainClass = loadClass(Main.class); final VmStaticField registryField = (VmStaticField) mainClass.getField(Main.REGISTRY_FIELD_NAME); final GPR abx = os.isCode32() ? X86Register.EBX : X86Register.RBX; final GPR adi = os.isCode32() ? X86Register.EDI : X86Register.RDI; final int slotSize = os.isCode32() ? 4 : 8; // Setup STATICS register (EDI/RDI) os.writeMOV_Const(adi, sharedStatics.getTable()); /* Set Main.pluginRegistry */ os.writeMOV_Const(abx, registry); final int rfOffset = (VmArray.DATA_OFFSET * slotSize) + (registryField.getSharedStaticsIndex() << 2); log("rfOffset " + NumberUtils.hex(rfOffset), Project.MSG_VERBOSE); os.writeMOV(abx.getSize(), adi, rfOffset, abx); } protected void emitStaticInitializerCalls(NativeStream nativeOs, VmType<?>[] bootClasses, Object clInitCaller) throws ClassNotFoundException { final X86Assembler os = (X86Assembler) nativeOs; NativeStream.ObjectInfo initCallerObject = os.startObject(loadClass(VmMethodCode.class)); os.setObjectRef(clInitCaller); // Call VmClass.loadFromBootClassArray final VmType<?> vmClassClass = loadClass(VmType.class); final VmMethod lfbcaMethod = vmClassClass.getMethod("loadFromBootClassArray", "([Lorg/jnode/vm/classmgr/VmType;)V"); final VmType<?> vmMethodClass = loadClass(VmMethod.class); final VmInstanceField nativeCodeField = (VmInstanceField) vmMethodClass.getField("nativeCode"); final GPR aax = os.isCode32() ? X86Register.EAX : X86Register.RAX; final GPR abx = os.isCode32() ? X86Register.EBX : X86Register.RBX; os.writeMOV_Const(aax, bootClasses); os.writePUSH(aax); os.writeMOV_Const(aax, lfbcaMethod); os.writeMOV(abx.getSize(), abx, aax, nativeCodeField.getOffset()); os.writeCALL(abx); // Now call all static initializers for (int i = 0; (i < bootClasses.length); i++) { VmType<?> vmClass = bootClasses[i]; if ((vmClass instanceof VmClassType) && (((VmClassType<?>) vmClass).getInstanceCount() > 0)) { VmMethod clInit = vmClass.getMethod("<clinit>", "()V"); if (clInit != null) { // os.setObjectRef(clInitCaller + "$$" + vmClass.getName()); log("Missing static initializer in class " + vmClass.getName(), Project.MSG_WARN); } } } os.writeRET(); // RET os.align(4096); initCallerObject.markEnd(); } /** * Save the native stream to destFile. * * @param os * @throws BuildException */ protected void storeImage(NativeStream os) throws BuildException { try { log("Creating image"); FileOutputStream fos = new FileOutputStream(getDestFile()); fos.write(os.getBytes(), 0, os.getLength()); fos.close(); /* * log.info("Creating ELF image"); final long start = * System.currentTimeMillis(); final Elf elf = * ((X86Stream)os).toElf(); final long end = * System.currentTimeMillis(); log.info("... took " + (end-start) + * "ms"); elf.store(getDestFile().getAbsolutePath() + ".elf"); */ } catch (IOException ex) { throw new BuildException(ex); } } /** * Patch the Multiboot header. */ private static final int MB_MAGIC = 0x1BADB002; private static final int MB_LOAD_ADDR = 4 * 4; private static final int MB_LOAD_END_ADDR = 5 * 4; private static final int MB_BSS_END_ADDR = 6 * 4; @SuppressWarnings("unused") private static final int MODE_TYPE = 8 * 4; @SuppressWarnings("unused") private static final int WIDTH = 9 * 4; @SuppressWarnings("unused") private static final int HEIGHT = 10 * 4; @SuppressWarnings("unused") private static final int DEPTH = 11 * 4; /** * Patch any fields in the header, just before the image is written to disk. * * @param nativeOs * @throws BuildException */ protected void patchHeader(NativeStream nativeOs) throws BuildException { final X86Assembler os = (X86Assembler) nativeOs; int mb_hdr = -1; for (int i = 0; i < 1024; i += 4) { if (os.get32(i) == MB_MAGIC) { mb_hdr = i; break; } } if (mb_hdr < 0) { throw new BuildException("Cannot find Multiboot header"); } int loadAddr = os.get32(mb_hdr + MB_LOAD_ADDR); if (loadAddr != os.getBaseAddr()) { throw new BuildException("Non-matching load address, found 0x" + Integer.toHexString(loadAddr) + ", expected 0x" + Long.toHexString(os.getBaseAddr())); } os.set32(mb_hdr + MB_LOAD_END_ADDR, (int) os.getBaseAddr() + os.getLength()); os.set32(mb_hdr + MB_BSS_END_ADDR, (int) os.getBaseAddr() + os.getLength()); } /** * @return Returns the processorId. */ public final String getCpu() { return this.processorId; } /** * @param processorId The processorId to set. */ public final void setCpu(String processorId) { this.processorId = processorId; } protected X86CpuID getCPUID() { return X86CpuID.createID(processorId); } protected void logStatistics(NativeStream os) { final X86Assembler os86 = (X86Assembler) os; final int count = os86.getObjectRefsCount(); if (count > INITIAL_OBJREFS_CAPACITY) { log("Increase BootImageBuilder.INITIAL_OBJREFS_CAPACITY to " + count + " for faster build.", Project.MSG_WARN); } final int size = os86.getLength(); if (size > INITIAL_SIZE) { log("Increase BootImageBuilder.INITIAL_SIZE to " + size + " for faster build.", Project.MSG_WARN); } } /** * Include x86 class files. * * @see org.jnode.build.AbstractBootImageBuilder#setupCompileHighOptLevelPackages() */ protected void setupCompileHighOptLevelPackages() { super.setupCompileHighOptLevelPackages(); addCompileHighOptLevel(loadClassList(archClassListFile)); } /** * @see org.jnode.build.AbstractBootImageBuilder#cleanup() */ protected void cleanup() { super.cleanup(); this.processor = null; this.sharedStatics = null; } /** * Gets the number of bits this builder targets. * * @return The number of bits (32, 64) */ public final int getBits() { return this.bits; } /** * Sets the number of bits this builder targets. * * @param bits */ public final void setBits(int bits) { if ((bits != 32) && (bits != 64)) { throw new IllegalArgumentException("Unknown bits value " + bits); } this.bits = bits; } /** * Initialize the statics table. * * @see org.jnode.build.AbstractBootImageBuilder#initializeStatics(org.jnode.vm.classmgr.VmSharedStatics) */ protected void initializeStatics(VmSharedStatics statics) throws BuildException { for (int i = 0; i < X86JumpTable.TABLE_LENGTH; i++) { final int idx = statics.allocAddressField(); if (getArchitecture().getReferenceSize() == 4) { if (i != idx) { throw new BuildException("JumpTable entry " + i + " must be at index " + i + " not " + idx); } } else { if ((i * 2) != idx) { throw new BuildException("JumpTable entry " + i + " must be at index " + (i * 2) + " not " + idx); } } } } protected void compileKernel(NativeStream os, AsmSourceInfo sourceInfo) throws BuildException { try { final String version = getVersion(); final int i_bist = getBits(); final String bits = "BITS" + i_bist; final Map<String, String> symbols = new HashMap<String, String>(); symbols.put(bits, ""); symbols.put("JNODE_VERSION", "'" + version + "'"); log("Compiling native kernel with JNAsm, Version " + version + ", " + i_bist + " bits"); JNAsm.assembler(os, sourceInfo, symbols); log("Compiling native kernel with JNAsm, Version " + version + ", " + i_bist + " bits done"); // Link the jump table entries for (int i = 0; i < X86JumpTable.TABLE_LENGTH; i++) { final Label lbl = new Label(X86JumpTable.TABLE_ENTRY_LABELS[i]); final int idx = (arch.getMode().is32()) ? i : i * 2; sharedStatics.setAddress(idx, lbl); } } catch (Exception e) { throw new BuildException(e); } } /** * Gets the architecture specific class list file. * * @return The archClassListFile to set */ public File getArchClassListFile() { return archClassListFile; } /** * Sets the architecture specific class list file. * * @param archClassListFile The archClassListFile to set */ public void setArchClassListFile(File archClassListFile) { this.archClassListFile = archClassListFile; } }