for (Stub stub : stubs) {
// add 8 bytes for alignment
codeSize += stub.assembler.codeSize() + 8;
}
PageManager pm = PageManager.getInstance();
long npages = (codeSize + pm.pageSize() - 1) / pm.pageSize();
// Allocate some native memory for it
long code = pm.allocatePages((int) npages, PageManager.PROT_READ | PageManager.PROT_WRITE);
if (code == 0) {
throw new OutOfMemoryError("allocatePages failed for codeSize=" + codeSize);
}
PageHolder page = new PageHolder(pm, code, npages);
// Now relocate/copy all the assembler stubs into the real code area
List<NativeMethod> methods = new ArrayList<NativeMethod>(stubs.size());
long fn = code;
PrintStream dbg = System.err;
System.out.flush(); System.err.flush();
for (Stub stub : stubs) {
Assembler asm = stub.assembler;
// align the start of all functions on a 8 byte boundary
fn = align(fn, 8);
ByteBuffer buf = ByteBuffer.allocate(asm.codeSize()).order(ByteOrder.LITTLE_ENDIAN);
stub.assembler.relocCode(buf, fn);
buf.flip();
MemoryIO.getInstance().putByteArray(fn, buf.array(), buf.arrayOffset(), buf.limit());
if (DEBUG && X86Disassembler.isAvailable()) {
dbg.println(clazz.getName() + "." + stub.name + " " + stub.signature);
X86Disassembler disassembler = X86Disassembler.create();
disassembler.setMode(Platform.getNativePlatform().getCPU() == Platform.CPU.I386
? X86Disassembler.Mode.I386 : X86Disassembler.Mode.X86_64);
disassembler.setSyntax(X86Disassembler.Syntax.INTEL);
disassembler.setInputBuffer(MemoryUtil.newPointer(runtime, fn), asm.offset());
while (disassembler.disassemble()) {
dbg.printf("%8x: %s\n", disassembler.offset(), disassembler.insn());
}
if (buf.remaining() > asm.offset()) {
// libudis86 for some reason cannot understand the code asmjit emits for the trampolines
dbg.printf("%8x: <indirect call trampolines>\n", asm.offset());
}
dbg.println();
}
methods.add(new NativeMethod(fn, stub.name, stub.signature));
fn += asm.codeSize();
}
pm.protectPages(code, (int) npages, PageManager.PROT_READ | PageManager.PROT_EXEC);
NativeMethods.register(clazz, methods);
StaticDataHolder.PAGES.put(clazz, page);
}