This commit is contained in:
Vladimir Kozlov 2017-08-22 19:24:42 +00:00
commit 59984483c7
100 changed files with 2333 additions and 2428 deletions

View File

@ -58,7 +58,7 @@ import org.graalvm.compiler.options.OptionValues;
* <p>
* Methods to record and access code section contents, symbols and relocations are provided.
*/
public class BinaryContainer implements SymbolTable {
public final class BinaryContainer implements SymbolTable {
private final OptionValues graalOptions;
private final int codeSegmentSize;
@ -70,20 +70,20 @@ public class BinaryContainer implements SymbolTable {
*/
private final CodeContainer codeContainer;
/**
* Container holding external hotspot linkage bits (PLT entries).
*/
private final CodeContainer extLinkageContainer;
/**
* Container holding global offset data for hotspot linkage.
*/
private final ByteContainer extLinkageGOTContainer;
/**
* Patched by HotSpot, contains metaspace pointers.
* Patched by HotSpot, contains Klass pointers.
*/
private final ByteContainer metaspaceGotContainer;
private final ByteContainer klassesGotContainer;
/**
* Patched by HotSpot, contains MethodCounters pointers.
*/
private final ByteContainer countersGotContainer;
/**
* Patched lazily by hotspot, contains klass/method pointers.
@ -268,33 +268,41 @@ public class BinaryContainer implements SymbolTable {
this.graalOptions = graalOptions;
this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
if (codeSegmentSize < 1 || codeSegmentSize > 1024) {
throw new InternalError("codeSegmentSize is not in range [1, 1024] bytes: (" + codeSegmentSize + "), update JPECoffRelocObject");
}
if ((codeSegmentSize & (codeSegmentSize - 1)) != 0) {
throw new InternalError("codeSegmentSize is not power of 2: (" + codeSegmentSize + "), update JPECoffRelocObject");
}
this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
// Section unique name is limited to 8 characters due to limitation on Windows.
// Name could be longer but only first 8 characters are stored on Windows.
// read only, code
codeContainer = new CodeContainer(".text", this);
extLinkageContainer = new CodeContainer(".hs.plt.linkage", this);
// read only, info
headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
configContainer = new ReadOnlyDataContainer(".config", this);
metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this);
methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this);
methodsOffsetsContainer = new ReadOnlyDataContainer(".meth.offsets", this);
klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this);
klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this);
headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this);
codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this);
constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this);
// needs relocation patching at load time by the loader
methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this);
// writable sections
metaspaceGotContainer = new ByteContainer(".meta.got", this);
metadataGotContainer = new ByteContainer(".metadata.got", this);
methodStateContainer = new ByteContainer(".meth.state", this);
oopGotContainer = new ByteContainer(".oop.got", this);
extLinkageGOTContainer = new ByteContainer(".hs.got.linkage", this);
klassesGotContainer = new ByteContainer(".kls.got", this);
countersGotContainer = new ByteContainer(".cnt.got", this);
metadataGotContainer = new ByteContainer(".meta.got", this);
methodStateContainer = new ByteContainer(".meth.state", this);
extLinkageGOTContainer = new ByteContainer(".got.linkage", this);
addGlobalSymbols();
@ -368,51 +376,51 @@ public class BinaryContainer implements SymbolTable {
* in the named GOT cell.
*/
public String getCardTableAddressSymbolName() {
public static String getCardTableAddressSymbolName() {
return "_aot_card_table_address";
}
public String getHeapTopAddressSymbolName() {
public static String getHeapTopAddressSymbolName() {
return "_aot_heap_top_address";
}
public String getHeapEndAddressSymbolName() {
public static String getHeapEndAddressSymbolName() {
return "_aot_heap_end_address";
}
public String getCrcTableAddressSymbolName() {
public static String getCrcTableAddressSymbolName() {
return "_aot_stub_routines_crc_table_adr";
}
public String getPollingPageSymbolName() {
public static String getPollingPageSymbolName() {
return "_aot_polling_page";
}
public String getResolveStaticEntrySymbolName() {
public static String getResolveStaticEntrySymbolName() {
return "_resolve_static_entry";
}
public String getResolveVirtualEntrySymbolName() {
public static String getResolveVirtualEntrySymbolName() {
return "_resolve_virtual_entry";
}
public String getResolveOptVirtualEntrySymbolName() {
public static String getResolveOptVirtualEntrySymbolName() {
return "_resolve_opt_virtual_entry";
}
public String getNarrowKlassBaseAddressSymbolName() {
public static String getNarrowKlassBaseAddressSymbolName() {
return "_aot_narrow_klass_base_address";
}
public String getNarrowOopBaseAddressSymbolName() {
public static String getNarrowOopBaseAddressSymbolName() {
return "_aot_narrow_oop_base_address";
}
public String getLogOfHeapRegionGrainBytesSymbolName() {
public static String getLogOfHeapRegionGrainBytesSymbolName() {
return "_aot_log_of_heap_region_grain_bytes";
}
public String getInlineContiguousAllocationSupportedSymbolName() {
public static String getInlineContiguousAllocationSupportedSymbolName() {
return "_aot_inline_contiguous_allocation_supported";
}
@ -430,7 +438,7 @@ public class BinaryContainer implements SymbolTable {
* @param functionName function name
* @return AOT symbol for the given function name, or null if there is no mapping.
*/
public String getAOTSymbolForVMFunctionName(String functionName) {
public static String getAOTSymbolForVMFunctionName(String functionName) {
return functionNamesToAOTSymbols.get(functionName);
}
@ -441,7 +449,8 @@ public class BinaryContainer implements SymbolTable {
createContainerSymbol(methodsOffsetsContainer);
createContainerSymbol(klassesOffsetsContainer);
createContainerSymbol(klassesDependenciesContainer);
createContainerSymbol(metaspaceGotContainer);
createContainerSymbol(klassesGotContainer);
createContainerSymbol(countersGotContainer);
createContainerSymbol(metadataGotContainer);
createContainerSymbol(methodStateContainer);
createContainerSymbol(oopGotContainer);
@ -469,12 +478,13 @@ public class BinaryContainer implements SymbolTable {
}
/**
* Creates a global symbol of the form {@code "JVM" + container name}.
* Creates a global symbol of the form {@code "A" + container name}.
* Note, linker on Windows does not allow names which start with '.'
*
* @param container container to create a symbol for
*/
private static void createContainerSymbol(ByteContainer container) {
container.createSymbol(0, Kind.OBJECT, Binding.GLOBAL, 0, "JVM" + container.getContainerName());
container.createSymbol(0, Kind.OBJECT, Binding.GLOBAL, 0, "A" + container.getContainerName());
}
/**
@ -499,12 +509,12 @@ public class BinaryContainer implements SymbolTable {
*
* @throws IOException in case of file creation failure
*/
public void createBinary(String outputFileName, String aotVersion) throws IOException {
public void createBinary(String outputFileName) throws IOException {
String osName = System.getProperty("os.name");
switch (osName) {
case "Linux":
case "SunOS":
JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName, aotVersion);
JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName);
elfobj.createELFRelocObject(relocationTable, symbolTable.values());
break;
case "Mac OS X":
@ -513,7 +523,7 @@ public class BinaryContainer implements SymbolTable {
break;
default:
if (osName.startsWith("Windows")) {
JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion);
JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName);
pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values());
break;
} else
@ -626,12 +636,6 @@ public class BinaryContainer implements SymbolTable {
return startOffset;
}
public int appendMetaspaceGotBytes(byte[] bytes, int offset, int size) {
int startOffset = metaspaceGotContainer.getByteStreamSize();
appendBytes(metaspaceGotContainer, bytes, offset, size);
return startOffset;
}
public void addMetadataGotEntry(int offset) {
metadataGotContainer.appendLong(offset);
}
@ -681,8 +685,7 @@ public class BinaryContainer implements SymbolTable {
}
/**
* Add oop symbol by as follows. Extend the oop.got section with another slot for the VM to
* patch.
* Add oop symbol by as follows. Extend the oop.got section with another slot for the VM to patch.
*
* @param oopName name of the oop symbol
*/
@ -708,13 +711,13 @@ public class BinaryContainer implements SymbolTable {
return relocationSymbol.getOffset();
}
public int addMetaspaceSymbol(String metaspaceName) {
public int addCountersSymbol(String metaspaceName) {
String gotName = "got." + metaspaceName;
Symbol relocationSymbol = getGotSymbol(gotName);
int metaspaceOffset = -1;
if (relocationSymbol == null) {
// Add slots when asked in the .metaspace.got section:
metaspaceGotContainer.createGotSymbol(gotName);
countersGotContainer.createGotSymbol(gotName);
}
return metaspaceOffset;
}
@ -725,29 +728,30 @@ public class BinaryContainer implements SymbolTable {
}
/**
* Add metaspace symbol by as follows. - Adding the symbol name to the metaspace.names section -
* Add the offset of the name in metaspace.names to metaspace.offsets - Extend the metaspace.got
* section with another slot for the VM to patch
* Add klass symbol by as follows.
* - Adding the symbol name to the metaspace.names section
* - Add the offset of the name in metaspace.names to metaspace.offsets
* - Extend the klasses.got section with another slot for the VM to patch
*
* @param metaspaceName name of the metaspace symbol
* @return the got offset in the metaspace.got of the metaspace symbol
* @param klassName name of the metaspace symbol
* @return the got offset in the klasses.got of the metaspace symbol
*/
public int addTwoSlotMetaspaceSymbol(String metaspaceName) {
String gotName = "got." + metaspaceName;
public int addTwoSlotKlassSymbol(String klassName) {
String gotName = "got." + klassName;
Symbol previous = getGotSymbol(gotName);
assert previous == null : "should be called only once for: " + metaspaceName;
assert previous == null : "should be called only once for: " + klassName;
// Add slots when asked in the .metaspace.got section:
// First slot
String gotInitName = "got.init." + metaspaceName;
GotSymbol slot1Symbol = metaspaceGotContainer.createGotSymbol(gotInitName);
GotSymbol slot2Symbol = metaspaceGotContainer.createGotSymbol(gotName);
String gotInitName = "got.init." + klassName;
GotSymbol slot1Symbol = klassesGotContainer.createGotSymbol(gotInitName);
GotSymbol slot2Symbol = klassesGotContainer.createGotSymbol(gotName);
slot1Symbol.getIndex(); // check alignment and ignore result
// Get the index (offset/8) to the got in the .metaspace.got section
return slot2Symbol.getIndex();
}
public int addMethodsCount(int count, ReadOnlyDataContainer container) {
public static int addMethodsCount(int count, ReadOnlyDataContainer container) {
return appendInt(count, container);
}
@ -772,7 +776,7 @@ public class BinaryContainer implements SymbolTable {
return constantDataOffset;
}
public int alignUp(ByteContainer container, int alignment) {
public static int alignUp(ByteContainer container, int alignment) {
if (Integer.bitCount(alignment) != 1) {
throw new IllegalArgumentException("Must be a power of 2");
}
@ -814,15 +818,11 @@ public class BinaryContainer implements SymbolTable {
appendBytes(codeSegmentsContainer, segments, 0, segmentsCount);
}
public CodeContainer getExtLinkageContainer() {
return extLinkageContainer;
}
public ByteContainer getExtLinkageGOTContainer() {
return extLinkageGOTContainer;
}
public ByteContainer getMethodMetadataContainer() {
public ReadOnlyDataContainer getMethodMetadataContainer() {
return methodMetadataContainer;
}
@ -854,8 +854,12 @@ public class BinaryContainer implements SymbolTable {
return constantDataContainer;
}
public ByteContainer getMetaspaceGotContainer() {
return metaspaceGotContainer;
public ByteContainer getKlassesGotContainer() {
return klassesGotContainer;
}
public ByteContainer getCountersGotContainer() {
return countersGotContainer;
}
public ByteContainer getMetadataGotContainer() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@ package jdk.tools.jaotc.binformat;
/**
* A container that holds information about code section. This is simply a ByteContainer.
*/
public class CodeContainer extends ByteContainer {
public final class CodeContainer extends ByteContainer {
public CodeContainer(String containerName, SymbolTable symbolTable) {
super(containerName, symbolTable);

View File

@ -23,7 +23,7 @@
package jdk.tools.jaotc.binformat;
public interface Container {
interface Container {
String getContainerName();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
package jdk.tools.jaotc.binformat;
public class GotSymbol extends Symbol {
public final class GotSymbol extends Symbol {
private static final int GOT_SIZE = 8;
@ -33,18 +33,27 @@ public class GotSymbol extends Symbol {
return offset / GOT_SIZE;
}
/**
* Create GOT symbol info.
*
* @param type type of the symbol (UNDEFINED, FUNC, etc)
* @param binding binding of the symbol (LOCAL, GLOBAL, ...)
* @param container section in which this symbol is "defined"
* @param name name of the symbol
*/
public GotSymbol(Kind type, Binding binding, ByteContainer container, String name) {
this(container.getByteStreamSize(), type, binding, container, name);
container.appendBytes(new byte[GOT_SIZE], 0, GOT_SIZE);
}
/**
* Create symbol info.
* Create GOT symbol info.
*
* @param offset section offset for the defined symbol
* @param type type of the symbol (UNDEFINED, FUNC, etc)
* @param binding binding of the symbol (LOCAL, GLOBAL, ...)
* @param sec section in which this symbol is "defined"
* @param name name of the symbol
*/
public GotSymbol(int offset, Kind type, Binding binding, ByteContainer sec, String name) {
super(offset, type, binding, sec, GOT_SIZE, name);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,14 +27,15 @@ import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class HeaderContainer {
public final class HeaderContainer {
private static final int CURRENT_VERSION = 1;
private final ReadOnlyDataContainer container;
// int _version;
// int _class_count;
// int _method_count;
// int _metaspace_got_size;
// int _klasses_got_size;
// int _metadata_got_size;
// int _oop_got_size;
// int _jvm_version_offset;
@ -76,7 +77,7 @@ public class HeaderContainer {
this.container.putIntAt(2 * 4, count);
}
public void setMetaspaceGotSize(int size) {
public void setKlassesGotSize(int size) {
this.container.putIntAt(3 * 4, size);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,9 +23,9 @@
package jdk.tools.jaotc.binformat;
public class ReadOnlyDataContainer extends ByteContainer {
public final class ReadOnlyDataContainer extends ByteContainer {
public ReadOnlyDataContainer(String containerName, SymbolTable symbolTable) {
ReadOnlyDataContainer(String containerName, SymbolTable symbolTable) {
super(containerName, symbolTable);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,25 +23,17 @@
package jdk.tools.jaotc.binformat;
public class Relocation {
public final class Relocation {
public enum RelocType {
UNDEFINED,
JAVA_CALL_INDIRECT,
JAVA_CALL_DIRECT,
FOREIGN_CALL_INDIRECT,
FOREIGN_CALL_INDIRECT_GOT, // Call to address in GOT cell
FOREIGN_CALL_DIRECT,
FOREIGN_CALL_DIRECT_FAR,
STUB_CALL_DIRECT,
STUB_CALL_INDIRECT,
EXTERNAL_DATA_REFERENCE_FAR,
METASPACE_GOT_REFERENCE,
EXTERNAL_GOT_TO_PLT,
EXTERNAL_PLT_TO_GOT,
STATIC_STUB_TO_STATIC_METHOD,
STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT,
LOADTIME_ADDRESS
EXTERNAL_PLT_TO_GOT
}
private final RelocType type;

View File

@ -39,7 +39,6 @@ public class Symbol {
UNDEFINED,
NATIVE_FUNCTION,
JAVA_FUNCTION,
STATIC_STUB_CALL, // static call stub inside the text section
OBJECT,
NOTYPE
}

View File

@ -25,17 +25,16 @@ package jdk.tools.jaotc.binformat.elf;
/**
*
* Support for the creation of Elf Object files.
* Current support is limited to 64 bit x86_64.
* Support for the creation of Elf Object files. Current support is limited to 64 bit x86_64.
*
*/
public class Elf {
final class Elf {
//@formatter:off
/**
* Elf64_Ehdr structure defines
*/
public enum Elf64_Ehdr {
enum Elf64_Ehdr {
e_ident( 0,16),
e_type(16, 2),
e_machine(18, 2),
@ -51,15 +50,15 @@ public class Elf {
e_shnum(60, 2),
e_shstrndx(62, 2);
public final int off;
public final int sz;
final int off;
final int sz;
Elf64_Ehdr(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 64;
static int totalsize = 64;
/**
* Elf64_Ehdr defines
@ -68,50 +67,44 @@ public class Elf {
/**
* e_ident
*/
public static final int EI_MAG0 = 0;
public static final byte ELFMAG0 = 0x7f;
public static final int EI_MAG1 = 1;
public static final byte ELFMAG1 = 0x45;
public static final int EI_MAG2 = 2;
public static final byte ELFMAG2 = 0x4c;
public static final int EI_MAG3 = 3;
public static final byte ELFMAG3 = 0x46;
static final int EI_MAG0 = 0;
static final byte ELFMAG0 = 0x7f;
static final int EI_MAG1 = 1;
static final byte ELFMAG1 = 0x45;
static final int EI_MAG2 = 2;
static final byte ELFMAG2 = 0x4c;
static final int EI_MAG3 = 3;
static final byte ELFMAG3 = 0x46;
static final int EI_CLASS = 4;
static final byte ELFCLASS64 = 0x2;
public static final int EI_CLASS = 4;
public static final byte ELFCLASS64 = 0x2;
static final int EI_DATA = 5;
static final byte ELFDATA2LSB = 0x1;
public static final int EI_DATA = 5;
public static final byte ELFDATA2LSB = 0x1;
static final int EI_VERSION = 6;
static final byte EV_CURRENT = 0x1;
public static final int EI_VERSION = 6;
public static final byte EV_CURRENT = 0x1;
public static final int EI_OSABI = 7;
public static final byte ELFOSABI_NONE = 0x0;
static final int EI_OSABI = 7;
static final byte ELFOSABI_NONE = 0x0;
/**
* e_type
*/
public static final char ET_REL = 0x1;
static final char ET_REL = 0x1;
/**
* e_machine
*/
public static final char EM_NONE = 0;
public static final char EM_X86_64 = 62;
public static final char EM_AARCH64 = 183;
/**
* e_version
*/
// public static final int EV_CURRENT = 1;
static final char EM_NONE = 0;
static final char EM_X86_64 = 62;
static final char EM_AARCH64 = 183;
}
/**
* Elf64_Shdr structure defines
*/
public enum Elf64_Shdr {
enum Elf64_Shdr {
sh_name( 0, 4),
sh_type( 4, 4),
sh_flags( 8, 8),
@ -123,15 +116,15 @@ public class Elf {
sh_addralign(48, 8),
sh_entsize(56, 8);
public final int off;
public final int sz;
final int off;
final int sz;
Elf64_Shdr(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 64;
static int totalsize = 64;
/**
* Elf64_Shdr defines
@ -140,21 +133,21 @@ public class Elf {
/**
* sh_type
*/
public static final int SHT_PROGBITS = 0x1;
public static final int SHT_SYMTAB = 0x2;
public static final int SHT_STRTAB = 0x3;
public static final int SHT_RELA = 0x4;
public static final int SHT_NOBITS = 0x8;
public static final int SHT_REL = 0x9;
static final int SHT_PROGBITS = 0x1;
static final int SHT_SYMTAB = 0x2;
static final int SHT_STRTAB = 0x3;
static final int SHT_RELA = 0x4;
static final int SHT_NOBITS = 0x8;
static final int SHT_REL = 0x9;
public static final byte SHN_UNDEF = 0x0;
static final byte SHN_UNDEF = 0x0;
/**
* sh_flag
*/
public static final int SHF_WRITE = 0x1;
public static final int SHF_ALLOC = 0x2;
public static final int SHF_EXECINSTR = 0x4;
static final int SHF_WRITE = 0x1;
static final int SHF_ALLOC = 0x2;
static final int SHF_EXECINSTR = 0x4;
}
@ -163,7 +156,7 @@ public class Elf {
*
* Elf64_Sym structure defines
*/
public enum Elf64_Sym {
enum Elf64_Sym {
st_name( 0, 4),
st_info( 4, 1),
st_other( 5, 1),
@ -171,25 +164,25 @@ public class Elf {
st_value( 8, 8),
st_size(16, 8);
public final int off;
public final int sz;
final int off;
final int sz;
Elf64_Sym(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 24;
static int totalsize = 24;
/* ST_BIND is in bits 4-7 of st_info. ST_TYPE is in low 4 bits */
public static final byte STB_LOCAL = 0x0;
public static final byte STB_GLOBAL = 0x1;
static final byte STB_LOCAL = 0x0;
static final byte STB_GLOBAL = 0x1;
public static final byte STT_NOTYPE = 0x0;
public static final byte STT_OBJECT = 0x1;
public static final byte STT_FUNC = 0x2;
static final byte STT_NOTYPE = 0x0;
static final byte STT_OBJECT = 0x1;
static final byte STT_FUNC = 0x2;
public static byte ELF64_ST_INFO(byte bind, byte type) {
static byte ELF64_ST_INFO(byte bind, byte type) {
return (byte)(((bind) << 4) + ((type) & 0xf));
}
@ -198,59 +191,59 @@ public class Elf {
/**
* Elf64_Rel structure defines
*/
public enum Elf64_Rel {
enum Elf64_Rel {
r_offset( 0, 8),
r_info( 8, 8);
public final int off;
public final int sz;
final int off;
final int sz;
Elf64_Rel(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 16;
static int totalsize = 16;
/**
* Relocation types
*/
public static final int R_X86_64_NONE = 0x0;
public static final int R_X86_64_64 = 0x1;
public static final int R_X86_64_PC32 = 0x2;
public static final int R_X86_64_PLT32 = 0x4;
public static final int R_X86_64_GOTPCREL = 0x9;
static final int R_X86_64_NONE = 0x0;
static final int R_X86_64_64 = 0x1;
static final int R_X86_64_PC32 = 0x2;
static final int R_X86_64_PLT32 = 0x4;
static final int R_X86_64_GOTPCREL = 0x9;
}
/**
* Elf64_Rela structure defines
*/
public enum Elf64_Rela {
enum Elf64_Rela {
r_offset( 0, 8),
r_info( 8, 8),
r_addend(16, 8);
public final int off;
public final int sz;
final int off;
final int sz;
Elf64_Rela(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 24;
static int totalsize = 24;
public static final int R_X86_64_NONE = 0x0;
public static final int R_X86_64_64 = 0x1;
public static final int R_X86_64_PC32 = 0x2;
public static final int R_X86_64_PLT32 = 0x4;
public static final int R_X86_64_GOTPCREL = 0x9;
static final int R_X86_64_NONE = 0x0;
static final int R_X86_64_64 = 0x1;
static final int R_X86_64_PC32 = 0x2;
static final int R_X86_64_PLT32 = 0x4;
static final int R_X86_64_GOTPCREL = 0x9;
public static long ELF64_R_INFO(int symidx, int type) {
return (((long)symidx << 32) + ((long)type));
static long ELF64_R_INFO(int symidx, int type) {
return (((long)symidx << 32) + type);
}
}
//@formatter:on
}

View File

@ -23,20 +23,20 @@
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
public class ElfByteBuffer {
final class ElfByteBuffer {
public static ByteBuffer allocate(int size) {
static ByteBuffer allocate(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
if (ElfTargetInfo.getElfEndian() == Elf64_Ehdr.ELFDATA2LSB)
if (ElfTargetInfo.getElfEndian() == Elf64_Ehdr.ELFDATA2LSB) {
buf.order(ByteOrder.LITTLE_ENDIAN);
else
} else {
buf.order(ByteOrder.BIG_ENDIAN);
}
return (buf);
}

View File

@ -26,14 +26,13 @@ package jdk.tools.jaotc.binformat.elf;
import java.io.File;
import java.io.FileOutputStream;
public class ElfContainer {
final class ElfContainer {
File outputFile;
FileOutputStream outputStream;
long fileOffset;
private final File outputFile;
private FileOutputStream outputStream;
private long fileOffset;
public ElfContainer(String fileName, String aotVersion) {
String baseName;
ElfContainer(String fileName) {
outputFile = new File(fileName);
if (outputFile.exists()) {
@ -48,7 +47,7 @@ public class ElfContainer {
fileOffset = 0;
}
public void close() {
void close() {
try {
outputStream.close();
} catch (Exception e) {
@ -56,8 +55,10 @@ public class ElfContainer {
}
}
public void writeBytes(byte [] bytes) {
if (bytes == null) return;
void writeBytes(byte[] bytes) {
if (bytes == null) {
return;
}
try {
outputStream.write(bytes);
} catch (Exception e) {
@ -67,11 +68,13 @@ public class ElfContainer {
}
// Write bytes to output file with up front alignment padding
public void writeBytes(byte [] bytes, int alignment) {
if (bytes == null) return;
void writeBytes(byte[] bytes, int alignment) {
if (bytes == null) {
return;
}
try {
// Pad to alignment
while ((fileOffset & (long)(alignment-1)) != 0) {
while ((fileOffset & (alignment - 1)) != 0) {
outputStream.write(0);
fileOffset++;
}
@ -82,4 +85,3 @@ public class ElfContainer {
fileOffset += bytes.length;
}
}

View File

@ -24,55 +24,52 @@
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
public class ElfHeader {
ByteBuffer header;
final class ElfHeader {
private final ByteBuffer header;
public ElfHeader() {
ElfHeader() {
header = ElfByteBuffer.allocate(Elf64_Ehdr.totalsize);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG0, Elf64_Ehdr.ELFMAG0);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG1, Elf64_Ehdr.ELFMAG1);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG2, Elf64_Ehdr.ELFMAG2);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG3, Elf64_Ehdr.ELFMAG3);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_CLASS, Elf64_Ehdr.ELFCLASS64);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_DATA, Elf64_Ehdr.ELFDATA2LSB);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_VERSION, Elf64_Ehdr.EV_CURRENT);
header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_OSABI, Elf64_Ehdr.ELFOSABI_NONE);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG0, Elf64_Ehdr.ELFMAG0);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG1, Elf64_Ehdr.ELFMAG1);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG2, Elf64_Ehdr.ELFMAG2);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_MAG3, Elf64_Ehdr.ELFMAG3);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_CLASS, Elf64_Ehdr.ELFCLASS64);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_DATA, Elf64_Ehdr.ELFDATA2LSB);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_VERSION, Elf64_Ehdr.EV_CURRENT);
header.put(Elf64_Ehdr.e_ident.off + Elf64_Ehdr.EI_OSABI, Elf64_Ehdr.ELFOSABI_NONE);
header.putChar(Elf64_Ehdr.e_type.off, Elf64_Ehdr.ET_REL);
header.putChar(Elf64_Ehdr.e_machine.off, ElfTargetInfo.getElfArch());
header.putInt(Elf64_Ehdr.e_version.off, Elf64_Ehdr.EV_CURRENT);
header.putChar(Elf64_Ehdr.e_ehsize.off, (char)Elf64_Ehdr.totalsize);
header.putChar(Elf64_Ehdr.e_shentsize.off, (char)Elf64_Shdr.totalsize);
header.putChar(Elf64_Ehdr.e_ehsize.off, (char) Elf64_Ehdr.totalsize);
header.putChar(Elf64_Ehdr.e_shentsize.off, (char) Elf64_Shdr.totalsize);
}
// Update header with file offset of first section
public void setSectionOff(int offset) {
void setSectionOff(int offset) {
header.putLong(Elf64_Ehdr.e_shoff.off, offset);
}
// Update header with the number of total sections
public void setSectionNum(int count) {
header.putChar(Elf64_Ehdr.e_shnum.off, (char)count);
void setSectionNum(int count) {
header.putChar(Elf64_Ehdr.e_shnum.off, (char) count);
}
// Update header with the section index containing the
// string table for section names
public void setSectionStrNdx(int index) {
header.putChar(Elf64_Ehdr.e_shstrndx.off, (char)index);
void setSectionStrNdx(int index) {
header.putChar(Elf64_Ehdr.e_shstrndx.off, (char) index);
}
public byte[] getArray() {
byte[] getArray() {
return header.array();
}
}

View File

@ -24,28 +24,23 @@
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
public class ElfRelocEntry {
ByteBuffer entry;
final class ElfRelocEntry {
private final ByteBuffer entry;
public ElfRelocEntry(int offset, int symno, int type, int addend) {
ElfRelocEntry(int offset, int symno, int type, int addend) {
entry = ElfByteBuffer.allocate(Elf64_Rela.totalsize);
entry.putLong(Elf64_Rela.r_offset.off, offset);
entry.putLong(Elf64_Rela.r_info.off, Elf64_Rela.ELF64_R_INFO(symno,type));
entry.putLong(Elf64_Rela.r_info.off, Elf64_Rela.ELF64_R_INFO(symno, type));
entry.putLong(Elf64_Rela.r_addend.off, addend);
}
public byte[] getArray() {
byte[] getArray() {
return entry.array();
}
}

View File

@ -25,48 +25,38 @@ package jdk.tools.jaotc.binformat.elf;
import java.util.ArrayList;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.ElfRelocEntry;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
public class ElfRelocTable {
ArrayList<ArrayList<ElfRelocEntry>> relocEntries;
final class ElfRelocTable {
private final ArrayList<ArrayList<ElfRelocEntry>> relocEntries;
public ElfRelocTable(int numsects) {
relocEntries = new ArrayList<ArrayList<ElfRelocEntry>>(numsects);
for (int i = 0; i < numsects; i++)
ElfRelocTable(int numsects) {
relocEntries = new ArrayList<>(numsects);
for (int i = 0; i < numsects; i++) {
relocEntries.add(new ArrayList<ElfRelocEntry>());
}
}
public void createRelocationEntry(int sectindex,
int offset,
int symno,
int type,
int addend) {
ElfRelocEntry entry = new ElfRelocEntry(offset,
symno,
type,
addend);
void createRelocationEntry(int sectindex, int offset, int symno, int type, int addend) {
ElfRelocEntry entry = new ElfRelocEntry(offset, symno, type, addend);
relocEntries.get(sectindex).add(entry);
}
public int getNumRelocs(int section_index) {
int getNumRelocs(int section_index) {
return relocEntries.get(section_index).size();
}
// Return the relocation entries for a single section
// or null if no entries added to section
public byte [] getRelocData(int section_index) {
// or null if no entries added to section
byte[] getRelocData(int section_index) {
ArrayList<ElfRelocEntry> entryList = relocEntries.get(section_index);
if (entryList.size() == 0)
if (entryList.size() == 0) {
return null;
}
ByteBuffer relocData = ElfByteBuffer.allocate(entryList.size() * Elf64_Rela.totalsize);
// Copy each entry to a single ByteBuffer
@ -78,4 +68,3 @@ public class ElfRelocTable {
return (relocData.array());
}
}

View File

@ -24,40 +24,36 @@
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
public class ElfSection {
String name;
ByteBuffer section;
byte [] data;
boolean hasrelocations;
int sectionIndex;
final class ElfSection {
private final String name;
private final ByteBuffer section;
private final byte[] data;
private final boolean hasrelocations;
private final int sectionIndex;
/**
* String holding section name strings
*/
private static StringBuilder sectNameTab = new StringBuilder();
private final static StringBuilder sectNameTab = new StringBuilder();
/**
* Keeps track of bytes in section string table since strTabContent.length()
* is number of chars, not bytes.
* Keeps track of bytes in section string table since strTabContent.length() is number of chars,
* not bytes.
*/
private static int shStrTabNrOfBytes = 0;
public ElfSection(String sectName, byte [] sectData, int sectFlags,
int sectType, boolean hasRelocations, int align,
int sectIndex) {
ElfSection(String sectName, byte[] sectData, int sectFlags, int sectType,
boolean hasRelocations, int align, int sectIndex) {
section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize);
name = sectName;
// Return all 0's for NULL section
if (sectIndex == 0) {
sectNameTab.append('\0');
@ -71,7 +67,6 @@ public class ElfSection {
section.putInt(Elf64_Shdr.sh_name.off, shStrTabNrOfBytes);
sectNameTab.append(sectName).append('\0');
shStrTabNrOfBytes += (sectName.getBytes().length + 1);
name = sectName;
section.putInt(Elf64_Shdr.sh_type.off, sectType);
section.putLong(Elf64_Shdr.sh_flags.off, sectFlags);
@ -81,8 +76,7 @@ public class ElfSection {
if (sectName.equals(".shstrtab")) {
section.putLong(Elf64_Shdr.sh_size.off, shStrTabNrOfBytes);
data = sectNameTab.toString().getBytes();
}
else {
} else {
data = sectData;
section.putLong(Elf64_Shdr.sh_size.off, sectData.length);
}
@ -110,55 +104,53 @@ public class ElfSection {
sectionIndex = sectIndex;
}
public String getName() {
String getName() {
return name;
}
public long getSize() {
long getSize() {
return section.getLong(Elf64_Shdr.sh_size.off);
}
public int getDataAlign() {
return ((int)section.getLong(Elf64_Shdr.sh_addralign.off));
int getDataAlign() {
return ((int) section.getLong(Elf64_Shdr.sh_addralign.off));
}
// Alignment requirements for the Elf64_Shdr structures
public static int getShdrAlign() {
static int getShdrAlign() {
return (4);
}
public byte[] getArray() {
byte[] getArray() {
return section.array();
}
public byte[] getDataArray() {
byte[] getDataArray() {
return data;
}
public void setOffset(long offset) {
void setOffset(long offset) {
section.putLong(Elf64_Shdr.sh_offset.off, offset);
}
public void setLink(int link) {
void setLink(int link) {
section.putInt(Elf64_Shdr.sh_link.off, link);
}
public void setInfo(int info) {
void setInfo(int info) {
section.putInt(Elf64_Shdr.sh_info.off, info);
}
public long getOffset() {
long getOffset() {
return (section.getLong(Elf64_Shdr.sh_offset.off));
}
public boolean hasRelocations() {
boolean hasRelocations() {
return hasrelocations;
}
public int getSectionId() {
int getSectionId() {
return sectionIndex;
}
}

View File

@ -24,34 +24,29 @@
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
public class ElfSymbol extends NativeSymbol {
ByteBuffer sym;
final class ElfSymbol extends NativeSymbol {
private final ByteBuffer sym;
public ElfSymbol(int symbolindex, int strindex, byte type, byte bind,
byte sectindex, long offset, long size) {
ElfSymbol(int symbolindex, int strindex, byte type, byte bind, byte sectindex, long offset, long size) {
super(symbolindex);
sym = ElfByteBuffer.allocate(Elf64_Sym.totalsize);
sym.putInt(Elf64_Sym.st_name.off, strindex);
sym.put(Elf64_Sym.st_info.off, Elf64_Sym.ELF64_ST_INFO(bind, type));
sym.put(Elf64_Sym.st_other.off, (byte)0);
sym.put(Elf64_Sym.st_other.off, (byte) 0);
// Section indexes start at 1 but we manage the index internally
// as 0 relative
sym.putChar(Elf64_Sym.st_shndx.off, (char)(sectindex));
sym.putChar(Elf64_Sym.st_shndx.off, (char) (sectindex));
sym.putLong(Elf64_Sym.st_value.off, offset);
sym.putLong(Elf64_Sym.st_size.off, size);
}
public byte[] getArray() {
byte[] getArray() {
return sym.array();
}
}

View File

@ -24,41 +24,38 @@
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.binformat.elf.ElfSymbol;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
public class ElfSymtab {
final class ElfSymtab {
ArrayList<ElfSymbol>localSymbols = new ArrayList<ElfSymbol>();
ArrayList<ElfSymbol>globalSymbols = new ArrayList<ElfSymbol>();
private final ArrayList<ElfSymbol> localSymbols = new ArrayList<>();
private final ArrayList<ElfSymbol> globalSymbols = new ArrayList<>();
/**
* number of symbols added
*/
int symbolCount;
private int symbolCount;
/**
* String holding symbol table strings
*/
private StringBuilder strTabContent = new StringBuilder();
private final StringBuilder strTabContent = new StringBuilder();
/**
* Keeps track of bytes in string table since strTabContent.length()
* is number of chars, not bytes.
* Keeps track of bytes in string table since strTabContent.length() is number of chars, not
* bytes.
*/
private int strTabNrOfBytes = 0;
public ElfSymtab() {
ElfSymtab() {
symbolCount = 0;
}
public ElfSymbol addSymbolEntry(String name, byte type, byte bind,
byte secHdrIndex, long offset, long size) {
ElfSymbol addSymbolEntry(String name, byte type, byte bind, byte secHdrIndex, long offset, long size) {
// Get the current symbol index and append symbol name to string table.
int index;
ElfSymbol sym;
@ -76,7 +73,7 @@ public class ElfSymtab {
// strTabContent.append("_").append(name).append('\0');
strTabContent.append(name).append('\0');
// + 1 for null, + 1 for "_"
//strTabNrOfBytes += (name.getBytes().length + 1 + 1);
// strTabNrOfBytes += (name.getBytes().length + 1 + 1);
strTabNrOfBytes += (name.getBytes().length + 1);
sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size);
@ -92,44 +89,47 @@ public class ElfSymtab {
// Update the symbol indexes once all symbols have been added.
// This is required since we'll be reordering the symbols in the
// file to be in the order of Local then global.
public void updateIndexes() {
void updateIndexes() {
int index = 0;
// Update the local symbol indexes
for (int i = 0; i < localSymbols.size(); i++ ) {
for (int i = 0; i < localSymbols.size(); i++) {
ElfSymbol sym = localSymbols.get(i);
sym.setIndex(index++);
}
// Update the global symbol indexes
for (int i = 0; i < globalSymbols.size(); i++ ) {
for (int i = 0; i < globalSymbols.size(); i++) {
ElfSymbol sym = globalSymbols.get(i);
sym.setIndex(index++);
}
}
public int getNumLocalSyms() { return localSymbols.size(); }
public int getNumGlobalSyms() { return globalSymbols.size(); }
int getNumLocalSyms() {
return localSymbols.size();
}
int getNumGlobalSyms() {
return globalSymbols.size();
}
// Create a single byte array that contains the symbol table entries
public byte[] getSymtabArray() {
int index = 0;
ByteBuffer symtabData = ElfByteBuffer.allocate(symbolCount*Elf64_Sym.totalsize);
byte [] retarray;
byte[] getSymtabArray() {
ByteBuffer symtabData = ElfByteBuffer.allocate(symbolCount * Elf64_Sym.totalsize);
byte[] retarray;
updateIndexes();
// Add the local symbols
for (int i = 0; i < localSymbols.size(); i++ ) {
for (int i = 0; i < localSymbols.size(); i++) {
ElfSymbol sym = localSymbols.get(i);
byte [] arr = sym.getArray();
byte[] arr = sym.getArray();
symtabData.put(arr);
}
// Add the global symbols
for (int i = 0; i < globalSymbols.size(); i++ ) {
for (int i = 0; i < globalSymbols.size(); i++) {
ElfSymbol sym = globalSymbols.get(i);
byte [] arr = sym.getArray();
byte[] arr = sym.getArray();
symtabData.put(arr);
}
retarray = symtabData.array();
@ -138,10 +138,8 @@ public class ElfSymtab {
}
// Return the string table array
public byte[] getStrtabArray() {
byte [] strs = strTabContent.toString().getBytes();
byte[] getStrtabArray() {
byte[] strs = strTabContent.toString().getBytes();
return (strs);
}
}

View File

@ -24,14 +24,13 @@
package jdk.tools.jaotc.binformat.elf;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
/**
* Class that abstracts MACH-O target details.
*
*/
public class ElfTargetInfo {
final class ElfTargetInfo {
/**
* Target architecture.
*/
@ -68,16 +67,15 @@ public class ElfTargetInfo {
}
}
public static char getElfArch() {
static char getElfArch() {
return arch;
}
public static int getElfEndian() {
static int getElfEndian() {
return endian;
}
public static String getOsName() {
static String getOsName() {
return osName;
}
}

View File

@ -24,13 +24,11 @@
package jdk.tools.jaotc.binformat.elf;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import jdk.tools.jaotc.binformat.Container;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.CodeContainer;
@ -38,17 +36,14 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Relocation;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.binformat.elf.ElfSymbol;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
public class JELFRelocObject {
@ -59,34 +54,29 @@ public class JELFRelocObject {
private final int segmentSize;
public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
public JELFRelocObject(BinaryContainer binContainer, String outputFileName) {
this.binContainer = binContainer;
this.elfContainer = new ElfContainer(outputFileName, aotVersion);
this.elfContainer = new ElfContainer(outputFileName);
this.segmentSize = binContainer.getCodeSegmentSize();
}
private ElfSection createByteSection(ArrayList<ElfSection>sections,
String sectName,
byte [] scnData,
boolean hasRelocs,
int align,
int scnFlags,
int scnType) {
private static ElfSection createByteSection(ArrayList<ElfSection> sections,
String sectName,
byte[] scnData,
boolean hasRelocs,
int align,
int scnFlags,
int scnType) {
ElfSection sect = new ElfSection(sectName,
scnData,
scnFlags,
scnType,
hasRelocs,
align,
sections.size());
ElfSection sect = new ElfSection(sectName, scnData, scnFlags, scnType,
hasRelocs, align, sections.size());
// Add this section to our list
sections.add(sect);
return (sect);
}
private void createByteSection(ArrayList<ElfSection>sections,
private void createByteSection(ArrayList<ElfSection> sections,
ByteContainer c, int scnFlags) {
ElfSection sect;
boolean hasRelocs = c.hasRelocations();
@ -112,15 +102,15 @@ public class JELFRelocObject {
c.setSectionId(sect.getSectionId());
}
private void createCodeSection(ArrayList<ElfSection>sections, CodeContainer c) {
private void createCodeSection(ArrayList<ElfSection> sections, CodeContainer c) {
createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR);
}
private void createReadOnlySection(ArrayList<ElfSection>sections, ReadOnlyDataContainer c) {
private void createReadOnlySection(ArrayList<ElfSection> sections, ReadOnlyDataContainer c) {
createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC);
}
private void createReadWriteSection(ArrayList<ElfSection>sections, ByteContainer c) {
private void createReadWriteSection(ArrayList<ElfSection> sections, ByteContainer c) {
createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE);
}
@ -135,7 +125,7 @@ public class JELFRelocObject {
// Allocate ELF Header
ElfHeader eh = new ElfHeader();
ArrayList<ElfSection> sections = new ArrayList<ElfSection>();
ArrayList<ElfSection> sections = new ArrayList<>();
// Create the null section
createByteSection(sections, null, null, false, 1, 0, 0);
@ -146,63 +136,49 @@ public class JELFRelocObject {
createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
createReadWriteSection(sections, binContainer.getMetaspaceGotContainer());
createReadWriteSection(sections, binContainer.getMetadataGotContainer());
createReadWriteSection(sections, binContainer.getMethodStateContainer());
createReadWriteSection(sections, binContainer.getOopGotContainer());
createReadWriteSection(sections, binContainer.getMethodMetadataContainer());
createReadOnlySection(sections, binContainer.getMethodMetadataContainer());
createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
createReadOnlySection(sections, binContainer.getConstantDataContainer());
createReadOnlySection(sections, binContainer.getConfigContainer());
// createExternalLinkage();
createCodeSection(sections, binContainer.getExtLinkageContainer());
createReadWriteSection(sections, binContainer.getKlassesGotContainer());
createReadWriteSection(sections, binContainer.getCountersGotContainer());
createReadWriteSection(sections, binContainer.getMetadataGotContainer());
createReadWriteSection(sections, binContainer.getOopGotContainer());
createReadWriteSection(sections, binContainer.getMethodStateContainer());
createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
// Get ELF symbol data from BinaryContainer object's symbol tables
ElfSymtab symtab = createELFSymbolTables(sections, symbols);
ElfSymtab symtab = createELFSymbolTables(symbols);
// Create string table section and symbol table sections in
// that order since symtab section needs to set the index of
// strtab in sh_link field
ElfSection strTabSection = createByteSection(sections,
".strtab",
ElfSection strTabSection = createByteSection(sections, ".strtab",
symtab.getStrtabArray(),
false,
1,
0,
false, 1, 0,
Elf64_Shdr.SHT_STRTAB);
// Now create .symtab section with the symtab data constructed.
// On Linux, sh_link of symtab contains the index of string table
// its symbols reference and sh_info contains the index of first
// non-local symbol
ElfSection symTabSection = createByteSection(sections,
".symtab",
symtab.getSymtabArray(),
false,
8,
0,
Elf64_Shdr.SHT_SYMTAB);
ElfSection symTabSection = createByteSection(sections, ".symtab",
symtab.getSymtabArray(),
false, 8, 0,
Elf64_Shdr.SHT_SYMTAB);
symTabSection.setLink(strTabSection.getSectionId());
symTabSection.setInfo(symtab.getNumLocalSyms());
ElfRelocTable elfRelocTable = createElfRelocTable(sections,
relocationTable);
ElfRelocTable elfRelocTable = createElfRelocTable(sections, relocationTable);
createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId());
// Now, finally, after creating all sections, create shstrtab section
ElfSection shStrTabSection = createByteSection(sections,
".shstrtab",
null,
false,
1,
0,
Elf64_Shdr.SHT_STRTAB);
ElfSection shStrTabSection = createByteSection(sections, ".shstrtab",
null, false, 1, 0,
Elf64_Shdr.SHT_STRTAB);
eh.setSectionStrNdx(shStrTabSection.getSectionId());
// Update all section offsets and the Elf header section offset
@ -211,21 +187,21 @@ public class JELFRelocObject {
int file_offset = Elf64_Ehdr.totalsize;
// and round it up
file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) &
~((sections.get(1).getDataAlign()-1));
file_offset = (file_offset + (sections.get(1).getDataAlign() - 1)) &
~((sections.get(1).getDataAlign() - 1));
// Calc file offsets for section data skipping null section
for (int i = 1; i < sections.size(); i++) {
ElfSection sect = sections.get(i);
file_offset = (file_offset + (sect.getDataAlign()-1)) &
~((sect.getDataAlign()-1));
file_offset = (file_offset + (sect.getDataAlign() - 1)) &
~((sect.getDataAlign() - 1));
sect.setOffset(file_offset);
file_offset += sect.getSize();
}
// Align the section table
file_offset = (file_offset + (ElfSection.getShdrAlign()-1)) &
~((ElfSection.getShdrAlign()-1));
file_offset = (file_offset + (ElfSection.getShdrAlign() - 1)) &
~((ElfSection.getShdrAlign() - 1));
// Update the Elf Header with the offset of the first Elf64_Shdr
// and the number of sections.
@ -249,24 +225,25 @@ public class JELFRelocObject {
elfContainer.close();
}
/**
* Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF
* symbol table and ELF symbol table are created from BinaryContainer's symbol info.
* Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF symbol
* table and ELF symbol table are created from BinaryContainer's symbol info.
*
* @param symbols
*/
private ElfSymtab createELFSymbolTables(ArrayList<ElfSection> sections, Collection<Symbol> symbols) {
private static ElfSymtab createELFSymbolTables(Collection<Symbol> symbols) {
ElfSymtab symtab = new ElfSymtab();
// First, create the initial null symbol. This is a local symbol.
symtab.addSymbolEntry("", (byte)0, (byte)0, Elf64_Shdr.SHN_UNDEF, 0, 0);
symtab.addSymbolEntry("", (byte) 0, (byte) 0, Elf64_Shdr.SHN_UNDEF, 0, 0);
// Now create ELF symbol entries for all symbols.
for (Symbol symbol : symbols) {
// Get the index of section this symbol is defined in.
int secHdrIndex = symbol.getSection().getSectionId();
ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize());
symbol.setNativeSymbol((NativeSymbol)elfSymbol);
ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte) secHdrIndex, symbol.getOffset(), symbol.getSize());
symbol.setNativeSymbol(elfSymbol);
}
return (symtab);
}
@ -300,8 +277,7 @@ public class JELFRelocObject {
ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size());
/*
* For each of the symbols with associated relocation records, create a Elf relocation
* entry.
* For each of the symbols with associated relocation records, create a Elf relocation entry.
*/
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
List<Relocation> relocs = entry.getValue();
@ -319,69 +295,39 @@ public class JELFRelocObject {
return (elfRelocTable);
}
private void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
private static void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
RelocType relocType = reloc.getType();
int elfRelocType = getELFRelocationType(relocType);
ElfSymbol sym = (ElfSymbol)symbol.getNativeSymbol();
ElfSymbol sym = (ElfSymbol) symbol.getNativeSymbol();
int symno = sym.getIndex();
int sectindex = reloc.getSection().getSectionId();
int offset = reloc.getOffset();
int addend = 0;
switch (relocType) {
case FOREIGN_CALL_DIRECT:
case JAVA_CALL_DIRECT:
case STUB_CALL_DIRECT:
case FOREIGN_CALL_INDIRECT_GOT: {
// Create relocation entry
// System.out.println("getELFRelocationType: PLT relocation type using X86_64_RELOC_BRANCH");
addend = -4; // Size in bytes of the patch location
// Relocation should be applied at the location after call operand
offset = offset + reloc.getSize() + addend;
break;
}
case FOREIGN_CALL_DIRECT_FAR: {
// Create relocation entry
addend = -8; // Size in bytes of the patch location
// Relocation should be applied at the location after call operand
// 10 = 2 (jmp [r]) + 8 (imm64)
offset = offset + reloc.getSize() + addend - 2;
break;
}
case FOREIGN_CALL_INDIRECT:
case JAVA_CALL_INDIRECT:
case STUB_CALL_INDIRECT: {
// Do nothing.
return;
}
case EXTERNAL_DATA_REFERENCE_FAR: {
// Create relocation entry
case METASPACE_GOT_REFERENCE:
case EXTERNAL_PLT_TO_GOT: {
addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to the move instruction.
* offset points to the test instruction after the instruction that loads
* the address of polling page. So set the offset appropriately.
* reloc.getOffset() points to the test instruction after the instruction that loads the address of
* polling page. So set the offset appropriately.
*/
offset = offset + addend;
break;
}
case METASPACE_GOT_REFERENCE:
case EXTERNAL_PLT_TO_GOT:
case STATIC_STUB_TO_STATIC_METHOD:
case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: {
addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to
* the move instruction. reloc.getOffset() points to the
* test instruction after the instruction that loads the
* address of polling page. So set the offset appropriately.
*/
offset = offset + addend;
break;
}
case EXTERNAL_GOT_TO_PLT:
case LOADTIME_ADDRESS: {
case EXTERNAL_GOT_TO_PLT: {
// this is load time relocations
break;
}
@ -396,27 +342,17 @@ public class JELFRelocObject {
switch (ElfTargetInfo.getElfArch()) {
case Elf64_Ehdr.EM_X86_64:
// Return R_X86_64_* entries based on relocType
if (relocType == RelocType.FOREIGN_CALL_DIRECT ||
relocType == RelocType.JAVA_CALL_DIRECT ||
if (relocType == RelocType.JAVA_CALL_DIRECT ||
relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
elfRelocType = Elf64_Rela.R_X86_64_PLT32;
} else if (relocType == RelocType.STUB_CALL_DIRECT) {
elfRelocType = Elf64_Rela.R_X86_64_PC32;
} else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
elfRelocType = Elf64_Rela.R_X86_64_64;
} else if (relocType == RelocType.FOREIGN_CALL_INDIRECT ||
relocType == RelocType.JAVA_CALL_INDIRECT ||
relocType == RelocType.STUB_CALL_INDIRECT) {
} else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
elfRelocType = Elf64_Rela.R_X86_64_NONE;
} else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
elfRelocType = Elf64_Rela.R_X86_64_GOTPCREL;
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
relocType == RelocType.EXTERNAL_PLT_TO_GOT ||
relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
elfRelocType = Elf64_Rela.R_X86_64_PC32;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT ||
relocType == RelocType.LOADTIME_ADDRESS) {
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
elfRelocType = Elf64_Rela.R_X86_64_64;
} else {
assert false : "Unhandled relocation type: " + relocType;
@ -428,9 +364,9 @@ public class JELFRelocObject {
return elfRelocType;
}
private void createElfRelocSections(ArrayList<ElfSection> sections,
ElfRelocTable elfRelocTable,
int symtabsectidx) {
private static void createElfRelocSections(ArrayList<ElfSection> sections,
ElfRelocTable elfRelocTable,
int symtabsectidx) {
// Grab count before we create new sections
int count = sections.size();
@ -439,15 +375,11 @@ public class JELFRelocObject {
if (elfRelocTable.getNumRelocs(i) > 0) {
ElfSection sect = sections.get(i);
String relname = ".rela" + sect.getName();
ElfSection relocSection = createByteSection(sections,
relname,
elfRelocTable.getRelocData(i),
false,
8,
0,
Elf64_Shdr.SHT_RELA);
relocSection.setLink(symtabsectidx);
relocSection.setInfo(sect.getSectionId());
ElfSection relocSection = createByteSection(sections, relname,
elfRelocTable.getRelocData(i),
false, 8, 0, Elf64_Shdr.SHT_RELA);
relocSection.setLink(symtabsectidx);
relocSection.setInfo(sect.getSectionId());
}
}
}

View File

@ -53,11 +53,8 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Relocation;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.section_64;
import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64;
@ -85,7 +82,7 @@ public class JMachORelocObject {
this.segmentSize = binContainer.getCodeSegmentSize();
}
private void createByteSection(ArrayList<MachOSection>sections,
private void createByteSection(ArrayList<MachOSection> sections,
ByteContainer c, String sectName, String segName, int scnFlags) {
if (c.getByteArray().length == 0) {
@ -102,24 +99,24 @@ public class JMachORelocObject {
sections.add(sect);
// Record the section Id (0 relative)
c.setSectionId(sections.size()-1);
c.setSectionId(sections.size() - 1);
// TODO: Clear out code section data to allow for GC
// c.clear();
}
private void createCodeSection(ArrayList<MachOSection>sections, CodeContainer c) {
createByteSection(sections, c, /*c.getContainerName()*/ "__text", "__TEXT",
section_64.S_ATTR_PURE_INSTRUCTIONS|
private void createCodeSection(ArrayList<MachOSection> sections, CodeContainer c) {
createByteSection(sections, c, /* c.getContainerName() */ "__text", "__TEXT",
section_64.S_ATTR_PURE_INSTRUCTIONS |
section_64.S_ATTR_SOME_INSTRUCTIONS);
}
private void createReadOnlySection(ArrayList<MachOSection>sections, ReadOnlyDataContainer c) {
private void createReadOnlySection(ArrayList<MachOSection> sections, ReadOnlyDataContainer c) {
createByteSection(sections, c, c.getContainerName(), "__TEXT",
section_64.S_ATTR_SOME_INSTRUCTIONS);
}
private void createReadWriteSection(ArrayList<MachOSection>sections, ByteContainer c) {
private void createReadWriteSection(ArrayList<MachOSection> sections, ByteContainer c) {
createByteSection(sections, c, c.getContainerName(), "__DATA", section_64.S_REGULAR);
}
@ -140,7 +137,7 @@ public class JMachORelocObject {
MachOHeader mh = new MachOHeader();
ArrayList<MachOSection> sections = new ArrayList<MachOSection>();
ArrayList<MachOSection> sections = new ArrayList<>();
// Create Sections contained in the main Segment LC_SEGMENT_64
@ -149,21 +146,19 @@ public class JMachORelocObject {
createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
createReadWriteSection(sections, binContainer.getMetaspaceGotContainer());
createReadWriteSection(sections, binContainer.getMetadataGotContainer());
createReadWriteSection(sections, binContainer.getMethodStateContainer());
createReadWriteSection(sections, binContainer.getOopGotContainer());
createReadWriteSection(sections, binContainer.getMethodMetadataContainer());
createReadOnlySection(sections, binContainer.getMethodMetadataContainer());
createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
createReadOnlySection(sections, binContainer.getConstantDataContainer());
createReadOnlySection(sections, binContainer.getConfigContainer());
// createExternalLinkage();
createCodeSection(sections, binContainer.getExtLinkageContainer());
createReadWriteSection(sections, binContainer.getKlassesGotContainer());
createReadWriteSection(sections, binContainer.getCountersGotContainer());
createReadWriteSection(sections, binContainer.getMetadataGotContainer());
createReadWriteSection(sections, binContainer.getMethodStateContainer());
createReadWriteSection(sections, binContainer.getOopGotContainer());
createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
// Update the Header sizeofcmds size.
// This doesn't include the Header struct size
mh.setCmdSizes(4, segment_command_64.totalsize +
@ -175,14 +170,14 @@ public class JMachORelocObject {
// Initialize file offset for data past commands
int file_offset = mach_header_64.totalsize + mh.getCmdSize();
// and round it up
file_offset = (file_offset + (sections.get(0).getAlign()-1)) & ~((sections.get(0).getAlign()-1));
file_offset = (file_offset + (sections.get(0).getAlign() - 1)) & ~((sections.get(0).getAlign() - 1));
long address = 0;
int segment_offset = file_offset;
for (int i = 0; i < sections.size(); i++) {
MachOSection sect = sections.get(i);
file_offset = (file_offset + (sect.getAlign()-1)) & ~((sect.getAlign()-1));
address = (address + (sect.getAlign()-1)) & ~((sect.getAlign()-1));
file_offset = (file_offset + (sect.getAlign() - 1)) & ~((sect.getAlign() - 1));
address = (address + (sect.getAlign() - 1)) & ~((sect.getAlign() - 1));
sect.setOffset(file_offset);
sect.setAddr(address);
file_offset += sect.getSize();
@ -199,7 +194,6 @@ public class JMachORelocObject {
segment_size,
sections.size());
MachOVersion vers = new MachOVersion();
// Get symbol data from BinaryContainer object's symbol tables
@ -213,7 +207,7 @@ public class JMachORelocObject {
// Create the Relocation Tables
MachORelocTable machORelocs = createMachORelocTable(sections, relocationTable, symtab);
// Calculate file offset for relocation data
file_offset = (file_offset + (machORelocs.getAlign()-1)) & ~((machORelocs.getAlign()-1));
file_offset = (file_offset + (MachORelocTable.getAlign() - 1)) & ~((MachORelocTable.getAlign() - 1));
// Update relocation sizing information in each section
for (int i = 0; i < sections.size(); i++) {
@ -227,10 +221,9 @@ public class JMachORelocObject {
}
// Calculate and set file offset for symbol table data
file_offset = (file_offset + (symtab.getAlign()-1)) & ~((symtab.getAlign()-1));
file_offset = (file_offset + (MachOSymtab.getAlign() - 1)) & ~((MachOSymtab.getAlign() - 1));
symtab.setOffset(file_offset);
// Write Out Header
machoContainer.writeBytes(mh.getArray());
// Write out first Segment
@ -259,12 +252,13 @@ public class JMachORelocObject {
// Write out the relocation tables for all sections
for (int i = 0; i < sections.size(); i++) {
if (machORelocs.getNumRelocs(i) > 0)
machoContainer.writeBytes(machORelocs.getRelocData(i), machORelocs.getAlign());
if (machORelocs.getNumRelocs(i) > 0) {
machoContainer.writeBytes(machORelocs.getRelocData(i), MachORelocTable.getAlign());
}
}
// Write out data associated with LC_SYMTAB
machoContainer.writeBytes(symtab.getDataArray(), symtab.getAlign());
machoContainer.writeBytes(symtab.getDataArray(), MachOSymtab.getAlign());
machoContainer.close();
}
@ -273,14 +267,14 @@ public class JMachORelocObject {
* Construct MachO symbol data from BinaryContainer object's symbol tables. Both dynamic MachO
* symbol table and MachO symbol table are created from BinaryContainer's symbol info.
*
* @param sections
* @param symbols
* @param symtab
*/
private MachOSymtab createMachOSymbolTables(ArrayList<MachOSection>sections,
Collection<Symbol> symbols) {
private static MachOSymtab createMachOSymbolTables(ArrayList<MachOSection> sections,
Collection<Symbol> symbols) {
MachOSymtab symtab = new MachOSymtab();
// First, create the initial null symbol. This is a local symbol.
symtab.addSymbolEntry("", (byte)nlist_64.N_UNDF, (byte)0, (long)0);
symtab.addSymbolEntry("", (byte) nlist_64.N_UNDF, (byte) 0, 0);
// Now create MachO symbol entries for all symbols.
for (Symbol symbol : symbols) {
@ -290,14 +284,14 @@ public class JMachORelocObject {
long sectionAddr = sections.get(sectionId).getAddr();
MachOSymbol machoSymbol = symtab.addSymbolEntry(symbol.getName(),
getMachOTypeOf(symbol),
(byte)sectionId,
symbol.getOffset() + sectionAddr);
symbol.setNativeSymbol((NativeSymbol)machoSymbol);
getMachOTypeOf(symbol),
(byte) sectionId,
symbol.getOffset() + sectionAddr);
symbol.setNativeSymbol(machoSymbol);
}
// Now that all symbols are enterred, update the
// symbol indexes. This is necessary since they will
// symbol indexes. This is necessary since they will
// be reordered based on local, global and undefined.
symtab.updateIndexes();
@ -309,9 +303,9 @@ public class JMachORelocObject {
byte type = nlist_64.N_UNDF;
// Global or Local
if (sym.getBinding() == Symbol.Binding.GLOBAL)
if (sym.getBinding() == Symbol.Binding.GLOBAL) {
type = nlist_64.N_EXT;
}
// If Function or Data, add section type
if (kind == Symbol.Kind.NATIVE_FUNCTION ||
kind == Symbol.Kind.JAVA_FUNCTION ||
@ -335,8 +329,7 @@ public class JMachORelocObject {
MachORelocTable machORelocTable = new MachORelocTable(sections.size());
/*
* For each of the symbols with associated relocation records, create a MachO relocation
* entry.
* For each of the symbols with associated relocation records, create a MachO relocation entry.
*/
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
List<Relocation> relocs = entry.getValue();
@ -354,11 +347,11 @@ public class JMachORelocObject {
return (machORelocTable);
}
private void createRelocation(Symbol symbol, Relocation reloc, MachORelocTable machORelocTable) {
private static void createRelocation(Symbol symbol, Relocation reloc, MachORelocTable machORelocTable) {
RelocType relocType = reloc.getType();
int machORelocType = getMachORelocationType(relocType);
MachOSymbol sym = (MachOSymbol)symbol.getNativeSymbol();
MachOSymbol sym = (MachOSymbol) symbol.getNativeSymbol();
int symno = sym.getIndex();
int sectindex = reloc.getSection().getSectionId();
int offset = reloc.getOffset();
@ -366,73 +359,39 @@ public class JMachORelocObject {
int length = 0;
int isextern = 1;
/*
System.out.println("reloctype: " + relocType + " size is " +
reloc.getSize() + " offset is " + offset +
" Section Index is " + (sectindex) +
" Symbol Index is " + symno +
" Symbol Name is " + symbol.getName() + "\n");
*/
switch (relocType) {
case FOREIGN_CALL_DIRECT:
case JAVA_CALL_DIRECT:
case STUB_CALL_DIRECT:
case FOREIGN_CALL_INDIRECT_GOT: {
// Create relocation entry
// System.out.println("getMachORelocationType: PLT relocation type using X86_64_RELOC_BRANCH");
int addend = -4; // Size in bytes of the patch location
// Relocation should be applied at the location after call operand
offset = offset + reloc.getSize() + addend;
pcrel = 1; length = 2;
pcrel = 1;
length = 2;
break;
}
case FOREIGN_CALL_DIRECT_FAR: {
// Create relocation entry
int addend = -8; // Size in bytes of the patch location
// Relocation should be applied at the location after call operand
// 10 = 2 (jmp [r]) + 8 (imm64)
offset = offset + reloc.getSize() + addend - 2;
pcrel = 0; length = 3;
break;
}
case FOREIGN_CALL_INDIRECT:
case JAVA_CALL_INDIRECT:
case STUB_CALL_INDIRECT: {
case JAVA_CALL_INDIRECT: {
// Do nothing.
return;
}
case EXTERNAL_DATA_REFERENCE_FAR: {
// Create relocation entry
case METASPACE_GOT_REFERENCE:
case EXTERNAL_PLT_TO_GOT: {
int addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to the move instruction.
* offset points to the test instruction after the instruction that loads
* the address of polling page. So set the offset appropriately.
* reloc.getOffset() points to the test instruction after the instruction that loads the address of
* polling page. So set the offset appropriately.
*/
offset = offset + addend;
pcrel = 0; length = 2;
pcrel = 1;
length = 2;
break;
}
case METASPACE_GOT_REFERENCE:
case EXTERNAL_PLT_TO_GOT:
case STATIC_STUB_TO_STATIC_METHOD:
case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: {
int addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to
* the move instruction. reloc.getOffset() points to the
* test instruction after the instruction that loads the
* address of polling page. So set the offset appropriately.
*/
offset = offset + addend;
pcrel = 1; length = 2;
break;
}
case EXTERNAL_GOT_TO_PLT:
case LOADTIME_ADDRESS: {
case EXTERNAL_GOT_TO_PLT: {
// this is load time relocations
pcrel = 0; length = 3;
pcrel = 0;
length = 3;
break;
}
default:
@ -448,20 +407,17 @@ public class JMachORelocObject {
switch (MachOTargetInfo.getMachOArch()) {
case mach_header_64.CPU_TYPE_X86_64:
// Return X86_64_RELOC_* entries based on relocType
if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
if (relocType == RelocType.JAVA_CALL_DIRECT ||
relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
machORelocType = reloc_info.X86_64_RELOC_BRANCH;
} else if (relocType == RelocType.STUB_CALL_DIRECT) {
machORelocType = reloc_info.X86_64_RELOC_BRANCH;
} else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
machORelocType = reloc_info.X86_64_RELOC_UNSIGNED;
} else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) {
} else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
machORelocType = reloc_info.X86_64_RELOC_NONE;
} else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
machORelocType = reloc_info.X86_64_RELOC_GOT;
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
machORelocType = reloc_info.X86_64_RELOC_BRANCH;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) {
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
machORelocType = reloc_info.X86_64_RELOC_UNSIGNED;
} else {
assert false : "Unhandled relocation type: " + relocType;

View File

@ -23,10 +23,10 @@
package jdk.tools.jaotc.binformat.macho;
//@formatter:off
/**
*
* Support for the creation of Mach-o Object files.
* Current support is limited to 64 bit x86_64.
* Support for the creation of Mach-o Object files. Current support is limited to 64 bit x86_64.
*
* File Format Overview:
*
@ -38,12 +38,12 @@ package jdk.tools.jaotc.binformat.macho;
* (which each include multiple Sections)
*/
public class MachO {
final class MachO {
/**
* mach_header_64 structure defines
*/
public enum mach_header_64 {
enum mach_header_64 {
magic( 0, 4),
cputype( 4, 4),
cpusubtype( 8, 4),
@ -53,49 +53,49 @@ public class MachO {
flags(24, 4),
reserved(28, 4);
public final int off;
public final int sz;
final int off;
final int sz;
mach_header_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 32;
static int totalsize = 32;
/**
* mach_header_64 defines
*/
public static final int MH_MAGIC = 0xfeedface;
public static final int MH_MAGIC_64 = 0xfeedfacf;
public static final int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000;
static final int MH_MAGIC = 0xfeedface;
static final int MH_MAGIC_64 = 0xfeedfacf;
static final int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000;
/**
* filetype
*/
public static final int MH_OBJECT = 0x1;
static final int MH_OBJECT = 0x1;
/**
* cputype
*/
public static final int CPU_TYPE_ANY = -1;
public static final int CPU_ARCH_ABI64 = 0x1000000;
public static final int CPU_TYPE_X86_64 = 0x1000007;
public static final int CPU_TYPE_ARM64 = 0x100000c;
static final int CPU_TYPE_ANY = -1;
static final int CPU_ARCH_ABI64 = 0x1000000;
static final int CPU_TYPE_X86_64 = 0x1000007;
static final int CPU_TYPE_ARM64 = 0x100000c;
/**
* cpusubtype
*/
public static final int CPU_SUBTYPE_I386_ALL = 3;
public static final int CPU_SUBTYPE_ARM64_ALL = 0;
public static final int CPU_SUBTYPE_LITTLE_ENDIAN = 0;
public static final int CPU_SUBTYPE_BIG_ENDIAN = 1;
static final int CPU_SUBTYPE_I386_ALL = 3;
static final int CPU_SUBTYPE_ARM64_ALL = 0;
static final int CPU_SUBTYPE_LITTLE_ENDIAN = 0;
static final int CPU_SUBTYPE_BIG_ENDIAN = 1;
}
/**
* segment_command_64 structure defines
*/
public enum segment_command_64 {
enum segment_command_64 {
cmd( 0, 4),
cmdsize( 4, 4),
segname( 8,16),
@ -108,23 +108,23 @@ public class MachO {
nsects(64, 4),
flags(68, 4);
public final int off;
public final int sz;
final int off;
final int sz;
segment_command_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 72;
static int totalsize = 72;
public static final int LC_SEGMENT_64 = 0x19;
static final int LC_SEGMENT_64 = 0x19;
}
/**
* section_64 structure defines
*/
public enum section_64 {
enum section_64 {
sectname( 0,16),
segname(16,16),
addr(32, 8),
@ -138,49 +138,49 @@ public class MachO {
reserved2(72, 4),
reserved3(76, 4);
public final int off;
public final int sz;
final int off;
final int sz;
section_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 80;
static int totalsize = 80;
public static int S_REGULAR = 0x0;
public static int S_CSTRING_LITERALS = 0x2;
public static int S_ATTR_PURE_INSTRUCTIONS = 0x80000000;
public static int S_ATTR_SOME_INSTRUCTIONS = 0x400;
static int S_REGULAR = 0x0;
static int S_CSTRING_LITERALS = 0x2;
static int S_ATTR_PURE_INSTRUCTIONS = 0x80000000;
static int S_ATTR_SOME_INSTRUCTIONS = 0x400;
}
/**
* version_min_command structure defines
*/
public enum version_min_command {
enum version_min_command {
cmd( 0, 4),
cmdsize( 4, 4),
version( 8, 4),
sdk(12, 4);
public final int off;
public final int sz;
final int off;
final int sz;
version_min_command(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 16;
static int totalsize = 16;
public static final int LC_VERSION_MIN_MACOSX = 0x24;
public static final int LC_VERSION_MIN_IPHONEOS = 0x25;
static final int LC_VERSION_MIN_MACOSX = 0x24;
static final int LC_VERSION_MIN_IPHONEOS = 0x25;
}
/**
* symtab_command structure defines
*/
public enum symtab_command {
enum symtab_command {
cmd( 0, 4),
cmdsize( 4, 4),
symoff( 8, 4),
@ -188,17 +188,17 @@ public class MachO {
stroff(16, 4),
strsize(20, 4);
public final int off;
public final int sz;
final int off;
final int sz;
symtab_command(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 24;
static int totalsize = 24;
public static final int LC_SYMTAB = 0x2;
static final int LC_SYMTAB = 0x2;
}
/**
@ -206,33 +206,33 @@ public class MachO {
*
* nlist_64 structure defines
*/
public enum nlist_64 {
enum nlist_64 {
n_strx( 0, 4),
n_type( 4, 1),
n_sect( 5, 1),
n_desc( 6, 2),
n_value( 8, 8);
public final int off;
public final int sz;
final int off;
final int sz;
nlist_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 16;
static int totalsize = 16;
public static final int N_EXT = 0x1;
public static final int N_TYPE = 0xe;
public static final int N_UNDF = 0x0;
public static final int N_SECT = 0xe;
static final int N_EXT = 0x1;
static final int N_TYPE = 0xe;
static final int N_UNDF = 0x0;
static final int N_SECT = 0xe;
}
/**
* dysymtab_command structure defines
*/
public enum dysymtab_command {
enum dysymtab_command {
cmd( 0, 4),
cmdsize( 4, 4),
ilocalsym( 8, 4),
@ -254,54 +254,55 @@ public class MachO {
locreloff(72, 4),
nlocrel(76, 4);
public final int off;
public final int sz;
final int off;
final int sz;
dysymtab_command(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 80;
static int totalsize = 80;
public static final int LC_DYSYMTAB = 0xb;
static final int LC_DYSYMTAB = 0xb;
}
/**
* relocation_info structure defines
*/
public enum reloc_info {
enum reloc_info {
r_address( 0, 4),
r_relocinfo( 4, 4);
public final int off;
public final int sz;
final int off;
final int sz;
reloc_info(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 8;
static int totalsize = 8;
public static final int REL_SYMNUM_MASK = 0xffffff;
public static final int REL_SYMNUM_SHIFT = 0x0;
public static final int REL_PCREL_MASK = 0x1;
public static final int REL_PCREL_SHIFT = 0x18;
public static final int REL_LENGTH_MASK = 0x3;
public static final int REL_LENGTH_SHIFT = 0x19;
public static final int REL_EXTERN_MASK = 0x1;
public static final int REL_EXTERN_SHIFT = 0x1b;
public static final int REL_TYPE_MASK = 0xf;
public static final int REL_TYPE_SHIFT = 0x1c;
static final int REL_SYMNUM_MASK = 0xffffff;
static final int REL_SYMNUM_SHIFT = 0x0;
static final int REL_PCREL_MASK = 0x1;
static final int REL_PCREL_SHIFT = 0x18;
static final int REL_LENGTH_MASK = 0x3;
static final int REL_LENGTH_SHIFT = 0x19;
static final int REL_EXTERN_MASK = 0x1;
static final int REL_EXTERN_SHIFT = 0x1b;
static final int REL_TYPE_MASK = 0xf;
static final int REL_TYPE_SHIFT = 0x1c;
/* reloc_type_x86_64 defines */
public static final int X86_64_RELOC_NONE = 0x0;
public static final int X86_64_RELOC_BRANCH = 0x2;
public static final int X86_64_RELOC_GOT = 0x4;
public static final int X86_64_RELOC_GOT_LOAD = 0x3;
public static final int X86_64_RELOC_SIGNED = 0x1;
public static final int X86_64_RELOC_UNSIGNED = 0x0;
static final int X86_64_RELOC_NONE = 0x0;
static final int X86_64_RELOC_BRANCH = 0x2;
static final int X86_64_RELOC_GOT = 0x4;
static final int X86_64_RELOC_GOT_LOAD = 0x3;
static final int X86_64_RELOC_SIGNED = 0x1;
static final int X86_64_RELOC_UNSIGNED = 0x0;
}
}
//@formatter:on

View File

@ -23,21 +23,19 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachOTargetInfo;
import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
public class MachOByteBuffer {
final class MachOByteBuffer {
public static ByteBuffer allocate(int size) {
static ByteBuffer allocate(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
if (MachOTargetInfo.getMachOEndian() ==
MachO.mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN)
if (MachOTargetInfo.getMachOEndian() == MachO.mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN) {
buf.order(ByteOrder.LITTLE_ENDIAN);
else
} else {
buf.order(ByteOrder.BIG_ENDIAN);
}
return (buf);
}

View File

@ -26,14 +26,13 @@ package jdk.tools.jaotc.binformat.macho;
import java.io.File;
import java.io.FileOutputStream;
public class MachOContainer {
final class MachOContainer {
File outputFile;
FileOutputStream outputStream;
long fileOffset;
private final File outputFile;
private FileOutputStream outputStream;
private long fileOffset;
public MachOContainer(String fileName) {
String baseName;
MachOContainer(String fileName) {
outputFile = new File(fileName);
if (outputFile.exists()) {
@ -48,7 +47,7 @@ public class MachOContainer {
fileOffset = 0;
}
public void close() {
void close() {
try {
outputStream.close();
} catch (Exception e) {
@ -56,7 +55,7 @@ public class MachOContainer {
}
}
public void writeBytes(byte [] bytes) {
void writeBytes(byte[] bytes) {
try {
outputStream.write(bytes);
} catch (Exception e) {
@ -66,10 +65,10 @@ public class MachOContainer {
}
// Write bytes to output file with up front alignment padding
public void writeBytes(byte [] bytes, int alignment) {
void writeBytes(byte[] bytes, int alignment) {
try {
// Pad to alignment
while ((fileOffset & (long)(alignment-1)) != 0) {
while ((fileOffset & (alignment - 1)) != 0) {
outputStream.write(0);
fileOffset++;
}
@ -80,4 +79,3 @@ public class MachOContainer {
fileOffset += bytes.length;
}
}

View File

@ -24,16 +24,14 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachODySymtab {
ByteBuffer dysymtab;
final class MachODySymtab {
private final ByteBuffer dysymtab;
public MachODySymtab(int nlocal, int nglobal, int nundef) {
MachODySymtab(int nlocal, int nglobal, int nundef) {
dysymtab = MachOByteBuffer.allocate(dysymtab_command.totalsize);
dysymtab.putInt(dysymtab_command.cmd.off, dysymtab_command.LC_DYSYMTAB);
@ -42,13 +40,11 @@ public class MachODySymtab {
dysymtab.putInt(dysymtab_command.nlocalsym.off, nlocal);
dysymtab.putInt(dysymtab_command.iextdefsym.off, nlocal);
dysymtab.putInt(dysymtab_command.nextdefsym.off, nglobal);
dysymtab.putInt(dysymtab_command.iundefsym.off, nlocal+nglobal);
dysymtab.putInt(dysymtab_command.iundefsym.off, nlocal + nglobal);
dysymtab.putInt(dysymtab_command.nundefsym.off, nundef);
}
public byte[] getArray() {
byte[] getArray() {
return dysymtab.array();
}
}

View File

@ -24,17 +24,15 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
import jdk.tools.jaotc.binformat.macho.MachOTargetInfo;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachOHeader {
ByteBuffer header;
final class MachOHeader {
private final ByteBuffer header;
public MachOHeader() {
MachOHeader() {
header = MachOByteBuffer.allocate(mach_header_64.totalsize);
header.putInt(mach_header_64.magic.off, mach_header_64.MH_MAGIC_64);
@ -44,17 +42,16 @@ public class MachOHeader {
header.putInt(mach_header_64.filetype.off, mach_header_64.MH_OBJECT);
}
public void setCmdSizes(int ncmds, int sizeofcmds) {
void setCmdSizes(int ncmds, int sizeofcmds) {
header.putInt(mach_header_64.ncmds.off, ncmds);
header.putInt(mach_header_64.sizeofcmds.off, sizeofcmds);
}
public int getCmdSize() {
int getCmdSize() {
return (header.getInt(mach_header_64.sizeofcmds.off));
}
public byte[] getArray() {
byte[] getArray() {
return header.array();
}
}

View File

@ -24,42 +24,31 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachORelocEntry {
ByteBuffer entry;
final class MachORelocEntry {
private final ByteBuffer entry;
public MachORelocEntry(int offset,
int symno,
int pcrel,
int length,
int isextern,
int type) {
MachORelocEntry(int offset, int symno, int pcrel, int length, int isextern, int type) {
entry = MachOByteBuffer.allocate(reloc_info.totalsize);
entry.putInt(reloc_info.r_address.off, offset);
// Encode and store the relocation entry bitfields
// @formatter:off
entry.putInt(reloc_info.r_relocinfo.off,
((symno & reloc_info.REL_SYMNUM_MASK)
<< reloc_info.REL_SYMNUM_SHIFT) |
((pcrel & reloc_info.REL_PCREL_MASK)
<< reloc_info.REL_PCREL_SHIFT) |
((length & reloc_info.REL_LENGTH_MASK)
<< reloc_info.REL_LENGTH_SHIFT) |
((isextern & reloc_info.REL_EXTERN_MASK)
<< reloc_info.REL_EXTERN_SHIFT) |
((type & reloc_info.REL_TYPE_MASK)
<< reloc_info.REL_TYPE_SHIFT));
((symno & reloc_info.REL_SYMNUM_MASK) << reloc_info.REL_SYMNUM_SHIFT) |
((pcrel & reloc_info.REL_PCREL_MASK) << reloc_info.REL_PCREL_SHIFT) |
((length & reloc_info.REL_LENGTH_MASK) << reloc_info.REL_LENGTH_SHIFT) |
((isextern & reloc_info.REL_EXTERN_MASK) << reloc_info.REL_EXTERN_SHIFT) |
((type & reloc_info.REL_TYPE_MASK) << reloc_info.REL_TYPE_SHIFT));
// @formatter:on
}
public byte[] getArray() {
byte[] getArray() {
return entry.array();
}
}

View File

@ -25,56 +25,43 @@ package jdk.tools.jaotc.binformat.macho;
import java.util.ArrayList;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachORelocEntry;
import jdk.tools.jaotc.binformat.macho.MachOTargetInfo;
import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachORelocTable {
ArrayList<ArrayList<MachORelocEntry>> relocEntries;
final class MachORelocTable {
private final ArrayList<ArrayList<MachORelocEntry>> relocEntries;
int fileOffset;
public MachORelocTable(int numsects) {
relocEntries = new ArrayList<ArrayList<MachORelocEntry>>(numsects);
for (int i = 0; i < numsects; i++)
MachORelocTable(int numsects) {
relocEntries = new ArrayList<>(numsects);
for (int i = 0; i < numsects; i++) {
relocEntries.add(new ArrayList<MachORelocEntry>());
}
}
public void createRelocationEntry(int sectindex,
int offset,
int symno,
int pcrel,
int length,
int isextern,
int type) {
MachORelocEntry entry = new MachORelocEntry(offset,
symno,
pcrel,
length,
isextern,
type);
void createRelocationEntry(int sectindex, int offset, int symno, int pcrel, int length, int isextern, int type) {
MachORelocEntry entry = new MachORelocEntry(offset, symno, pcrel, length, isextern, type);
relocEntries.get(sectindex).add(entry);
}
public int getAlign() {
static int getAlign() {
return (4);
}
public int getNumRelocs(int section_index) {
int getNumRelocs(int section_index) {
return relocEntries.get(section_index).size();
}
// Return the relocation entries for a single section
// or null if no entries added to section
public byte [] getRelocData(int section_index) {
// or null if no entries added to section
byte[] getRelocData(int section_index) {
ArrayList<MachORelocEntry> entryList = relocEntries.get(section_index);
if (entryList.size() == 0)
if (entryList.size() == 0) {
return null;
}
ByteBuffer relocData = MachOByteBuffer.allocate(entryList.size() * reloc_info.totalsize);
// Copy each entry to a single ByteBuffer
@ -86,4 +73,3 @@ public class MachORelocTable {
return (relocData.array());
}
}

View File

@ -24,41 +24,36 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.section_64;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachOSection {
ByteBuffer section;
byte [] data;
boolean hasrelocations;
final class MachOSection {
private final ByteBuffer section;
private final byte[] data;
private final boolean hasrelocations;
public MachOSection(String sectName, String segName, byte [] sectData, int sectFlags, boolean hasRelocations, int align) {
MachOSection(String sectName, String segName, byte[] sectData, int sectFlags, boolean hasRelocations, int align) {
section = MachOByteBuffer.allocate(section_64.totalsize);
// TODO: Hotspot uses long section names.
// They are getting truncated.
// Is this a problem??
// They are getting truncated.
// Is this a problem??
byte[] sectNameBytes = sectName.getBytes();
int sectNameMax = section_64.sectname.sz < sectNameBytes.length ?
section_64.sectname.sz : sectNameBytes.length;
for (int i = 0; i < sectNameMax; i++)
section.put(section_64.sectname.off+i, sectNameBytes[i]);
int sectNameMax = section_64.sectname.sz < sectNameBytes.length ? section_64.sectname.sz : sectNameBytes.length;
for (int i = 0; i < sectNameMax; i++) {
section.put(section_64.sectname.off + i, sectNameBytes[i]);
}
byte[] segNameBytes = segName.getBytes();
int segNameMax = section_64.segname.sz < segNameBytes.length ?
section_64.segname.sz : segNameBytes.length;
for (int i = 0; i < segNameMax; i++)
section.put(section_64.segname.off+i, segNameBytes[i]);
int segNameMax = section_64.segname.sz < segNameBytes.length ? section_64.segname.sz : segNameBytes.length;
for (int i = 0; i < segNameMax; i++) {
section.put(section_64.segname.off + i, segNameBytes[i]);
}
section.putLong(section_64.size.off, sectData.length);
section.putInt(section_64.align.off,
31 - Integer.numberOfLeadingZeros(align));
section.putInt(section_64.align.off, 31 - Integer.numberOfLeadingZeros(align));
section.putInt(section_64.flags.off, sectFlags);
@ -67,49 +62,47 @@ public class MachOSection {
hasrelocations = hasRelocations;
}
public long getSize() {
long getSize() {
return section.getLong(section_64.size.off);
}
public int getAlign() {
int getAlign() {
return (1 << section.getInt(section_64.align.off));
}
public byte[] getArray() {
byte[] getArray() {
return section.array();
}
public byte[] getDataArray() {
byte[] getDataArray() {
return data;
}
public void setAddr(long addr) {
void setAddr(long addr) {
section.putLong(section_64.addr.off, addr);
}
public long getAddr() {
long getAddr() {
return (section.getLong(section_64.addr.off));
}
public void setOffset(int offset) {
void setOffset(int offset) {
section.putInt(section_64.offset.off, offset);
}
public int getOffset() {
int getOffset() {
return (section.getInt(section_64.offset.off));
}
public void setReloff(int offset) {
void setReloff(int offset) {
section.putInt(section_64.reloff.off, offset);
}
public void setRelcount(int count) {
void setRelcount(int count) {
section.putInt(section_64.nreloc.off, count);
}
public boolean hasRelocations() {
boolean hasRelocations() {
return hasrelocations;
}
}

View File

@ -24,9 +24,7 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
@ -52,5 +50,3 @@ public class MachOSegment {
return segment.array();
}
}

View File

@ -24,17 +24,15 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachOSymbol extends NativeSymbol {
ByteBuffer sym;
final class MachOSymbol extends NativeSymbol {
private final ByteBuffer sym;
public MachOSymbol(int symbolindex, int strindex, byte type, byte sectindex, long offset) {
MachOSymbol(int symbolindex, int strindex, byte type, byte sectindex, long offset) {
super(symbolindex);
sym = MachOByteBuffer.allocate(nlist_64.totalsize);
@ -42,13 +40,12 @@ public class MachOSymbol extends NativeSymbol {
sym.put(nlist_64.n_type.off, type);
// Section indexes start at 1 but we manage the index internally
// as 0 relative
sym.put(nlist_64.n_sect.off, (byte)(sectindex+1));
sym.putChar(nlist_64.n_desc.off, (char )0);
sym.put(nlist_64.n_sect.off, (byte) (sectindex + 1));
sym.putChar(nlist_64.n_desc.off, (char) 0);
sym.putLong(nlist_64.n_value.off, offset);
}
public byte[] getArray() {
byte[] getArray() {
return sym.array();
}
}

View File

@ -24,50 +24,42 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.symtab_command;
import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
import jdk.tools.jaotc.binformat.macho.MachOSymbol;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachOSymtab {
final class MachOSymtab {
/**
* ByteBuffer holding the LC_SYMTAB command contents
*/
ByteBuffer symtabCmd;
private final ByteBuffer symtabCmd;
/**
* ByteBuffer holding the symbol table entries and strings
*/
ByteBuffer symtabData;
private int symtabDataSize;
int symtabDataSize;
ArrayList<MachOSymbol>localSymbols = new ArrayList<MachOSymbol>();
ArrayList<MachOSymbol>globalSymbols = new ArrayList<MachOSymbol>();
ArrayList<MachOSymbol>undefSymbols = new ArrayList<MachOSymbol>();
private final ArrayList<MachOSymbol> localSymbols = new ArrayList<>();
private final ArrayList<MachOSymbol> globalSymbols = new ArrayList<>();
private final ArrayList<MachOSymbol> undefSymbols = new ArrayList<>();
/**
* number of symbols added
*/
int symbolCount;
private int symbolCount;
/**
* String holding symbol table strings
*/
private StringBuilder strTabContent = new StringBuilder();
private final StringBuilder strTabContent = new StringBuilder();
/**
* Keeps track of bytes in string table since strTabContent.length()
* is number of chars, not bytes.
* Keeps track of bytes in string table since strTabContent.length() is number of chars, not bytes.
*/
private int strTabNrOfBytes = 0;
public MachOSymtab() {
MachOSymtab() {
symtabCmd = MachOByteBuffer.allocate(symtab_command.totalsize);
symtabCmd.putInt(symtab_command.cmd.off, symtab_command.LC_SYMTAB);
@ -77,11 +69,11 @@ public class MachOSymtab {
}
public int getAlign() {
static int getAlign() {
return (4);
}
public MachOSymbol addSymbolEntry(String name, byte type, byte secHdrIndex, long offset) {
MachOSymbol addSymbolEntry(String name, byte type, byte secHdrIndex, long offset) {
// Get the current symbol index and append symbol name to string table.
int index;
MachOSymbol sym;
@ -109,7 +101,7 @@ public class MachOSymtab {
case nlist_64.N_UNDF: // null symbol
localSymbols.add(sym);
break;
case nlist_64.N_SECT|nlist_64.N_EXT:
case nlist_64.N_SECT | nlist_64.N_EXT:
globalSymbols.add(sym);
break;
default:
@ -121,30 +113,30 @@ public class MachOSymtab {
return (sym);
}
public void setOffset(int symoff) {
void setOffset(int symoff) {
symtabCmd.putInt(symtab_command.symoff.off, symoff);
}
// Update the symbol indexes once all symbols have been added.
// This is required since we'll be reordering the symbols in the
// file to be in the order of Local, global and Undefined.
public void updateIndexes() {
void updateIndexes() {
int index = 0;
// Update the local symbol indexes
for (int i = 0; i < localSymbols.size(); i++ ) {
for (int i = 0; i < localSymbols.size(); i++) {
MachOSymbol sym = localSymbols.get(i);
sym.setIndex(index++);
}
// Update the global symbol indexes
for (int i = 0; i < globalSymbols.size(); i++ ) {
for (int i = 0; i < globalSymbols.size(); i++) {
MachOSymbol sym = globalSymbols.get(i);
sym.setIndex(index++);
}
// Update the undefined symbol indexes
for (int i = index; i < undefSymbols.size(); i++ ) {
for (int i = index; i < undefSymbols.size(); i++) {
MachOSymbol sym = undefSymbols.get(i);
sym.setIndex(index++);
}
@ -152,7 +144,7 @@ public class MachOSymtab {
// Update LC_SYMTAB command fields based on the number of symbols added
// return the file size taken up by symbol table entries and strings
public int calcSizes() {
int calcSizes() {
int stroff;
stroff = symtabCmd.getInt(symtab_command.symoff.off) + (nlist_64.totalsize * symbolCount);
@ -164,42 +156,49 @@ public class MachOSymtab {
return (symtabDataSize);
}
public int getNumLocalSyms() { return localSymbols.size(); }
public int getNumGlobalSyms() { return globalSymbols.size(); }
public int getNumUndefSyms() { return undefSymbols.size(); }
int getNumLocalSyms() {
return localSymbols.size();
}
public byte[] getCmdArray() {
int getNumGlobalSyms() {
return globalSymbols.size();
}
int getNumUndefSyms() {
return undefSymbols.size();
}
byte[] getCmdArray() {
return symtabCmd.array();
}
// Create a single byte array that contains the symbol table entries
// and string table
public byte[] getDataArray() {
int index = 0;
symtabData = MachOByteBuffer.allocate(symtabDataSize);
byte [] retarray;
byte[] getDataArray() {
ByteBuffer symtabData = MachOByteBuffer.allocate(symtabDataSize);
byte[] retarray;
// Add the local symbols
for (int i = 0; i < localSymbols.size(); i++ ) {
for (int i = 0; i < localSymbols.size(); i++) {
MachOSymbol sym = localSymbols.get(i);
byte [] arr = sym.getArray();
byte[] arr = sym.getArray();
symtabData.put(arr);
}
// Add the global symbols
for (int i = 0; i < globalSymbols.size(); i++ ) {
for (int i = 0; i < globalSymbols.size(); i++) {
MachOSymbol sym = globalSymbols.get(i);
byte [] arr = sym.getArray();
byte[] arr = sym.getArray();
symtabData.put(arr);
}
// Add the undefined symbols
for (int i = 0; i < undefSymbols.size(); i++ ) {
for (int i = 0; i < undefSymbols.size(); i++) {
MachOSymbol sym = undefSymbols.get(i);
byte [] arr = sym.getArray();
byte[] arr = sym.getArray();
symtabData.put(arr);
}
// Add the stringtable
byte [] strs = strTabContent.toString().getBytes();
byte[] strs = strTabContent.toString().getBytes();
symtabData.put(strs);
retarray = symtabData.array();
@ -207,5 +206,3 @@ public class MachOSymtab {
return (retarray);
}
}

View File

@ -24,14 +24,13 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64;
/**
* Class that abstracts MACH-O target details.
*
*/
public class MachOTargetInfo {
final class MachOTargetInfo {
/**
* Target architecture and subtype.
*/
@ -68,20 +67,19 @@ public class MachOTargetInfo {
osName = System.getProperty("os.name").toLowerCase();
}
public static int getMachOArch() {
static int getMachOArch() {
return arch;
}
public static int getMachOSubArch() {
static int getMachOSubArch() {
return subarch;
}
public static int getMachOEndian() {
static int getMachOEndian() {
return endian;
}
public static String getOsName() {
static String getOsName() {
return osName;
}
}

View File

@ -24,16 +24,14 @@
package jdk.tools.jaotc.binformat.macho;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.macho.MachO;
import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachOVersion {
ByteBuffer version;
final class MachOVersion {
private final ByteBuffer version;
public MachOVersion() {
MachOVersion() {
version = MachOByteBuffer.allocate(version_min_command.totalsize);
version.putInt(version_min_command.cmd.off, version_min_command.LC_VERSION_MIN_MACOSX);
@ -42,8 +40,7 @@ public class MachOVersion {
version.putInt(version_min_command.sdk.off, 0); /* N/A SDK */
}
public byte[] getArray() {
byte[] getArray() {
return version.array();
}
}

View File

@ -24,13 +24,11 @@
package jdk.tools.jaotc.binformat.pecoff;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import jdk.tools.jaotc.binformat.Container;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.CodeContainer;
@ -38,11 +36,9 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Relocation;
import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol;
import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
@ -56,71 +52,53 @@ public class JPECoffRelocObject {
private final PECoffContainer pecoffContainer;
private final int segmentSize;
private final int sectionAlignment;
public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName) {
this.binContainer = binContainer;
this.pecoffContainer = new PECoffContainer(outputFileName, aotVersion);
this.segmentSize = binContainer.getCodeSegmentSize();
if (segmentSize != 64) {
System.out.println("binContainer alignment size not 64 bytes, update JPECoffRelocObject");
}
this.pecoffContainer = new PECoffContainer(outputFileName);
this.sectionAlignment = binContainer.getCodeSegmentSize();
}
private PECoffSection createByteSection(ArrayList<PECoffSection>sections,
String sectName,
byte [] scnData,
boolean hasRelocs,
int scnFlags) {
private static PECoffSection createByteSection(ArrayList<PECoffSection> sections, String sectName, byte[] scnData,
boolean hasRelocs, int scnFlags, int sectAlign) {
PECoffSection sect = new PECoffSection(sectName,
scnData,
scnFlags,
hasRelocs,
sections.size());
PECoffSection sect = new PECoffSection(sectName, scnData, scnFlags, sectAlign, hasRelocs, sections.size());
// Add this section to our list
sections.add(sect);
return (sect);
}
private void createByteSection(ArrayList<PECoffSection>sections,
ByteContainer c, int scnFlags) {
private static void createByteSection(ArrayList<PECoffSection> sections, ByteContainer c, int scnFlags, int sectAlign) {
PECoffSection sect;
boolean hasRelocs = c.hasRelocations();
byte[] scnData = c.getByteArray();
sect = createByteSection(sections, c.getContainerName(),
scnData, hasRelocs,
scnFlags);
sect = createByteSection(sections, c.getContainerName(), scnData, hasRelocs, scnFlags, sectAlign);
c.setSectionId(sect.getSectionId());
}
private void createCodeSection(ArrayList<PECoffSection>sections, CodeContainer c) {
createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE |
IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES |
IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE);
private void createCodeSection(ArrayList<PECoffSection> sections, CodeContainer c) {
int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE | IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE;
createByteSection(sections, c, scnFlags, sectionAlignment);
}
private void createReadOnlySection(ArrayList<PECoffSection>sections, ReadOnlyDataContainer c) {
createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES |
IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA);
private void createReadOnlySection(ArrayList<PECoffSection> sections, ReadOnlyDataContainer c) {
int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
createByteSection(sections, c, scnFlags, sectionAlignment);
}
private void createReadWriteSection(ArrayList<PECoffSection>sections, ByteContainer c) {
int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE |
IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES;
private void createReadWriteSection(ArrayList<PECoffSection> sections, ByteContainer c) {
int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE;
if (c.getByteArray().length > 0)
if (c.getByteArray().length > 0) {
scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
else
} else {
scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA;
createByteSection(sections, c, scnFlags);
}
createByteSection(sections, c, scnFlags, sectionAlignment);
}
/**
@ -131,7 +109,7 @@ public class JPECoffRelocObject {
* @throws IOException throws {@code IOException} as a result of file system access failures.
*/
public void createPECoffRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
ArrayList<PECoffSection> sections = new ArrayList<PECoffSection>();
ArrayList<PECoffSection> sections = new ArrayList<>();
// Create text section
createCodeSection(sections, binContainer.getCodeContainer());
@ -139,51 +117,45 @@ public class JPECoffRelocObject {
createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
createReadWriteSection(sections, binContainer.getMetaspaceGotContainer());
createReadWriteSection(sections, binContainer.getMetadataGotContainer());
createReadWriteSection(sections, binContainer.getMethodStateContainer());
createReadWriteSection(sections, binContainer.getOopGotContainer());
createReadWriteSection(sections, binContainer.getMethodMetadataContainer());
createReadOnlySection(sections, binContainer.getMethodMetadataContainer());
createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
createReadOnlySection(sections, binContainer.getConstantDataContainer());
createReadOnlySection(sections, binContainer.getConfigContainer());
// createExternalLinkage();
createCodeSection(sections, binContainer.getExtLinkageContainer());
createReadWriteSection(sections, binContainer.getKlassesGotContainer());
createReadWriteSection(sections, binContainer.getCountersGotContainer());
createReadWriteSection(sections, binContainer.getMetadataGotContainer());
createReadWriteSection(sections, binContainer.getMethodStateContainer());
createReadWriteSection(sections, binContainer.getOopGotContainer());
createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
// Allocate PECoff Header
PECoffHeader header = new PECoffHeader();
// Get PECoff symbol data from BinaryContainer object's symbol tables
PECoffSymtab symtab = createPECoffSymbolTables(sections, symbols);
PECoffSymtab symtab = createPECoffSymbolTables(symbols);
// Add Linker Directives Section
createByteSection(sections, ".drectve",
symtab.getDirectiveArray(), false,
IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO |
IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE |
IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_1BYTES);
int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO | IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE;
createByteSection(sections, ".drectve", symtab.getDirectiveArray(), false, scnFlags, 1 /* 1 byte alignment */);
// Create the Relocation Tables
PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable);
// File Output Order
//
// HEADER (Need address of Symbol Table + symbol count)
// SECTIONS (Need pointer to Section Data, Relocation Table)
// DIRECTIVES
// SYMBOL TABLE
// SYMBOLS
// SECTION DATA
// RELOCATION TABLE
// HEADER (Need address of Symbol Table + symbol count)
// SECTIONS (Need pointer to Section Data, Relocation Table)
// DIRECTIVES
// SYMBOL TABLE
// SYMBOLS
// SECTION DATA
// RELOCATION TABLE
// Calculate Offset for Symbol table
int file_offset = IMAGE_FILE_HEADER.totalsize +
(IMAGE_SECTION_HEADER.totalsize*sections.size());
(IMAGE_SECTION_HEADER.totalsize * sections.size());
// Update Header fields
header.setSectionCount(sections.size());
@ -194,14 +166,14 @@ public class JPECoffRelocObject {
file_offset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) +
symtab.getStrtabSize());
// And round it up
file_offset = (file_offset + (sections.get(0).getDataAlign()-1)) &
~((sections.get(0).getDataAlign()-1));
file_offset = (file_offset + (sections.get(0).getDataAlign() - 1)) &
~((sections.get(0).getDataAlign() - 1));
// Calc file offsets for section data
for (int i = 0; i < sections.size(); i++) {
PECoffSection sect = sections.get(i);
file_offset = (file_offset + (sect.getDataAlign()-1)) &
~((sect.getDataAlign()-1));
file_offset = (file_offset + (sect.getDataAlign() - 1)) &
~((sect.getDataAlign() - 1));
sect.setOffset(file_offset);
file_offset += sect.getSize();
}
@ -214,7 +186,9 @@ public class JPECoffRelocObject {
sect.setReloff(file_offset);
sect.setRelcount(nreloc);
// extended relocations add an addition entry
if (nreloc > 0xFFFF) nreloc++;
if (nreloc > 0xFFFF) {
nreloc++;
}
file_offset += (nreloc * IMAGE_RELOCATION.totalsize);
}
}
@ -253,7 +227,7 @@ public class JPECoffRelocObject {
*
* @param symbols
*/
private PECoffSymtab createPECoffSymbolTables(ArrayList<PECoffSection> sections, Collection<Symbol> symbols) {
private static PECoffSymtab createPECoffSymbolTables(Collection<Symbol> symbols) {
PECoffSymtab symtab = new PECoffSymtab();
// First, create the initial null symbol. This is a local symbol.
@ -263,8 +237,8 @@ public class JPECoffRelocObject {
for (Symbol symbol : symbols) {
// Get the index of section this symbol is defined in.
int secHdrIndex = symbol.getSection().getSectionId();
PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize());
symbol.setNativeSymbol((NativeSymbol)pecoffSymbol);
PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte) secHdrIndex, symbol.getOffset());
symbol.setNativeSymbol(pecoffSymbol);
}
return (symtab);
}
@ -291,13 +265,11 @@ public class JPECoffRelocObject {
* @param sections
* @param relocationTable
*/
private PECoffRelocTable createPECoffRelocTable(ArrayList<PECoffSection> sections,
Map<Symbol, List<Relocation>> relocationTable) {
private PECoffRelocTable createPECoffRelocTable(ArrayList<PECoffSection> sections, Map<Symbol, List<Relocation>> relocationTable) {
PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size());
/*
* For each of the symbols with associated relocation records, create a PECoff relocation
* entry.
* For each of the symbols with associated relocation records, create a PECoff relocation entry.
*/
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
List<Relocation> relocs = entry.getValue();
@ -315,18 +287,17 @@ public class JPECoffRelocObject {
return (pecoffRelocTable);
}
private void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) {
private static void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) {
RelocType relocType = reloc.getType();
int pecoffRelocType = getPECoffRelocationType(relocType);
PECoffSymbol sym = (PECoffSymbol)symbol.getNativeSymbol();
PECoffSymbol sym = (PECoffSymbol) symbol.getNativeSymbol();
int symno = sym.getIndex();
int sectindex = reloc.getSection().getSectionId();
int offset = reloc.getOffset();
int addend = 0;
switch (relocType) {
case FOREIGN_CALL_DIRECT:
case JAVA_CALL_DIRECT:
case STUB_CALL_DIRECT:
case FOREIGN_CALL_INDIRECT_GOT: {
@ -336,47 +307,22 @@ public class JPECoffRelocObject {
offset = offset + reloc.getSize() + addend;
break;
}
case FOREIGN_CALL_DIRECT_FAR: {
// Create relocation entry
addend = -8; // Size in bytes of the patch location
// Relocation should be applied at the location after call operand
// 10 = 2 (jmp [r]) + 8 (imm64)
offset = offset + reloc.getSize() + addend - 2;
break;
}
case FOREIGN_CALL_INDIRECT:
case JAVA_CALL_INDIRECT:
case STUB_CALL_INDIRECT: {
case JAVA_CALL_INDIRECT: {
// Do nothing.
return;
}
case EXTERNAL_DATA_REFERENCE_FAR: {
// Create relocation entry
case METASPACE_GOT_REFERENCE:
case EXTERNAL_PLT_TO_GOT: {
addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to the move instruction.
* offset points to the test instruction after the instruction that loads
* the address of polling page. So set the offset appropriately.
* reloc.getOffset() points to the test instruction after the instruction that loads the address of
* polling page. So set the offset appropriately.
*/
offset = offset + addend;
break;
}
case METASPACE_GOT_REFERENCE:
case EXTERNAL_PLT_TO_GOT:
case STATIC_STUB_TO_STATIC_METHOD:
case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: {
addend = -4; // Size of 32-bit address of the GOT
/*
* Relocation should be applied before the test instruction to
* the move instruction. reloc.getOffset() points to the
* test instruction after the instruction that loads the
* address of polling page. So set the offset appropriately.
*/
offset = offset + addend;
break;
}
case EXTERNAL_GOT_TO_PLT:
case LOADTIME_ADDRESS: {
case EXTERNAL_GOT_TO_PLT: {
// this is load time relocations
break;
}
@ -391,27 +337,17 @@ public class JPECoffRelocObject {
int pecoffRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
switch (PECoffTargetInfo.getPECoffArch()) {
case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
if (relocType == RelocType.FOREIGN_CALL_DIRECT ||
relocType == RelocType.JAVA_CALL_DIRECT ||
if (relocType == RelocType.JAVA_CALL_DIRECT ||
relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.STUB_CALL_DIRECT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
} else if (relocType == RelocType.FOREIGN_CALL_INDIRECT ||
relocType == RelocType.JAVA_CALL_INDIRECT ||
relocType == RelocType.STUB_CALL_INDIRECT) {
} else if (relocType == RelocType.JAVA_CALL_INDIRECT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE;
} else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
relocType == RelocType.EXTERNAL_PLT_TO_GOT ||
relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
relocType == RelocType.EXTERNAL_PLT_TO_GOT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT ||
relocType == RelocType.LOADTIME_ADDRESS) {
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
} else {
assert false : "Unhandled relocation type: " + relocType;

View File

@ -25,17 +25,16 @@ package jdk.tools.jaotc.binformat.pecoff;
/**
*
* Support for the creation of Coff files.
* Current support is limited to 64 bit x86_64.
* Support for the creation of Coff files. Current support is limited to 64 bit x86_64.
*
*/
public class PECoff {
final class PECoff {
//@formatter:off
/**
* IMAGE_FILE_HEADER structure defines
*/
public enum IMAGE_FILE_HEADER {
enum IMAGE_FILE_HEADER {
Machine( 0, 2),
NumberOfSections( 2, 2),
TimeDateStamp( 4, 4),
@ -44,15 +43,15 @@ public class PECoff {
SizeOfOptionalHeader(16, 2),
Characteristics(18, 2);
public final int off;
public final int sz;
final int off;
final int sz;
IMAGE_FILE_HEADER(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 20;
static int totalsize = 20;
/**
* IMAGE_FILE_HEADER defines
@ -61,15 +60,15 @@ public class PECoff {
/**
* Machine
*/
public static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
public static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664;
static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664;
}
/**
* IMAGE_SECTION_HEADER structure defines
*/
public enum IMAGE_SECTION_HEADER {
enum IMAGE_SECTION_HEADER {
Name( 0, 8),
PhysicalAddress( 8, 4),
VirtualSize( 8, 4),
@ -82,15 +81,15 @@ public class PECoff {
NumberOfLinenumbers(34, 2),
Characteristics(36, 4);
public final int off;
public final int sz;
final int off;
final int sz;
IMAGE_SECTION_HEADER(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 40;
static int totalsize = 40;
/**
* IMAGE_SECTION_HEADER defines
@ -99,29 +98,33 @@ public class PECoff {
/**
* Characteristics
*/
public static final int IMAGE_SCN_CNT_CODE = 0x20;
public static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40;
public static final int IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x80;
public static final int IMAGE_SCN_LNK_COMDAT = 0x1000;
public static final int IMAGE_SCN_LNK_INFO = 0x200;
public static final int IMAGE_SCN_LNK_REMOVE = 0x800;
static final int IMAGE_SCN_CNT_CODE = 0x20;
static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40;
static final int IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x80;
static final int IMAGE_SCN_LNK_COMDAT = 0x1000;
static final int IMAGE_SCN_LNK_INFO = 0x200;
static final int IMAGE_SCN_LNK_REMOVE = 0x800;
public static final int IMAGE_SCN_ALIGN_1BYTES = 0x100000;
public static final int IMAGE_SCN_ALIGN_2BYTES = 0x200000;
public static final int IMAGE_SCN_ALIGN_4BYTES = 0x300000;
public static final int IMAGE_SCN_ALIGN_8BYTES = 0x400000;
public static final int IMAGE_SCN_ALIGN_16BYTES = 0x500000;
public static final int IMAGE_SCN_ALIGN_32BYTES = 0x600000;
public static final int IMAGE_SCN_ALIGN_64BYTES = 0x700000;
public static final int IMAGE_SCN_ALIGN_MASK = 0xf00000;
public static final int IMAGE_SCN_ALIGN_SHIFT = 20;
static final int IMAGE_SCN_ALIGN_1BYTES = 0x100000;
static final int IMAGE_SCN_ALIGN_2BYTES = 0x200000;
static final int IMAGE_SCN_ALIGN_4BYTES = 0x300000;
static final int IMAGE_SCN_ALIGN_8BYTES = 0x400000;
static final int IMAGE_SCN_ALIGN_16BYTES = 0x500000;
static final int IMAGE_SCN_ALIGN_32BYTES = 0x600000;
static final int IMAGE_SCN_ALIGN_64BYTES = 0x700000;
static final int IMAGE_SCN_ALIGN_128BYTES = 0x800000;
static final int IMAGE_SCN_ALIGN_256BYTES = 0x900000;
static final int IMAGE_SCN_ALIGN_512BYTES = 0xa00000;
static final int IMAGE_SCN_ALIGN_1024BYTES = 0xb00000;
static final int IMAGE_SCN_ALIGN_MASK = 0xf00000;
static final int IMAGE_SCN_ALIGN_SHIFT = 20;
public static final int IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000;
static final int IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000;
public static final int IMAGE_SCN_MEM_SHARED = 0x10000000;
public static final int IMAGE_SCN_MEM_EXECUTE = 0x20000000;
public static final int IMAGE_SCN_MEM_READ = 0x40000000;
public static final int IMAGE_SCN_MEM_WRITE = 0x80000000;
static final int IMAGE_SCN_MEM_SHARED = 0x10000000;
static final int IMAGE_SCN_MEM_EXECUTE = 0x20000000;
static final int IMAGE_SCN_MEM_READ = 0x40000000;
static final int IMAGE_SCN_MEM_WRITE = 0x80000000;
}
@ -130,7 +133,7 @@ public class PECoff {
*
* IMAGE_SYMBOL structure defines
*/
public enum IMAGE_SYMBOL {
enum IMAGE_SYMBOL {
ShortName( 0, 8),
Short( 0, 4),
Long( 4, 4),
@ -140,63 +143,63 @@ public class PECoff {
StorageClass(16, 1),
NumberOfAuxSymbols(17, 1);
public final int off;
public final int sz;
final int off;
final int sz;
IMAGE_SYMBOL(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 18;
static int totalsize = 18;
/**
* Type
*/
public static final int IMAGE_SYM_DTYPE_NONE = 0x0;
public static final int IMAGE_SYM_DTYPE_FUNCTION = 0x20;
static final int IMAGE_SYM_DTYPE_NONE = 0x0;
static final int IMAGE_SYM_DTYPE_FUNCTION = 0x20;
/**
* StorageClass
*/
public static final int IMAGE_SYM_CLASS_NULL = 0x0;
public static final int IMAGE_SYM_CLASS_EXTERNAL = 0x2;
public static final int IMAGE_SYM_CLASS_STATIC = 0x3;
public static final int IMAGE_SYM_CLASS_LABEL = 0x6;
static final int IMAGE_SYM_CLASS_NULL = 0x0;
static final int IMAGE_SYM_CLASS_EXTERNAL = 0x2;
static final int IMAGE_SYM_CLASS_STATIC = 0x3;
static final int IMAGE_SYM_CLASS_LABEL = 0x6;
}
/**
* IMAGE_RELOCATION structure defines
*/
public enum IMAGE_RELOCATION {
enum IMAGE_RELOCATION {
VirtualAddress( 0, 4),
SymbolTableIndex( 4, 4),
Type( 8, 2);
public final int off;
public final int sz;
final int off;
final int sz;
IMAGE_RELOCATION(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 10;
static int totalsize = 10;
/**
* Relocation types
*/
public static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0;
public static final int IMAGE_REL_AMD64_ADDR32 = 0x2;
public static final int IMAGE_REL_AMD64_ADDR64 = 0x1;
public static final int IMAGE_REL_AMD64_REL32 = 0x4;
public static final int IMAGE_REL_AMD64_REL32_1 = 0x5;
public static final int IMAGE_REL_AMD64_REL32_2 = 0x6;
public static final int IMAGE_REL_AMD64_REL32_3 = 0x7;
public static final int IMAGE_REL_AMD64_REL32_4 = 0x8;
public static final int IMAGE_REL_AMD64_REL32_5 = 0x9;
static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0;
static final int IMAGE_REL_AMD64_ADDR32 = 0x2;
static final int IMAGE_REL_AMD64_ADDR64 = 0x1;
static final int IMAGE_REL_AMD64_REL32 = 0x4;
static final int IMAGE_REL_AMD64_REL32_1 = 0x5;
static final int IMAGE_REL_AMD64_REL32_2 = 0x6;
static final int IMAGE_REL_AMD64_REL32_3 = 0x7;
static final int IMAGE_REL_AMD64_REL32_4 = 0x8;
static final int IMAGE_REL_AMD64_REL32_5 = 0x9;
}
//@formatter:on
}

View File

@ -26,9 +26,9 @@ package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class PECoffByteBuffer {
final class PECoffByteBuffer {
public static ByteBuffer allocate(int size) {
static ByteBuffer allocate(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
// Only support Little Endian on Windows
buf.order(ByteOrder.LITTLE_ENDIAN);

View File

@ -26,14 +26,13 @@ package jdk.tools.jaotc.binformat.pecoff;
import java.io.File;
import java.io.FileOutputStream;
public class PECoffContainer {
final class PECoffContainer {
File outputFile;
FileOutputStream outputStream;
long fileOffset;
private final File outputFile;
private FileOutputStream outputStream;
private long fileOffset;
public PECoffContainer(String fileName, String aotVersion) {
String baseName;
PECoffContainer(String fileName) {
outputFile = new File(fileName);
if (outputFile.exists()) {
@ -48,7 +47,7 @@ public class PECoffContainer {
fileOffset = 0;
}
public void close() {
void close() {
try {
outputStream.close();
} catch (Exception e) {
@ -56,8 +55,10 @@ public class PECoffContainer {
}
}
public void writeBytes(byte [] bytes) {
if (bytes == null) return;
void writeBytes(byte[] bytes) {
if (bytes == null) {
return;
}
try {
outputStream.write(bytes);
} catch (Exception e) {
@ -67,11 +68,13 @@ public class PECoffContainer {
}
// Write bytes to output file with up front alignment padding
public void writeBytes(byte [] bytes, int alignment) {
if (bytes == null) return;
void writeBytes(byte[] bytes, int alignment) {
if (bytes == null) {
return;
}
try {
// Pad to alignment
while ((fileOffset & (long)(alignment-1)) != 0) {
while ((fileOffset & (alignment - 1)) != 0) {
outputStream.write(0);
fileOffset++;
}
@ -82,4 +85,3 @@ public class PECoffContainer {
fileOffset += bytes.length;
}
}

View File

@ -24,45 +24,41 @@
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo;
import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
public class PECoffHeader {
ByteBuffer header;
final class PECoffHeader {
private final ByteBuffer header;
public PECoffHeader() {
PECoffHeader() {
header = PECoffByteBuffer.allocate(IMAGE_FILE_HEADER.totalsize);
header.putChar(IMAGE_FILE_HEADER.Machine.off, IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64);
header.putInt(IMAGE_FILE_HEADER.TimeDateStamp.off, (int)(System.currentTimeMillis()/1000));
header.putInt(IMAGE_FILE_HEADER.TimeDateStamp.off, (int) (System.currentTimeMillis() / 1000));
header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, 0);
header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, 0);
header.putChar(IMAGE_FILE_HEADER.SizeOfOptionalHeader.off, (char)0);
header.putChar(IMAGE_FILE_HEADER.Characteristics.off, (char)0);
header.putChar(IMAGE_FILE_HEADER.SizeOfOptionalHeader.off, (char) 0);
header.putChar(IMAGE_FILE_HEADER.Characteristics.off, (char) 0);
}
// Update header with the number of total sections
public void setSectionCount(int count) {
header.putChar(IMAGE_FILE_HEADER.NumberOfSections.off, (char)count);
void setSectionCount(int count) {
header.putChar(IMAGE_FILE_HEADER.NumberOfSections.off, (char) count);
}
// Update header with the number of total symbols
public void setSymbolCount(int count) {
void setSymbolCount(int count) {
header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, count);
}
// Update header with the offset of symbol table
public void setSymbolOff(int offset) {
void setSymbolOff(int offset) {
header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, offset);
}
public byte[] getArray() {
byte[] getArray() {
return header.array();
}
}

View File

@ -24,26 +24,23 @@
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
public class PECoffRelocEntry {
ByteBuffer entry;
final class PECoffRelocEntry {
private final ByteBuffer entry;
public PECoffRelocEntry(int offset, int symno, int type) {
PECoffRelocEntry(int offset, int symno, int type) {
entry = PECoffByteBuffer.allocate(IMAGE_RELOCATION.totalsize);
entry.putInt(IMAGE_RELOCATION.VirtualAddress.off, offset);
entry.putInt(IMAGE_RELOCATION.SymbolTableIndex.off, symno);
entry.putChar(IMAGE_RELOCATION.Type.off, (char)type);
entry.putChar(IMAGE_RELOCATION.Type.off, (char) type);
}
public byte[] getArray() {
byte[] getArray() {
return entry.array();
}
}

View File

@ -25,52 +25,47 @@ package jdk.tools.jaotc.binformat.pecoff;
import java.util.ArrayList;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
import jdk.tools.jaotc.binformat.pecoff.PECoffRelocEntry;
import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
public class PECoffRelocTable {
final class PECoffRelocTable {
ArrayList<ArrayList<PECoffRelocEntry>> relocEntries;
public PECoffRelocTable(int numsects) {
relocEntries = new ArrayList<ArrayList<PECoffRelocEntry>>(numsects);
for (int i = 0; i < numsects; i++)
PECoffRelocTable(int numsects) {
relocEntries = new ArrayList<>(numsects);
for (int i = 0; i < numsects; i++) {
relocEntries.add(new ArrayList<PECoffRelocEntry>());
}
}
public void createRelocationEntry(int sectindex,
int offset,
int symno,
int type) {
PECoffRelocEntry entry = new PECoffRelocEntry(offset,
symno,
type);
void createRelocationEntry(int sectindex, int offset, int symno, int type) {
PECoffRelocEntry entry = new PECoffRelocEntry(offset, symno, type);
relocEntries.get(sectindex).add(entry);
}
public int getAlign() { return (4); }
static int getAlign() {
return (4);
}
public int getNumRelocs(int section_index) {
int getNumRelocs(int section_index) {
return relocEntries.get(section_index).size();
}
// Return the relocation entries for a single section
// or null if no entries added to section
public byte [] getRelocData(int section_index) {
// or null if no entries added to section
byte[] getRelocData(int section_index) {
ArrayList<PECoffRelocEntry> entryList = relocEntries.get(section_index);
int entryCount = entryList.size();
int allocCount = entryCount;
if (entryCount == 0)
if (entryCount == 0) {
return null;
if (entryCount > 0xFFFF)
}
if (entryCount > 0xFFFF) {
allocCount++;
}
ByteBuffer relocData = PECoffByteBuffer.allocate(allocCount * IMAGE_RELOCATION.totalsize);
// If number of relocs exceeds 65K, add the real size
@ -89,4 +84,3 @@ public class PECoffRelocTable {
return (relocData.array());
}
}

View File

@ -24,32 +24,39 @@
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
public class PECoffSection {
ByteBuffer section;
byte [] data;
boolean hasrelocations;
int sectionIndex;
int align;
final class PECoffSection {
private final ByteBuffer section;
private final byte[] data;
private final boolean hasrelocations;
private final int sectionIndex;
private final int align;
public PECoffSection(String sectName, byte [] sectData, int sectFlags,
boolean hasRelocations, int sectIndex) {
PECoffSection(String sectName, byte[] sectData0, int sectFlags0, int sectAlign, boolean hasRelocations, int sectIndex) {
section = PECoffByteBuffer.allocate(IMAGE_SECTION_HEADER.totalsize);
// bug: If JVM.oop.got section is empty, VM exits since JVM.oop.got
// symbol ends up as external forwarded reference.
if (sectData.length == 0) sectData = new byte[8];
// If .oop.got section is empty, VM exits since .oop.got
// symbol ends up as external forwarded reference.
byte[] sectData = sectData0;
if (sectData0.length == 0) {
sectData = new byte[8];
}
// Copy only Max allowed bytes to Section Entry
byte [] Name = sectName.getBytes();
int max = Name.length <= IMAGE_SECTION_HEADER.Name.sz ?
Name.length : IMAGE_SECTION_HEADER.Name.sz;
byte[] Name = sectName.getBytes();
int max = Name.length <= IMAGE_SECTION_HEADER.Name.sz ? Name.length : IMAGE_SECTION_HEADER.Name.sz;
assert (sectAlign < 1 || sectAlign > 1024 || (sectAlign & (sectAlign - 1)) != 0) : "section alignment is not valid: " + sectAlign;
align = sectAlign;
// Using 32 because IMAGE_SCN_ALIGN_*BYTES is value + 1
int sectAlignBits = (32 - Integer.numberOfLeadingZeros(align)) << IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_SHIFT;
// Clear and set alignment bits
int sectFlags = (sectFlags0 & ~IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK) | (sectAlignBits & IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK);
section.put(Name, IMAGE_SECTION_HEADER.Name.off, max);
@ -57,84 +64,69 @@ public class PECoffSection {
section.putInt(IMAGE_SECTION_HEADER.VirtualAddress.off, 0);
section.putInt(IMAGE_SECTION_HEADER.SizeOfRawData.off, sectData.length);
section.putInt(IMAGE_SECTION_HEADER.PointerToLinenumbers.off, 0);
section.putChar(IMAGE_SECTION_HEADER.NumberOfLinenumbers.off, (char)0);
section.putChar(IMAGE_SECTION_HEADER.NumberOfLinenumbers.off, (char) 0);
section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, sectFlags);
// Extract alignment from Characteristics field
int alignshift = (sectFlags & IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK) >>
IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_SHIFT;
// Use 8 byte alignment if not specified
if (alignshift == 0)
alignshift = 3;
else
--alignshift;
align = 1 << alignshift;
data = sectData;
hasrelocations = hasRelocations;
sectionIndex = sectIndex;
}
public long getSize() {
long getSize() {
return section.getInt(IMAGE_SECTION_HEADER.SizeOfRawData.off);
}
public int getDataAlign() {
int getDataAlign() {
return (align);
}
// Alignment requirements for the IMAGE_SECTION_HEADER structures
public static int getShdrAlign() {
static int getShdrAlign() {
return (4);
}
public byte[] getArray() {
byte[] getArray() {
return section.array();
}
public byte[] getDataArray() {
byte[] getDataArray() {
return data;
}
public void setOffset(long offset) {
section.putInt(IMAGE_SECTION_HEADER.PointerToRawData.off, (int)offset);
void setOffset(long offset) {
section.putInt(IMAGE_SECTION_HEADER.PointerToRawData.off, (int) offset);
}
public long getOffset() {
long getOffset() {
return (section.getInt(IMAGE_SECTION_HEADER.PointerToRawData.off));
}
public void setReloff(int offset) {
void setReloff(int offset) {
section.putInt(IMAGE_SECTION_HEADER.PointerToRelocations.off, offset);
}
public void setRelcount(int count) {
void setRelcount(int count) {
// If the number of relocs is larger than 65K, then set
// the overflow bit. The real count will be written to
// the overflow bit. The real count will be written to
// the first reloc entry for this section.
if (count > 0xFFFF) {
int flags;
section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)0xFFFF);
section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char) 0xFFFF);
flags = section.getInt(IMAGE_SECTION_HEADER.Characteristics.off);
flags |= IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_NRELOC_OVFL;
section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, flags);
}
else {
section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)count);
} else {
section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char) count);
}
}
public boolean hasRelocations() {
boolean hasRelocations() {
return hasrelocations;
}
public int getSectionId() {
int getSectionId() {
return sectionIndex;
}
}

View File

@ -24,18 +24,15 @@
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.NativeSymbol;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
public class PECoffSymbol extends NativeSymbol {
ByteBuffer sym;
final class PECoffSymbol extends NativeSymbol {
private final ByteBuffer sym;
public PECoffSymbol(int symbolindex, int strindex, byte type, byte storageclass,
byte sectindex, long offset, long size) {
PECoffSymbol(int symbolindex, int strindex, byte type, byte storageclass, byte sectindex, long offset) {
super(symbolindex);
sym = PECoffByteBuffer.allocate(IMAGE_SYMBOL.totalsize);
@ -43,19 +40,18 @@ public class PECoffSymbol extends NativeSymbol {
sym.putInt(IMAGE_SYMBOL.Short.off, 0);
sym.putInt(IMAGE_SYMBOL.Long.off, strindex);
sym.putInt(IMAGE_SYMBOL.Value.off, (int)offset);
sym.putInt(IMAGE_SYMBOL.Value.off, (int) offset);
// Section indexes start at 1 but we manage the index internally
// as 0 relative except in this structure
sym.putChar(IMAGE_SYMBOL.SectionNumber.off, (char)(sectindex+1));
sym.putChar(IMAGE_SYMBOL.SectionNumber.off, (char) (sectindex + 1));
sym.putChar(IMAGE_SYMBOL.Type.off, (char)type);
sym.putChar(IMAGE_SYMBOL.Type.off, (char) type);
sym.put(IMAGE_SYMBOL.StorageClass.off, storageclass);
sym.put(IMAGE_SYMBOL.NumberOfAuxSymbols.off, (byte)0);
sym.put(IMAGE_SYMBOL.NumberOfAuxSymbols.off, (byte) 0);
}
public byte[] getArray() {
byte[] getArray() {
return sym.array();
}
}

View File

@ -27,36 +27,35 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol;
import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
public class PECoffSymtab {
ArrayList<PECoffSymbol>symbols = new ArrayList<PECoffSymbol>();
final class PECoffSymtab {
ArrayList<PECoffSymbol> symbols = new ArrayList<>();
/**
* number of symbols added
*/
int symbolCount;
private int symbolCount;
/**
* String holding symbol table strings
*/
private StringBuilder strTabContent;
private final StringBuilder strTabContent;
/**
* Keeps track of bytes in string table since strTabContent.length()
* is number of chars, not bytes.
* Keeps track of bytes in string table since strTabContent.length() is number of chars, not
* bytes.
*/
private int strTabNrOfBytes;
/**
* String holding Linker Directives
*/
private StringBuilder directives;
private final StringBuilder directives;
public PECoffSymtab() {
PECoffSymtab() {
symbolCount = 0;
strTabContent = new StringBuilder();
directives = new StringBuilder();
@ -72,8 +71,7 @@ public class PECoffSymtab {
directives.append(" ");
}
public PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass,
byte secHdrIndex, long offset, long size) {
PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass, byte secHdrIndex, long offset) {
// Get the current symbol index and append symbol name to string table.
int index;
PECoffSymbol sym;
@ -82,7 +80,7 @@ public class PECoffSymtab {
index = 0;
strTabContent.append('\0');
strTabNrOfBytes += 1;
sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size);
sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset);
symbols.add(sym);
} else {
int nameSize = name.getBytes().length;
@ -94,10 +92,11 @@ public class PECoffSymtab {
strTabContent.append(name).append('\0');
strTabNrOfBytes += (nameSize + 1);
sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size);
sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset);
symbols.add(sym);
if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL)
if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL) {
addDirective(name, type);
}
}
symbolCount++;
return (sym);
@ -105,37 +104,37 @@ public class PECoffSymtab {
private void addDirective(String name, byte type) {
directives.append("/EXPORT:" + name);
if(type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) {
if (type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) {
directives.append(",DATA");
}
directives.append(" ");
}
public int getSymtabCount() {
int getSymtabCount() {
return symbolCount;
}
public int getStrtabSize() {
int getStrtabSize() {
return strTabNrOfBytes;
}
// Return a byte array that contains the symbol table entries
public byte[] getSymtabArray() {
ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount*IMAGE_SYMBOL.totalsize);
byte[] getSymtabArray() {
ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount * IMAGE_SYMBOL.totalsize);
symtabData.order(ByteOrder.LITTLE_ENDIAN);
// copy all symbols
for (int i = 0; i < symbolCount; i++ ) {
for (int i = 0; i < symbolCount; i++) {
PECoffSymbol sym = symbols.get(i);
byte [] arr = sym.getArray();
byte[] arr = sym.getArray();
symtabData.put(arr);
}
return (symtabData.array());
}
// Return the string table array
public byte[] getStrtabArray() {
byte [] strs = strTabContent.toString().getBytes();
byte[] getStrtabArray() {
byte[] strs = strTabContent.toString().getBytes();
// Update the size of the string table
ByteBuffer buff = ByteBuffer.wrap(strs);
@ -145,7 +144,7 @@ public class PECoffSymtab {
return (strs);
}
public byte[] getDirectiveArray() {
byte[] getDirectiveArray() {
return (directives.toString().getBytes());
}
}

View File

@ -24,14 +24,13 @@
package jdk.tools.jaotc.binformat.pecoff;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
/**
* Class that abstracts MACH-O target details.
*
*/
public class PECoffTargetInfo {
final class PECoffTargetInfo {
/**
* Target architecture.
*/
@ -63,12 +62,11 @@ public class PECoffTargetInfo {
}
}
public static char getPECoffArch() {
static char getPECoffArch() {
return arch;
}
public static String getOsName() {
static String getOsName() {
return osName;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -52,7 +52,7 @@ import jdk.vm.ci.meta.ProfilingInfo;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.TriState;
public class AOTBackend {
final class AOTBackend {
private final Main main;
private final OptionValues graalOptions;
private final HotSpotBackend backend;
@ -60,28 +60,26 @@ public class AOTBackend {
private final HotSpotCodeCacheProvider codeCache;
private final PhaseSuite<HighTierContext> graphBuilderSuite;
private final HighTierContext highTierContext;
private final GraalFilters filters;
public AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, GraalFilters filters) {
AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend) {
this.main = main;
this.graalOptions = graalOptions;
this.backend = backend;
this.filters = filters;
providers = backend.getProviders();
codeCache = providers.getCodeCache();
graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions);
highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
}
public PhaseSuite<HighTierContext> getGraphBuilderSuite() {
PhaseSuite<HighTierContext> getGraphBuilderSuite() {
return graphBuilderSuite;
}
public HotSpotBackend getBackend() {
HotSpotBackend getBackend() {
return backend;
}
public HotSpotProviders getProviders() {
HotSpotProviders getProviders() {
return providers;
}
@ -96,7 +94,7 @@ public class AOTBackend {
}
@SuppressWarnings("try")
public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod, DebugContext debug) {
CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod, DebugContext debug) {
StructuredGraph graph = buildStructuredGraph(resolvedMethod, debug);
if (graph != null) {
return compileGraph(resolvedMethod, graph, debug);
@ -118,7 +116,7 @@ public class AOTBackend {
graphBuilderSuite.apply(graph, highTierContext);
return graph;
} catch (Throwable e) {
handleError(javaMethod, e, " (building graph)");
main.handleError(javaMethod, e, " (building graph)");
}
return null;
}
@ -135,20 +133,11 @@ public class AOTBackend {
compilationResult, CompilationResultBuilderFactory.Default);
} catch (Throwable e) {
handleError(resolvedMethod, e, " (compiling graph)");
main.handleError(resolvedMethod, e, " (compiling graph)");
}
return null;
}
/**
* Returns whether the VM is a debug build.
*
* @return true is debug VM, false otherwise
*/
public boolean isDebugVM() {
return backend.getRuntime().getVMConfig().cAssertions;
}
private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions) {
PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
@ -165,39 +154,12 @@ public class AOTBackend {
return graphBuilderSuite;
}
private void handleError(ResolvedJavaMethod resolvedMethod, Throwable e, String message) {
String methodName = MiscUtils.uniqueMethodName(resolvedMethod);
if (main.options.debug) {
main.printError("Failed compilation: " + methodName + ": " + e);
}
// Ignore some exceptions when meta-compiling Graal.
if (filters.shouldIgnoreException(e)) {
return;
}
Main.writeLog("Failed compilation of method " + methodName + message);
if (!main.options.debug) {
main.printError("Failed compilation: " + methodName + ": " + e);
}
if (main.options.verbose) {
e.printStackTrace(main.log);
}
if (main.options.exitOnError) {
System.exit(1);
}
}
public void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) {
void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) {
// This is really not installing the method.
InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult), null, null);
String disassembly = codeCache.disassemble(installedCode);
if (disassembly != null) {
main.printlnDebug(disassembly);
main.printer.printlnDebug(disassembly);
}
}
}

View File

@ -48,7 +48,7 @@ import jdk.vm.ci.runtime.JVMCICompiler;
* compilation of classes. It also defines methods that parse compilation result of Graal to create
* target-independent representation {@code BinaryContainer} of the intended target binary.
*/
public class AOTCompilationTask implements Runnable, Comparable<Object> {
final class AOTCompilationTask implements Runnable, Comparable<Object> {
private static final AtomicInteger ids = new AtomicInteger();
@ -77,7 +77,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
*/
private CompiledMethodInfo result;
public AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) {
AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) {
this.main = main;
this.graalOptions = graalOptions;
this.id = ids.incrementAndGet();
@ -95,7 +95,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
// may include processing command line options used by the latter.
HotSpotJVMCIRuntime.runtime();
AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling");
AOTCompiler.logCompilation(JavaMethodInfo.uniqueMethodName(method), "Compiling");
final long threadId = Thread.currentThread().getId();
@ -137,7 +137,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
}
// For now precision to the nearest second is sufficient.
Main.writeLog(" Compile Time: " + TimeUnit.MILLISECONDS.toSeconds(endTime - startTime) + "secs");
LogPrinter.writeLog(" Compile Time: " + TimeUnit.MILLISECONDS.toSeconds(endTime - startTime) + "secs");
if (main.options.debug) {
aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult);
}
@ -146,7 +146,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
}
private String getMethodDescription() {
return String.format("%-6d aot %s %s", getId(), MiscUtils.uniqueMethodName(method),
return String.format("%-6d aot %s %s", getId(), JavaMethodInfo.uniqueMethodName(method),
getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") ");
}
@ -154,11 +154,11 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
return id;
}
public int getEntryBCI() {
private static int getEntryBCI() {
return JVMCICompiler.INVOCATION_ENTRY_BCI;
}
public ResolvedJavaMethod getMethod() {
ResolvedJavaMethod getMethod() {
return method;
}
@ -167,7 +167,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
*
* @return the holder of this method
*/
public AOTCompiledClass getHolder() {
AOTCompiledClass getHolder() {
return holder;
}
@ -176,7 +176,7 @@ public class AOTCompilationTask implements Runnable, Comparable<Object> {
*
* @return result of this compilation task
*/
public CompiledMethodInfo getResult() {
CompiledMethodInfo getResult() {
return result;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -41,16 +41,16 @@ import jdk.vm.ci.meta.ResolvedJavaType;
* Class encapsulating Graal-compiled output of a Java class. The compilation result of all methods
* of a class {@code className} are maintained in an array list.
*/
public class AOTCompiledClass {
final class AOTCompiledClass {
public static class AOTKlassData {
int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
int classId; // Unique ID
static class AOTKlassData {
private int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
private int classId; // Unique ID
// Offset to compiled methods data in the .methods.offsets section.
int compiledMethodsOffset;
private int compiledMethodsOffset;
// Offset to dependent methods data.
int dependentMethodsOffset;
long fingerprint; // Class fingerprint
private int dependentMethodsOffset;
private long fingerprint; // Class fingerprint
private final String name;
private boolean isArray;
@ -60,25 +60,25 @@ public class AOTCompiledClass {
*/
private ArrayList<CompiledMethodInfo> dependentMethods;
public AOTKlassData(BinaryContainer binaryContainer, String name, long fingerprint, int classId) {
AOTKlassData(BinaryContainer binaryContainer, String name, long fingerprint, int classId) {
this.dependentMethods = new ArrayList<>();
this.classId = classId;
this.fingerprint = fingerprint;
this.gotIndex = binaryContainer.addTwoSlotMetaspaceSymbol(name);
this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(name);
this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
this.dependentMethodsOffset = -1;
this.name = name;
this.isArray = name.length() > 0 && name.charAt(0) == '[';
}
public long getFingerprint() {
long getFingerprint() {
return fingerprint;
}
/**
* Add a method to the list of dependent methods.
*/
public synchronized boolean addDependentMethod(CompiledMethodInfo cm) {
synchronized boolean addDependentMethod(CompiledMethodInfo cm) {
return dependentMethods.add(cm);
}
@ -87,7 +87,7 @@ public class AOTCompiledClass {
*
* @return array list of dependent methods
*/
public ArrayList<CompiledMethodInfo> getDependentMethods() {
ArrayList<CompiledMethodInfo> getDependentMethods() {
return dependentMethods;
}
@ -96,11 +96,11 @@ public class AOTCompiledClass {
*
* @return true if dependent methods exist, false otherwise
*/
public boolean hasDependentMethods() {
boolean hasDependentMethods() {
return !dependentMethods.isEmpty();
}
public void setCompiledMethodsOffset(int offset) {
void setCompiledMethodsOffset(int offset) {
compiledMethodsOffset = offset;
}
@ -108,7 +108,7 @@ public class AOTCompiledClass {
int cntDepMethods = dependentMethods.size();
// Create array of dependent methods IDs. First word is count.
ReadOnlyDataContainer dependenciesContainer = binaryContainer.getKlassesDependenciesContainer();
this.dependentMethodsOffset = binaryContainer.addMethodsCount(cntDepMethods, dependenciesContainer);
this.dependentMethodsOffset = BinaryContainer.addMethodsCount(cntDepMethods, dependenciesContainer);
for (CompiledMethodInfo methodInfo : dependentMethods) {
dependenciesContainer.appendInt(methodInfo.getCodeId());
}
@ -176,7 +176,7 @@ public class AOTCompiledClass {
*
* @param compiledMethods AOT compiled methods
*/
public AOTCompiledClass(ArrayList<CompiledMethodInfo> compiledMethods) {
AOTCompiledClass(ArrayList<CompiledMethodInfo> compiledMethods) {
this.resolvedJavaType = null;
this.compiledMethods = compiledMethods;
this.representsStubs = true;
@ -185,7 +185,7 @@ public class AOTCompiledClass {
/**
* Construct an object with compiled versions of the named class.
*/
public AOTCompiledClass(ResolvedJavaType resolvedJavaType) {
AOTCompiledClass(ResolvedJavaType resolvedJavaType) {
this.resolvedJavaType = (HotSpotResolvedObjectType) resolvedJavaType;
this.compiledMethods = new ArrayList<>();
this.representsStubs = false;
@ -194,14 +194,14 @@ public class AOTCompiledClass {
/**
* @return the ResolvedJavaType of this class
*/
public ResolvedJavaType getResolvedJavaType() {
ResolvedJavaType getResolvedJavaType() {
return resolvedJavaType;
}
/**
* Get the list of methods which should be compiled.
*/
public ArrayList<ResolvedJavaMethod> getMethods() {
ArrayList<ResolvedJavaMethod> getMethods() {
ArrayList<ResolvedJavaMethod> m = methods;
methods = null; // Free - it is not used after that.
return m;
@ -210,7 +210,7 @@ public class AOTCompiledClass {
/**
* Get the number of all AOT classes.
*/
public static int getClassesCount() {
static int getClassesCount() {
return classesCount;
}
@ -219,14 +219,14 @@ public class AOTCompiledClass {
*
* @return number of methods which should be compiled
*/
public int getMethodCount() {
int getMethodCount() {
return methods.size();
}
/**
* Add a method to the list of methods to be compiled.
*/
public void addMethod(ResolvedJavaMethod method) {
void addMethod(ResolvedJavaMethod method) {
methods.add(method);
}
@ -235,14 +235,14 @@ public class AOTCompiledClass {
*
* @return true if this class contains methods which should be compiled, false otherwise
*/
public boolean hasMethods() {
boolean hasMethods() {
return !methods.isEmpty();
}
/**
* Add a method to the list of compiled methods. This method needs to be thread-safe.
*/
public synchronized boolean addCompiledMethod(CompiledMethodInfo cm) {
synchronized boolean addCompiledMethod(CompiledMethodInfo cm) {
return compiledMethods.add(cm);
}
@ -251,7 +251,7 @@ public class AOTCompiledClass {
*
* @return array list of compiled methods
*/
public ArrayList<CompiledMethodInfo> getCompiledMethods() {
ArrayList<CompiledMethodInfo> getCompiledMethods() {
return compiledMethods;
}
@ -260,14 +260,14 @@ public class AOTCompiledClass {
*
* @return true if methods were compiled, false otherwise
*/
public boolean hasCompiledMethods() {
boolean hasCompiledMethods() {
return !compiledMethods.isEmpty();
}
/**
* Add a klass data.
*/
public synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
String name = type.getName();
long fingerprint = type.getFingerprint();
AOTKlassData data = klassData.get(name);
@ -280,15 +280,15 @@ public class AOTCompiledClass {
return data;
}
public synchronized static AOTKlassData getAOTKlassData(String name) {
synchronized static AOTKlassData getAOTKlassData(String name) {
return klassData.get(name);
}
public synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
return getAOTKlassData(type.getName());
}
public void addAOTKlassData(BinaryContainer binaryContainer) {
void addAOTKlassData(BinaryContainer binaryContainer) {
for (CompiledMethodInfo methodInfo : compiledMethods) {
// Record methods holder
methodInfo.addDependentKlassData(binaryContainer, resolvedJavaType);
@ -309,7 +309,7 @@ public class AOTCompiledClass {
}
}
public synchronized static AOTKlassData addFingerprintKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
synchronized static AOTKlassData addFingerprintKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
if (type.isArray()) {
return addAOTKlassData(binaryContainer, type);
}
@ -317,14 +317,15 @@ public class AOTCompiledClass {
AOTKlassData old = getAOTKlassData(type);
if (old != null) {
boolean assertsEnabled = false;
// Next assignment will be executed when asserts are enabled.
assert assertsEnabled = true;
if (assertsEnabled) {
HotSpotResolvedObjectType s = type.getSuperclass();
if (s != null) {
assert getAOTKlassData(s) != null : "fingerprint super " + s.getName() + " needed for " + type.getName();
assert getAOTKlassData(s) != null : "fingerprint for super " + s.getName() + " needed for " + type.getName();
}
for (HotSpotResolvedObjectType i : type.getInterfaces()) {
assert getAOTKlassData(i) != null : "fingerprint super " + i.getName() + " needed for " + type.getName();
assert getAOTKlassData(i) != null : "fingerprint for interface " + i.getName() + " needed for " + type.getName();
}
}
return old;
@ -345,10 +346,10 @@ public class AOTCompiledClass {
/*
* Put methods data to contained.
*/
public void putMethodsData(BinaryContainer binaryContainer) {
void putMethodsData(BinaryContainer binaryContainer) {
ReadOnlyDataContainer container = binaryContainer.getMethodsOffsetsContainer();
int cntMethods = compiledMethods.size();
int startMethods = binaryContainer.addMethodsCount(cntMethods, container);
int startMethods = BinaryContainer.addMethodsCount(cntMethods, container);
for (CompiledMethodInfo methodInfo : compiledMethods) {
methodInfo.addMethodOffsets(binaryContainer, container);
}
@ -361,18 +362,18 @@ public class AOTCompiledClass {
data.setCompiledMethodsOffset(startMethods);
}
public static void putAOTKlassData(BinaryContainer binaryContainer) {
static void putAOTKlassData(BinaryContainer binaryContainer) {
ReadOnlyDataContainer container = binaryContainer.getKlassesOffsetsContainer();
for (AOTKlassData data : klassData.values()) {
data.putAOTKlassData(binaryContainer, container);
}
}
public boolean representsStubs() {
boolean representsStubs() {
return representsStubs;
}
public void clear() {
void clear() {
for (CompiledMethodInfo c : compiledMethods) {
c.clear();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@ import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class AOTCompiler {
final class AOTCompiler {
private final Main main;
@ -68,7 +68,7 @@ public class AOTCompiler {
/**
* Create a compile queue with the given number of threads.
*/
public CompileQueue(final int threads) {
CompileQueue(final int threads) {
super(threads, threads, 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<>());
startTime = System.currentTimeMillis();
}
@ -79,7 +79,7 @@ public class AOTCompiler {
if (task.getResult() != null) {
final int count = successfulMethodCount.incrementAndGet();
if (count % 100 == 0) {
main.printInfo(".");
main.printer.printInfo(".");
}
CompiledMethodInfo result = task.getResult();
if (result != null) {
@ -87,9 +87,9 @@ public class AOTCompiler {
}
} else {
failedMethodCount.incrementAndGet();
main.printlnVerbose("");
main.printer.printlnVerbose("");
ResolvedJavaMethod method = task.getMethod();
main.printlnVerbose(" failed " + method.getName() + method.getSignature().toMethodDescriptor());
main.printer.printlnVerbose(" failed " + method.getName() + method.getSignature().toMethodDescriptor());
}
}
@ -98,8 +98,8 @@ public class AOTCompiler {
final long endTime = System.currentTimeMillis();
final int success = successfulMethodCount.get();
final int failed = failedMethodCount.get();
main.printlnInfo("");
main.printlnInfo(success + " methods compiled, " + failed + " methods failed (" + (endTime - startTime) + " ms)");
main.printer.printlnInfo("");
main.printer.printlnInfo(success + " methods compiled, " + failed + " methods failed (" + (endTime - startTime) + " ms)");
}
}
@ -110,7 +110,7 @@ public class AOTCompiler {
* @param aotBackend
* @param threads number of compilation threads
*/
public AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) {
AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) {
this.main = main;
this.graalOptions = graalOptions;
this.compileQueue = new CompileQueue(threads);
@ -123,9 +123,9 @@ public class AOTCompiler {
* @param classes a list of class to compile
* @throws InterruptedException
*/
public List<AOTCompiledClass> compileClasses(List<AOTCompiledClass> classes) throws InterruptedException {
main.printlnInfo("Compiling with " + compileQueue.getCorePoolSize() + " threads");
main.printInfo("."); // Compilation progress indication.
List<AOTCompiledClass> compileClasses(List<AOTCompiledClass> classes) throws InterruptedException {
main.printer.printlnInfo("Compiling with " + compileQueue.getCorePoolSize() + " threads");
main.printer.printInfo("."); // Compilation progress indication.
for (AOTCompiledClass c : classes) {
for (ResolvedJavaMethod m : c.getMethods()) {
@ -160,8 +160,8 @@ public class AOTCompiler {
}
}
public static void logCompilation(String methodName, String message) {
Main.writeLog(message + " " + methodName);
static void logCompilation(String methodName, String message) {
LogPrinter.writeLog(message + " " + methodName);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,18 +29,18 @@ import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
final class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo {
private final HotSpotResolvedJavaMethod method;
private final Backend backend;
public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) {
AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) {
this.method = method;
this.backend = backend;
}
public String getSymbolName() {
return MiscUtils.uniqueMethodName(method);
return JavaMethodInfo.uniqueMethodName(method);
}
public String getNameAndSignature() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,12 +30,12 @@ import org.graalvm.compiler.hotspot.stubs.Stub;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
public class AOTStub implements JavaMethodInfo {
final class AOTStub implements JavaMethodInfo {
private final Stub stub;
private final Backend backend;
public AOTStub(Stub stub, Backend backend) {
AOTStub(Stub stub, Backend backend) {
this.stub = stub;
this.backend = backend;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,28 +30,16 @@ import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class MiscUtils {
final class CallInfo {
/**
* Name a java method with class and signature to make it unique.
*
* @param method to generate unique identifier for
* @return Unique name for this method including class and signature
**/
public static String uniqueMethodName(ResolvedJavaMethod method) {
String className = method.getDeclaringClass().toClassName();
String name = className + "." + method.getName() + method.getSignature().toMethodDescriptor();
return name;
}
public static boolean isStaticCall(Call call) {
static boolean isStaticCall(Call call) {
if (isJavaCall(call)) {
return ((getByteCode(call) & 0xFF) == Bytecodes.INVOKESTATIC);
}
return false;
}
public static boolean isSpecialCall(Call call) {
static boolean isSpecialCall(Call call) {
if (isJavaCall(call)) {
return ((getByteCode(call) & 0xFF) == Bytecodes.INVOKESPECIAL);
}
@ -65,11 +53,11 @@ public class MiscUtils {
return false;
}
public static boolean isVirtualCall(CompiledMethodInfo methodInfo, Call call) {
static boolean isVirtualCall(CompiledMethodInfo methodInfo, Call call) {
return isInvokeVirtual(call) && !methodInfo.hasMark(call, MarkId.INVOKESPECIAL);
}
public static boolean isOptVirtualCall(CompiledMethodInfo methodInfo, Call call) {
static boolean isOptVirtualCall(CompiledMethodInfo methodInfo, Call call) {
return isInvokeVirtual(call) && methodInfo.hasMark(call, MarkId.INVOKESPECIAL);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,10 +31,10 @@ import jdk.tools.jaotc.binformat.Relocation.RelocType;
*/
abstract class CallSiteRelocationInfo {
public final String targetSymbol;
public final RelocType type;
final String targetSymbol;
final RelocType type;
public CallSiteRelocationInfo(String targetSymbol, RelocType type) {
CallSiteRelocationInfo(String targetSymbol, RelocType type) {
this.targetSymbol = targetSymbol;
this.type = type;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,9 +37,9 @@ import jdk.tools.jaotc.binformat.Symbol.Kind;
*/
abstract class CallSiteRelocationSymbol {
public final Symbol symbol;
final Symbol symbol;
public CallSiteRelocationSymbol(Symbol symbol) {
CallSiteRelocationSymbol(Symbol symbol) {
assert symbol != null;
this.symbol = symbol;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@ import java.util.List;
import jdk.vm.ci.code.site.Mark;
public final class CodeOffsets {
final class CodeOffsets {
private final int entry;
private final int verifiedEntry;
private final int exceptionHandler;
@ -40,7 +40,7 @@ public final class CodeOffsets {
this.deoptHandler = deoptHandler;
}
public static CodeOffsets buildFrom(List<Mark> marks) {
static CodeOffsets buildFrom(List<Mark> marks) {
int entry = 0;
int verifiedEntry = 0;
int exceptionHandler = -1;
@ -73,19 +73,19 @@ public final class CodeOffsets {
return new CodeOffsets(entry, verifiedEntry, exceptionHandler, deoptHandler);
}
public int entry() {
int entry() {
return entry;
}
public int verifiedEntry() {
int verifiedEntry() {
return verifiedEntry;
}
public int exceptionHandler() {
int exceptionHandler() {
return exceptionHandler;
}
public int deoptHandler() {
int deoptHandler() {
return deoptHandler;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,7 +28,7 @@ import java.util.ArrayList;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.CodeContainer;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.CompiledMethodInfo.StubInformation;
import jdk.tools.jaotc.StubInformation;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
@ -38,7 +38,7 @@ import jdk.vm.ci.code.site.Infopoint;
import jdk.vm.ci.code.site.InfopointReason;
import jdk.vm.ci.meta.ResolvedJavaMethod;
class CodeSectionProcessor {
final class CodeSectionProcessor {
private final TargetDescription target;
@ -89,11 +89,11 @@ class CodeSectionProcessor {
// Align and pad method entry
CodeContainer codeSection = binaryContainer.getCodeContainer();
int codeIdOffset = binaryContainer.alignUp(codeSection, binaryContainer.getCodeSegmentSize());
int codeIdOffset = BinaryContainer.alignUp(codeSection, binaryContainer.getCodeSegmentSize());
// Store CodeId into code. It will be use by find_aot() using code.segments
methodInfo.setCodeId();
binaryContainer.appendIntToCode(methodInfo.getCodeId());
int textBaseOffset = binaryContainer.alignUp(codeSection, binaryContainer.getCodeEntryAlignment());
int textBaseOffset = BinaryContainer.alignUp(codeSection, binaryContainer.getCodeEntryAlignment());
codeSection.createSymbol(textBaseOffset, Symbol.Kind.JAVA_FUNCTION, Symbol.Binding.LOCAL, targetCodeSize, entry);
@ -102,7 +102,7 @@ class CodeSectionProcessor {
// Write code bytes of the current method into byte stream
binaryContainer.appendCodeBytes(targetCode, 0, targetCodeSize);
int currentStubOffset = binaryContainer.alignUp(codeSection, 8);
int currentStubOffset = BinaryContainer.alignUp(codeSection, 8);
// Set the offset at which stubs of this method would be laid out
methodInfo.setStubsOffset(currentStubOffset - textBaseOffset);
// step through all calls, for every call, add a stub
@ -111,10 +111,10 @@ class CodeSectionProcessor {
final Call callInfopoint = (Call) infopoint;
if (callInfopoint.target instanceof ResolvedJavaMethod) {
ResolvedJavaMethod call = (ResolvedJavaMethod) callInfopoint.target;
StubInformation stub = addCallStub(MiscUtils.isVirtualCall(methodInfo, callInfopoint));
StubInformation stub = addCallStub(CallInfo.isVirtualCall(methodInfo, callInfopoint));
// Get the targetSymbol. A symbol for this will be created later during plt
// creation
String targetSymbol = MiscUtils.uniqueMethodName(call) + ".at." + infopoint.pcOffset;
String targetSymbol = JavaMethodInfo.uniqueMethodName(call) + ".at." + infopoint.pcOffset;
methodInfo.addStubCode(targetSymbol, stub);
currentStubOffset += stub.getSize();
}

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jdk.tools.jaotc.collect.ClassSearch;
import jdk.tools.jaotc.collect.FileSupport;
import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
import jdk.tools.jaotc.collect.jar.JarSourceProvider;
import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
final class Collector {
private final Main main;
Collector(Main main) {
this.main = main;
}
Set<Class<?>> collectClassesToCompile() {
Set<Class<?>> classesToCompile = new HashSet<>();
FileSupport fileSupport = new FileSupport();
ClassSearch lookup = new ClassSearch();
lookup.addProvider(new ModuleSourceProvider());
lookup.addProvider(new ClassNameSourceProvider(fileSupport));
lookup.addProvider(new JarSourceProvider());
lookup.addProvider(new DirectorySourceProvider(fileSupport));
List<LoadedClass> foundClasses = null;
try {
foundClasses = lookup.search(main.options.files, main.options.searchPath);
} catch (InternalError e) {
main.printer.reportError(e);
return null;
}
for (LoadedClass loadedClass : foundClasses) {
classesToCompile.add(loadedClass.getLoadedClass());
}
return classesToCompile;
}
private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions) {
for (ResolvedJavaMethod m : methods) {
addMethod(aotClass, m, compilationRestrictions);
}
}
private void addMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method, CompilationSpec compilationRestrictions) {
// Don't compile native or abstract methods.
if (!method.hasBytecodes()) {
return;
}
if (!compilationRestrictions.shouldCompileMethod(method)) {
return;
}
if (!main.filters.shouldCompileMethod(method)) {
return;
}
aotClass.addMethod(method);
main.printer.printlnVerbose(" added " + method.getName() + method.getSignature().toMethodDescriptor());
}
/**
* Collect all method we should compile.
*
* @return array list of AOT classes which have compiled methods.
*/
List<AOTCompiledClass> collectMethodsToCompile(Set<Class<?>> classesToCompile, MetaAccessProvider metaAccess) {
int total = 0;
int count = 0;
List<AOTCompiledClass> classes = new ArrayList<>();
CompilationSpec compilationRestrictions = collectSpecifiedMethods();
for (Class<?> c : classesToCompile) {
ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c);
if (main.filters.shouldCompileAnyMethodInClass(resolvedJavaType)) {
AOTCompiledClass aotClass = new AOTCompiledClass(resolvedJavaType);
main.printer.printlnVerbose(" Scanning " + c.getName());
// Constructors
try {
ResolvedJavaMethod[] ctors = resolvedJavaType.getDeclaredConstructors();
addMethods(aotClass, ctors, compilationRestrictions);
total += ctors.length;
} catch (Throwable e) {
// If we are running in JCK mode we ignore all exceptions.
if (main.options.ignoreClassLoadingErrors) {
main.printer.printError(c.getName() + ": " + e);
} else {
throw new InternalError(e);
}
}
// Methods
try {
ResolvedJavaMethod[] methods = resolvedJavaType.getDeclaredMethods();
addMethods(aotClass, methods, compilationRestrictions);
total += methods.length;
} catch (Throwable e) {
// If we are running in JCK mode we ignore all exceptions.
if (main.options.ignoreClassLoadingErrors) {
main.printer.printError(c.getName() + ": " + e);
} else {
throw new InternalError(e);
}
}
// Class initializer
try {
ResolvedJavaMethod clinit = resolvedJavaType.getClassInitializer();
if (clinit != null) {
addMethod(aotClass, clinit, compilationRestrictions);
total++;
}
} catch (Throwable e) {
// If we are running in JCK mode we ignore all exceptions.
if (main.options.ignoreClassLoadingErrors) {
main.printer.printError(c.getName() + ": " + e);
} else {
throw new InternalError(e);
}
}
// Found any methods to compile? Add the class.
if (aotClass.hasMethods()) {
classes.add(aotClass);
count += aotClass.getMethodCount();
}
}
}
main.printer.printInfo(total + " methods total, " + count + " methods to compile");
return classes;
}
/**
* If a file with compilation limitations is specified using flag --compile-commands, read the
* file's contents and collect the restrictions.
*/
private CompilationSpec collectSpecifiedMethods() {
CompilationSpec compilationRestrictions = new CompilationSpec();
String methodListFileName = main.options.methodList;
if (methodListFileName != null && !methodListFileName.equals("")) {
try {
FileReader methListFile = new FileReader(methodListFileName);
BufferedReader readBuf = new BufferedReader(methListFile);
String line = null;
while ((line = readBuf.readLine()) != null) {
String trimmedLine = line.trim();
if (!trimmedLine.startsWith("#")) {
String[] components = trimmedLine.split(" ");
if (components.length == 2) {
String directive = components[0];
String pattern = components[1];
switch (directive) {
case "compileOnly":
compilationRestrictions.addCompileOnlyPattern(pattern);
break;
case "exclude":
compilationRestrictions.addExcludePattern(pattern);
break;
default:
System.out.println("Unrecognized command " + directive + ". Ignoring\n\t" + line + "\n encountered in " + methodListFileName);
}
} else {
if (!trimmedLine.equals("")) {
System.out.println("Ignoring malformed line:\n\t " + line + "\n");
}
}
}
}
readBuf.close();
} catch (FileNotFoundException e) {
throw new InternalError("Unable to open method list file: " + methodListFileName, e);
} catch (IOException e) {
throw new InternalError("Unable to read method list file: " + methodListFileName, e);
}
}
return compilationRestrictions;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
* A class encapsulating any user-specified compilation restrictions.
*/
public class CompilationSpec {
final class CompilationSpec {
/**
* Set of method names to restrict compilation to.
@ -51,7 +51,7 @@ public class CompilationSpec {
*
* @param pattern regex or non-regex pattern string
*/
public void addCompileOnlyPattern(String pattern) {
void addCompileOnlyPattern(String pattern) {
if (pattern.contains("*")) {
compileOnlyPatterns.add(Pattern.compile(pattern));
} else {
@ -64,7 +64,7 @@ public class CompilationSpec {
*
* @param pattern regex or non-regex pattern string
*/
public void addExcludePattern(String pattern) {
void addExcludePattern(String pattern) {
if (pattern.contains("*")) {
excludePatterns.add(Pattern.compile(pattern));
} else {
@ -78,14 +78,14 @@ public class CompilationSpec {
* @param method method to be checked
* @return true or false
*/
public boolean shouldCompileMethod(ResolvedJavaMethod method) {
boolean shouldCompileMethod(ResolvedJavaMethod method) {
if (compileWithRestrictions()) {
// If there are user-specified compileOnly patterns, default action
// is not to compile the method.
boolean compileMethod = compileOnlyStrings.isEmpty() && compileOnlyPatterns.isEmpty();
// Check if the method matches with any of the specified compileOnly patterns.
String methodName = MiscUtils.uniqueMethodName(method);
String methodName = JavaMethodInfo.uniqueMethodName(method);
// compileOnly
if (!compileMethod) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,104 +37,7 @@ import jdk.vm.ci.code.site.Site;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
public class CompiledMethodInfo {
public static class StubInformation {
int stubOffset; // the offset inside the code (text + stubOffset)
int stubSize; // the stub size
int dispatchJumpOffset; // offset after main dispatch jump instruction
int resolveJumpOffset; // offset after jump instruction to runtime call resolution
// function.
int resolveJumpStart; // offset of jump instruction to VM runtime call resolution
// function.
int c2iJumpOffset; // offset after jump instruction to c2i adapter for static calls.
int movOffset; // offset after move instruction which loads from got cell:
// - Method* for static call
// - Klass* for virtual call
boolean isVirtual; // virtual call stub
// maybe add type of stub as well, right now we only have static stubs
public StubInformation(int stubOffset, boolean isVirtual) {
this.stubOffset = stubOffset;
this.isVirtual = isVirtual;
this.stubSize = -1;
this.movOffset = -1;
this.c2iJumpOffset = -1;
this.resolveJumpOffset = -1;
this.resolveJumpStart = -1;
this.dispatchJumpOffset = -1;
}
public int getOffset() {
return stubOffset;
}
public boolean isVirtual() {
return isVirtual;
}
public void setSize(int stubSize) {
this.stubSize = stubSize;
}
public int getSize() {
return stubSize;
}
public void setMovOffset(int movOffset) {
this.movOffset = movOffset + stubOffset;
}
public int getMovOffset() {
return movOffset;
}
public void setC2IJumpOffset(int c2iJumpOffset) {
this.c2iJumpOffset = c2iJumpOffset + stubOffset;
}
public int getC2IJumpOffset() {
return c2iJumpOffset;
}
public void setResolveJumpOffset(int resolveJumpOffset) {
this.resolveJumpOffset = resolveJumpOffset + stubOffset;
}
public int getResolveJumpOffset() {
return resolveJumpOffset;
}
public void setResolveJumpStart(int resolveJumpStart) {
this.resolveJumpStart = resolveJumpStart + stubOffset;
}
public int getResolveJumpStart() {
return resolveJumpStart;
}
public void setDispatchJumpOffset(int dispatchJumpOffset) {
this.dispatchJumpOffset = dispatchJumpOffset + stubOffset;
}
public int getDispatchJumpOffset() {
return dispatchJumpOffset;
}
public void verify() {
assert stubOffset > 0 : "incorrect stubOffset: " + stubOffset;
assert stubSize > 0 : "incorrect stubSize: " + stubSize;
assert movOffset > 0 : "incorrect movOffset: " + movOffset;
assert dispatchJumpOffset > 0 : "incorrect dispatchJumpOffset: " + dispatchJumpOffset;
assert resolveJumpStart > 0 : "incorrect resolveJumpStart: " + resolveJumpStart;
assert resolveJumpOffset > 0 : "incorrect resolveJumpOffset: " + resolveJumpOffset;
if (!isVirtual) {
assert c2iJumpOffset > 0 : "incorrect c2iJumpOffset: " + c2iJumpOffset;
}
}
}
final class CompiledMethodInfo {
private static final int UNINITIALIZED_OFFSET = -1;
@ -169,7 +72,7 @@ public class CompiledMethodInfo {
*/
private int codeId;
public AOTMethodOffsets() {
AOTMethodOffsets() {
this.nameOffset = UNINITIALIZED_OFFSET;
this.textSectionOffset = UNINITIALIZED_OFFSET;
this.metadataOffset = UNINITIALIZED_OFFSET;
@ -178,7 +81,7 @@ public class CompiledMethodInfo {
this.codeId = -1;
}
protected void addMethodOffsets(ReadOnlyDataContainer container, String name) {
void addMethodOffsets(ReadOnlyDataContainer container, String name) {
verify(name);
// @formatter:off
/*
@ -291,7 +194,7 @@ public class CompiledMethodInfo {
*/
private static final AtomicInteger methodsCount = new AtomicInteger();
public CompiledMethodInfo(CompilationResult compilationResult, JavaMethodInfo methodInfo) {
CompiledMethodInfo(CompilationResult compilationResult, JavaMethodInfo methodInfo) {
this.name = methodInfo.getNameAndSignature();
this.compilationResult = compilationResult;
this.methodInfo = methodInfo;
@ -299,11 +202,11 @@ public class CompiledMethodInfo {
this.methodOffsets = new AOTMethodOffsets();
}
public String name() {
String name() {
return name;
}
public void addMethodOffsets(BinaryContainer binaryContainer, ReadOnlyDataContainer container) {
void addMethodOffsets(BinaryContainer binaryContainer, ReadOnlyDataContainer container) {
this.methodOffsets.setNameOffset(binaryContainer.addMetaspaceName(name));
this.methodOffsets.addMethodOffsets(container, name);
for (AOTKlassData data : dependentKlasses.values()) {
@ -311,15 +214,15 @@ public class CompiledMethodInfo {
}
}
public CompilationResult getCompilationResult() {
CompilationResult getCompilationResult() {
return compilationResult;
}
public JavaMethodInfo getMethodInfo() {
JavaMethodInfo getMethodInfo() {
return methodInfo;
}
public void setTextSectionOffset(int textSectionOffset) {
void setTextSectionOffset(int textSectionOffset) {
methodOffsets.setTextSectionOffset(textSectionOffset);
}
@ -327,66 +230,66 @@ public class CompiledMethodInfo {
return methodOffsets.getTextSectionOffset();
}
public void setCodeId() {
void setCodeId() {
methodOffsets.setCodeId(CompiledMethodInfo.getNextCodeId());
}
public int getCodeId() {
int getCodeId() {
return this.methodOffsets.getCodeId();
}
public static int getMethodsCount() {
static int getMethodsCount() {
return methodsCount.get();
}
public static int getNextCodeId() {
static int getNextCodeId() {
return methodsCount.getAndIncrement();
}
public int getCodeSize() {
int getCodeSize() {
return stubsOffset + getStubCodeSize();
}
public int getStubCodeSize() {
int getStubCodeSize() {
return totalStubSize;
}
public void setMetadataOffset(int offset) {
void setMetadataOffset(int offset) {
this.methodOffsets.setMetadataOffset(offset);
}
/**
* Offset into the code of this method where the stub section starts.
*/
public void setStubsOffset(int offset) {
void setStubsOffset(int offset) {
stubsOffset = offset;
}
public int getStubsOffset() {
int getStubsOffset() {
return stubsOffset;
}
public void setMetadataGotOffset(int metadataGotOffset) {
void setMetadataGotOffset(int metadataGotOffset) {
this.methodOffsets.setMetadataGotOffset(metadataGotOffset);
}
public void setMetadataGotSize(int length) {
void setMetadataGotSize(int length) {
this.methodOffsets.setMetadataGotSize(length);
}
public void addStubCode(String call, StubInformation stub) {
void addStubCode(String call, StubInformation stub) {
stubs.put(call, stub);
totalStubSize += stub.getSize();
}
public StubInformation getStubFor(String call) {
StubInformation getStubFor(String call) {
StubInformation stub = stubs.get(call);
assert stub != null : "missing stub for call " + call;
stub.verify();
return stub;
}
public void addDependentKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
void addDependentKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
AOTKlassData klassData = AOTCompiledClass.addFingerprintKlassData(binaryContainer, type);
String klassName = type.getName();
@ -397,11 +300,11 @@ public class CompiledMethodInfo {
}
}
public AOTKlassData getDependentKlassData(String klassName) {
AOTKlassData getDependentKlassData(String klassName) {
return dependentKlasses.get(klassName);
}
public boolean hasMark(Site call, MarkId id) {
boolean hasMark(Site call, MarkId id) {
for (Mark m : compilationResult.getMarks()) {
// TODO: X64-specific code.
// Call instructions are aligned to 8
@ -415,11 +318,11 @@ public class CompiledMethodInfo {
return false;
}
public String asTag() {
String asTag() {
return "[" + methodInfo.getSymbolName() + "]";
}
public HotSpotCompiledCode compiledCode() {
HotSpotCompiledCode compiledCode() {
if (code == null) {
code = methodInfo.compiledCode(compilationResult);
}
@ -427,12 +330,12 @@ public class CompiledMethodInfo {
}
// Free memory
public void clear() {
void clear() {
this.dependentKlasses = null;
this.name = null;
}
public void clearCompileData() {
void clearCompileData() {
this.code = null;
this.stubs = null;
this.compilationResult = null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,7 +31,7 @@ import java.util.Map.Entry;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.HeaderContainer;
import jdk.tools.jaotc.utils.Timer;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
@ -42,7 +42,7 @@ import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.hotspot.VMField;
class DataBuilder {
final class DataBuilder {
private final Main main;
@ -55,9 +55,9 @@ class DataBuilder {
*/
private final BinaryContainer binaryContainer;
private final HashMap<Long, String> vmAddresses = new HashMap<>();
private static final HashMap<Long, String> vmAddresses = new HashMap<>();
public DataBuilder(Main main, HotSpotHostBackend backend, List<AOTCompiledClass> classes, BinaryContainer binaryContainer) {
DataBuilder(Main main, HotSpotHostBackend backend, List<AOTCompiledClass> classes, BinaryContainer binaryContainer) {
this.main = main;
this.backend = backend;
this.classes = classes;
@ -68,7 +68,7 @@ class DataBuilder {
/**
* Returns a value-name map of all {@link VMField} fields.
*/
private void fillVMAddresses(HotSpotVMConfigStore config) {
private static void fillVMAddresses(HotSpotVMConfigStore config) {
for (VMField vmField : config.getFields().values()) {
if (vmField.value != null && vmField.value instanceof Long) {
final long address = (Long) vmField.value;
@ -98,7 +98,7 @@ class DataBuilder {
* @param address native address
* @return C/C++ functio name associated with the native address
*/
public String getVMFunctionNameForAddress(long address) {
static String getVMFunctionNameForAddress(long address) {
return vmAddresses.get(address);
}
@ -107,7 +107,7 @@ class DataBuilder {
*
* @return host backend
*/
public HotSpotHostBackend getBackend() {
HotSpotHostBackend getBackend() {
return backend;
}
@ -116,7 +116,7 @@ class DataBuilder {
*
* @return binary container
*/
public BinaryContainer getBinaryContainer() {
BinaryContainer getBinaryContainer() {
return binaryContainer;
}
@ -128,7 +128,7 @@ class DataBuilder {
* @throws Exception
*/
@SuppressWarnings("try")
public void prepareData(DebugContext debug) throws Exception {
void prepareData(DebugContext debug) throws Exception {
try (Timer t = new Timer(main, "Parsing compiled code")) {
/*
* Copy compiled code into code section container and calls stubs (PLT trampoline).
@ -147,7 +147,7 @@ class DataBuilder {
// Free memory!
try (Timer t = main.options.verbose ? new Timer(main, "Freeing memory") : null) {
main.printMemoryUsage();
main.printer.printMemoryUsage();
System.gc();
}
@ -163,7 +163,7 @@ class DataBuilder {
// Free memory!
try (Timer t = main.options.verbose ? new Timer(main, "Freeing memory") : null) {
main.printMemoryUsage();
main.printer.printMemoryUsage();
System.gc();
}
@ -172,7 +172,7 @@ class DataBuilder {
}
try (Timer t = new Timer(main, "Preparing compiled binary")) {
// Should be called after Stubs because they can set dependent klasses.
prepareCompiledBinary(metadataBuilder);
prepareCompiledBinary();
}
}
@ -203,7 +203,7 @@ class DataBuilder {
/**
* Prepare metaspace.offsets section.
*/
private void prepareCompiledBinary(MetadataBuilder metadataBuilder) {
private void prepareCompiledBinary() {
for (AOTCompiledClass c : classes) {
// Create records for compiled AOT methods.
c.putMethodsData(binaryContainer);
@ -216,8 +216,8 @@ class DataBuilder {
header.setClassesCount(AOTCompiledClass.getClassesCount());
header.setMethodsCount(CompiledMethodInfo.getMethodsCount());
// Record size of got sections
ByteContainer bc = binaryContainer.getMetaspaceGotContainer();
header.setMetaspaceGotSize((bc.getByteStreamSize() / 8));
ByteContainer bc = binaryContainer.getKlassesGotContainer();
header.setKlassesGotSize((bc.getByteStreamSize() / 8));
bc = binaryContainer.getMetadataGotContainer();
header.setMetadataGotSize((bc.getByteStreamSize() / 8));
bc = binaryContainer.getOopGotContainer();
@ -232,7 +232,7 @@ class DataBuilder {
// them.
ArrayList<CompiledMethodInfo> compiledStubs = compiledClass.getCompiledMethods();
int cntStubs = compiledStubs.size();
binaryContainer.addMethodsCount(cntStubs, binaryContainer.getStubsOffsetsContainer());
BinaryContainer.addMethodsCount(cntStubs, binaryContainer.getStubsOffsetsContainer());
for (CompiledMethodInfo methodInfo : compiledStubs) {
// Note, stubs have different offsets container.
methodInfo.addMethodOffsets(binaryContainer, binaryContainer.getStubsOffsetsContainer());

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,6 @@ import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.AOTCompiledClass.AOTKlassData;
import org.graalvm.compiler.code.DataSection;
import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
@ -47,7 +46,7 @@ import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.hotspot.HotSpotSentinelConstant;
import jdk.vm.ci.meta.VMConstant;
class DataPatchProcessor {
final class DataPatchProcessor {
private final TargetDescription target;
@ -89,9 +88,9 @@ class DataPatchProcessor {
gotName = ((action == HotSpotConstantLoadAction.INITIALIZE) ? "got.init." : "got.") + targetSymbol;
methodInfo.addDependentKlassData(binaryContainer, type);
} else if (metaspaceConstant.asResolvedJavaMethod() != null && action == HotSpotConstantLoadAction.LOAD_COUNTERS) {
targetSymbol = "counters." + MiscUtils.uniqueMethodName(metaspaceConstant.asResolvedJavaMethod());
targetSymbol = "counters." + JavaMethodInfo.uniqueMethodName(metaspaceConstant.asResolvedJavaMethod());
gotName = "got." + targetSymbol;
binaryContainer.addMetaspaceSymbol(targetSymbol);
binaryContainer.addCountersSymbol(targetSymbol);
}
} else if (constant instanceof HotSpotObjectConstant) {
// String constant.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
package jdk.tools.jaotc;
import jdk.tools.jaotc.CompiledMethodInfo.StubInformation;
import jdk.tools.jaotc.StubInformation;
import jdk.tools.jaotc.amd64.AMD64ELFMacroAssembler;
import jdk.vm.ci.amd64.AMD64;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,21 +37,20 @@ import jdk.vm.ci.code.site.Call;
*/
final class ForeignCallSiteRelocationInfo extends CallSiteRelocationInfo {
ForeignCallSiteRelocationInfo(Call call, HotSpotForeignCallLinkage callTarget, DataBuilder dataBuilder) {
super(getTargetSymbol(call, callTarget, dataBuilder), getRelocType(callTarget));
ForeignCallSiteRelocationInfo(Call call, HotSpotForeignCallLinkage callTarget) {
super(getTargetSymbol(call, callTarget), getRelocType(callTarget));
}
private static String getTargetSymbol(Call call, HotSpotForeignCallLinkage callTarget, DataBuilder dataBuilder) {
private static String getTargetSymbol(Call call, HotSpotForeignCallLinkage callTarget) {
// If it specifies a foreign call linkage, find the symbol corresponding to the address in
// HotSpotVMConfig's fields.
final long foreignCallTargetAddress = callTarget.getAddress();
// Get the C/C++ function name associated with the foreign call target address.
String functionName = dataBuilder.getVMFunctionNameForAddress(foreignCallTargetAddress);
String functionName = DataBuilder.getVMFunctionNameForAddress(foreignCallTargetAddress);
if (functionName != null) {
// Use the known global AOT symbol associated with function name, if one exists
BinaryContainer binaryContainer = dataBuilder.getBinaryContainer();
String aotSymbol = binaryContainer.getAOTSymbolForVMFunctionName(functionName);
String aotSymbol = BinaryContainer.getAOTSymbolForVMFunctionName(functionName);
if (aotSymbol == null) {
throw new InternalError("no global symbol found for: " + functionName);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,7 @@ import jdk.tools.jaotc.binformat.Symbol.Kind;
*/
final class ForeignCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
public ForeignCallSiteRelocationSymbol(CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
ForeignCallSiteRelocationSymbol(CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
super(binaryContainer.createSymbol(0, Kind.NATIVE_FUNCTION, Binding.GLOBAL, 0, callSiteRelocation.targetSymbol));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,7 @@ import jdk.vm.ci.code.site.Call;
final class ForeignGotCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
public ForeignGotCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, DataBuilder dataBuilder) {
ForeignGotCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, DataBuilder dataBuilder) {
super(createPltSymbol(dataBuilder, mi, call, callSiteRelocation));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -45,7 +45,7 @@ import org.graalvm.compiler.hotspot.word.MetaspacePointer;
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.word.WordBase;
public class GraalFilters {
final class GraalFilters {
private List<ResolvedJavaType> specialClasses;
private List<ResolvedJavaType> specialArgumentAndReturnTypes;
@ -57,7 +57,7 @@ public class GraalFilters {
skipAnnotations.add(MethodSubstitution.class);
}
public boolean shouldCompileMethod(ResolvedJavaMethod method) {
boolean shouldCompileMethod(ResolvedJavaMethod method) {
// NodeIntrinsics cannot be compiled.
if (hasExcludedAnnotation(method)) {
return false;
@ -83,7 +83,7 @@ public class GraalFilters {
return false;
}
public boolean shouldCompileAnyMethodInClass(ResolvedJavaType klass) {
boolean shouldCompileAnyMethodInClass(ResolvedJavaType klass) {
if (specialClasses.stream().filter(s -> s.isAssignableFrom(klass)).findAny().isPresent()) {
return false;
}
@ -113,7 +113,7 @@ public class GraalFilters {
specialArgumentAndReturnTypes = getSpecialArgumentAndReturnTypes(metaAccess);
}
public boolean shouldIgnoreException(Throwable e) {
static boolean shouldIgnoreException(Throwable e) {
if (e instanceof GraalError) {
String m = e.getMessage();
if (m.contains("ArrayKlass::_component_mirror")) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,16 +28,14 @@ import jdk.tools.jaotc.binformat.Relocation;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
import jdk.vm.ci.code.BytecodePosition;
import jdk.vm.ci.code.DebugInfo;
import jdk.vm.ci.code.VirtualObject;
import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.code.site.Infopoint;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.meta.InvokeTarget;
class InfopointProcessor {
final class InfopointProcessor {
private final DataBuilder dataBuilder;
@ -70,9 +68,13 @@ class InfopointProcessor {
default:
throw new InternalError("Unknown info point reason: " + info.reason);
}
if (info.debugInfo == null) return;
if (info.debugInfo == null) {
return;
}
BytecodePosition bcp = info.debugInfo.getBytecodePosition();
if (bcp == null) return;
if (bcp == null) {
return;
}
recordScopeKlasses(methodInfo, bcp, info.debugInfo.getVirtualObjectMapping());
}
@ -82,14 +84,15 @@ class InfopointProcessor {
recordScopeKlasses(methodInfo, caller, vos);
}
HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod)bcp.getMethod();
HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod) bcp.getMethod();
HotSpotResolvedObjectType klass = m.getDeclaringClass();
methodInfo.addDependentKlassData(binaryContainer, klass);
if (vos == null) return;
if (vos == null) {
return;
}
for (VirtualObject vo : vos) {
HotSpotResolvedObjectType vk = (HotSpotResolvedObjectType)vo.getType();
HotSpotResolvedObjectType vk = (HotSpotResolvedObjectType) vo.getType();
methodInfo.addDependentKlassData(binaryContainer, vk);
}
@ -116,12 +119,12 @@ class InfopointProcessor {
/**
* Get information about the call site. Name of the callee and relocation call type.
*/
private CallSiteRelocationInfo getCallSiteRelocationInfo(Call call) {
private static CallSiteRelocationInfo getCallSiteRelocationInfo(Call call) {
InvokeTarget callTarget = call.target;
if (callTarget instanceof HotSpotResolvedJavaMethod) {
return new JavaCallSiteRelocationInfo(call, (HotSpotResolvedJavaMethod) callTarget);
} else if (callTarget instanceof HotSpotForeignCallLinkage) {
return new ForeignCallSiteRelocationInfo(call, (HotSpotForeignCallLinkage) callTarget, dataBuilder);
return new ForeignCallSiteRelocationInfo(call, (HotSpotForeignCallLinkage) callTarget);
} else {
throw new InternalError("Unhandled call type found in infopoint: " + callTarget);
}
@ -136,10 +139,6 @@ class InfopointProcessor {
return new StubDirectCallSiteRelocationSymbol(callSiteRelocation, binaryContainer);
case FOREIGN_CALL_INDIRECT_GOT:
return new ForeignGotCallSiteRelocationSymbol(mi, call, callSiteRelocation, dataBuilder);
case FOREIGN_CALL_DIRECT:
case FOREIGN_CALL_DIRECT_FAR:
case FOREIGN_CALL_INDIRECT:
return new ForeignCallSiteRelocationSymbol(callSiteRelocation, binaryContainer);
default:
return new JavaCallSiteRelocationSymbol(mi, call, callSiteRelocation, binaryContainer);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,8 +34,8 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
*/
final class JavaCallSiteRelocationInfo extends CallSiteRelocationInfo {
public JavaCallSiteRelocationInfo(Call call, HotSpotResolvedJavaMethod callTarget) {
super(MiscUtils.uniqueMethodName(callTarget), call.direct ? RelocType.JAVA_CALL_DIRECT : RelocType.JAVA_CALL_INDIRECT);
JavaCallSiteRelocationInfo(Call call, HotSpotResolvedJavaMethod callTarget) {
super(JavaMethodInfo.uniqueMethodName(callTarget), call.direct ? RelocType.JAVA_CALL_DIRECT : RelocType.JAVA_CALL_INDIRECT);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@ package jdk.tools.jaotc;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.Symbol;
import jdk.tools.jaotc.CompiledMethodInfo.StubInformation;
import jdk.tools.jaotc.StubInformation;
import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@ -40,7 +40,7 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
// -1 represents Universe::non_oop_word() value
private static final byte[] minusOneSlot = {-1, -1, -1, -1, -1, -1, -1, -1};
public JavaCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
JavaCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
super(createPltEntrySymbol(binaryContainer, mi, call, callSiteRelocation));
StubInformation stub = getStub(mi, call);
addRelocations(mi, stub, binaryContainer, call, callSiteRelocation);
@ -61,7 +61,7 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
private static StubInformation getStub(CompiledMethodInfo mi, Call call) {
HotSpotResolvedJavaMethod callTarget = (HotSpotResolvedJavaMethod) call.target;
String callTargetSymbol = MiscUtils.uniqueMethodName(callTarget) + ".at." + call.pcOffset;
String callTargetSymbol = JavaMethodInfo.uniqueMethodName(callTarget) + ".at." + call.pcOffset;
return mi.getStubFor(callTargetSymbol);
}
@ -69,7 +69,7 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
* Add all the required relocations.
*/
private static void addRelocations(CompiledMethodInfo mi, StubInformation stub, BinaryContainer binaryContainer, Call call, CallSiteRelocationInfo callSiteRelocation) {
final boolean isVirtualCall = MiscUtils.isVirtualCall(mi, call);
final boolean isVirtualCall = CallInfo.isVirtualCall(mi, call);
final int gotStartOffset = binaryContainer.appendExtLinkageGotBytes(zeroSlot, 0, zeroSlot.length);
if (isVirtualCall) {
@ -82,7 +82,7 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
// Add relocation to GOT cell for call resolution jump.
// This GOT cell will be initialized during JVM startup with address
// of JVM runtime call resolution function.
String gotSymbolName = "got." + getResolveSymbolName(binaryContainer, mi, call);
String gotSymbolName = "got." + getResolveSymbolName(mi, call);
Symbol gotSymbol = binaryContainer.getGotSymbol(gotSymbolName);
addExternalPltToGotRelocation(binaryContainer, gotSymbol, stub.getResolveJumpOffset());
@ -121,16 +121,16 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
/**
* Returns the name of the resolve method for this particular call.
*/
private static String getResolveSymbolName(BinaryContainer binaryContainer, CompiledMethodInfo mi, Call call) {
private static String getResolveSymbolName(CompiledMethodInfo mi, Call call) {
String resolveSymbolName;
if (MiscUtils.isStaticCall(call)) {
resolveSymbolName = binaryContainer.getResolveStaticEntrySymbolName();
} else if (MiscUtils.isSpecialCall(call)) {
resolveSymbolName = binaryContainer.getResolveOptVirtualEntrySymbolName();
} else if (MiscUtils.isOptVirtualCall(mi, call)) {
resolveSymbolName = binaryContainer.getResolveOptVirtualEntrySymbolName();
} else if (MiscUtils.isVirtualCall(mi, call)) {
resolveSymbolName = binaryContainer.getResolveVirtualEntrySymbolName();
if (CallInfo.isStaticCall(call)) {
resolveSymbolName = BinaryContainer.getResolveStaticEntrySymbolName();
} else if (CallInfo.isSpecialCall(call)) {
resolveSymbolName = BinaryContainer.getResolveOptVirtualEntrySymbolName();
} else if (CallInfo.isOptVirtualCall(mi, call)) {
resolveSymbolName = BinaryContainer.getResolveOptVirtualEntrySymbolName();
} else if (CallInfo.isVirtualCall(mi, call)) {
resolveSymbolName = BinaryContainer.getResolveVirtualEntrySymbolName();
} else {
throw new InternalError("Unknown call type in " + mi.asTag() + " @ " + call.pcOffset + " for call" + call.target);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,9 +24,11 @@
package jdk.tools.jaotc;
import org.graalvm.compiler.code.CompilationResult;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
public interface JavaMethodInfo {
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
interface JavaMethodInfo {
/**
* @return unique symbol name for this method.
@ -42,4 +44,16 @@ public interface JavaMethodInfo {
HotSpotCompiledCode compiledCode(CompilationResult result);
/**
* Name a java method with class and signature to make it unique.
*
* @param method to generate unique identifier for
* @return Unique name for this method including class and signature
**/
static String uniqueMethodName(ResolvedJavaMethod method) {
String className = method.getDeclaringClass().toClassName();
String name = className + "." + method.getName() + method.getSignature().toMethodDescriptor();
return name;
}
}

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Stream;
final class Linker {
private final Options options;
private String objectFileName;
private String libraryFileName;
private String linkerCmd;
String objFile() {
return objectFileName;
}
String libFile() {
return libraryFileName;
}
Linker(Main main) throws Exception {
this.options = main.options;
String name = options.outputName;
objectFileName = name;
libraryFileName = name;
if (options.linkerpath != null && !(new File(options.linkerpath).exists())) {
throw new InternalError("Invalid linker path: " + options.linkerpath);
}
String linkerPath;
String linkerCheck;
switch (options.osName) {
case "Linux":
if (name.endsWith(".so")) {
objectFileName = name.substring(0, name.length() - ".so".length());
}
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
linkerCheck = linkerPath + " -v";
break;
case "SunOS":
if (name.endsWith(".so")) {
objectFileName = name.substring(0, name.length() - ".so".length());
}
objectFileName = objectFileName + ".o";
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName;
linkerCheck = linkerPath + " -V";
break;
case "Mac OS X":
if (name.endsWith(".dylib")) {
objectFileName = name.substring(0, name.length() - ".dylib".length());
}
objectFileName = objectFileName + ".o";
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName;
linkerCheck = linkerPath + " -v";
break;
default:
if (options.osName.startsWith("Windows")) {
if (name.endsWith(".dll")) {
objectFileName = name.substring(0, name.length() - ".dll".length());
}
objectFileName = objectFileName + ".obj";
linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath();
if (linkerPath == null) {
throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe");
}
linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName;
linkerCheck = null; // link.exe presence is verified already
break;
} else {
throw new InternalError("Unsupported platform: " + options.osName);
}
}
// Check linker presence on platforms by printing its version
if (linkerCheck != null) {
Process p = Runtime.getRuntime().exec(linkerCheck);
final int exitCode = p.waitFor();
if (exitCode != 0) {
InputStream stderr = p.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(stderr));
Stream<String> lines = br.lines();
StringBuilder sb = new StringBuilder();
lines.iterator().forEachRemaining(e -> sb.append(e));
throw new InternalError(sb.toString());
}
}
}
void link() throws Exception {
Process p = Runtime.getRuntime().exec(linkerCmd);
final int exitCode = p.waitFor();
if (exitCode != 0) {
InputStream stderr = p.getErrorStream();
if (stderr.read() == -1) {
stderr = p.getInputStream();
}
BufferedReader br = new BufferedReader(new InputStreamReader(stderr));
Stream<String> lines = br.lines();
StringBuilder sb = new StringBuilder();
lines.iterator().forEachRemaining(e -> sb.append(e));
throw new InternalError(sb.toString());
}
File objFile = new File(objectFileName);
if (objFile.exists()) {
if (!objFile.delete()) {
throw new InternalError("Failed to delete " + objectFileName + " file");
}
}
// Make non-executable for all.
File libFile = new File(libraryFileName);
if (libFile.exists() && !options.osName.startsWith("Windows")) {
if (!libFile.setExecutable(false, false)) {
throw new InternalError("Failed to change attribute for " + libraryFileName + " file");
}
}
}
/**
* Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012
*/
public enum VSVERSIONS {
VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe");
private final String envvariable;
private final String wkp;
VSVERSIONS(String envvariable, String wellknownpath) {
this.envvariable = envvariable;
this.wkp = wellknownpath;
}
String EnvVariable() {
return envvariable;
}
String WellKnownPath() {
return wkp;
}
}
/**
* Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012
*/
private static String getWindowsLinkPath() {
String link = "\\VC\\bin\\amd64\\link.exe";
/**
* First try searching the paths pointed to by the VS environment variables.
*/
for (VSVERSIONS vs : VSVERSIONS.values()) {
String vspath = System.getenv(vs.EnvVariable());
if (vspath != null) {
File commonTools = new File(vspath);
File vsRoot = commonTools.getParentFile().getParentFile();
File linkPath = new File(vsRoot, link);
if (linkPath.exists()) {
return linkPath.getPath();
}
}
}
/**
* If we didn't find via the VS environment variables, try the well known paths
*/
for (VSVERSIONS vs : VSVERSIONS.values()) {
String wkp = vs.WellKnownPath();
if (new File(wkp).exists()) {
return wkp;
}
}
return null;
}
}

View File

@ -1,4 +1,4 @@
package jdk.tools.jaotc;/*
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -21,6 +21,8 @@ package jdk.tools.jaotc;/*
* questions.
*/
package jdk.tools.jaotc;
public class LoadedClass {
private final String name;
private final Class<?> clz;
@ -45,12 +47,17 @@ public class LoadedClass {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof LoadedClass)) return false;
if (this == o) {
return true;
}
if (!(o instanceof LoadedClass)) {
return false;
}
LoadedClass that = (LoadedClass) o;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) {
return false;
}
return clz != null ? clz.equals(that.clz) : that.clz == null;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,12 +23,174 @@
package jdk.tools.jaotc;
public interface LogPrinter {
void printInfo(String s);
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Date;
void printlnVerbose(String s);
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.BinaryContainer;
void printlnInfo(String s);
final class LogPrinter {
private static FileWriter logFile = null;
private final Options options;
private final PrintWriter log;
LogPrinter(Main main, PrintWriter log) {
this.options = main.options;
this.log = log;
}
void printInfo(String message) {
if (options.info) {
log.print(message);
log.flush();
}
}
void printlnInfo(String message) {
if (options.info) {
log.println(message);
log.flush();
}
}
void printVerbose(String message) {
if (options.verbose) {
log.print(message);
log.flush();
}
}
void printlnVerbose(String message) {
if (options.verbose) {
log.println(message);
log.flush();
}
}
void printDebug(String message) {
if (options.debug) {
log.print(message);
log.flush();
}
}
void printlnDebug(String message) {
if (options.debug) {
log.println(message);
log.flush();
}
}
void printError(String message) {
log.println("Error: " + message);
log.flush();
}
void reportError(Throwable e) {
log.println("Error: " + e.getMessage());
if (options.info) {
e.printStackTrace(log);
}
log.flush();
}
void reportError(String key, Object... args) {
printError(MessageFormat.format(key, args));
}
private static String humanReadableByteCount(long bytes) {
int unit = 1024;
if (bytes < unit) {
return bytes + " B";
}
int exp = (int) (Math.log(bytes) / Math.log(unit));
char pre = "KMGTPE".charAt(exp - 1);
return String.format("%.1f %cB", bytes / Math.pow(unit, exp), pre);
}
void printMemoryUsage() {
if (options.verbose) {
MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
log.format(" [used: %-7s, comm: %-7s, freeRatio ~= %.1f%%]",
humanReadableByteCount(memusage.getUsed()),
humanReadableByteCount(memusage.getCommitted()),
freeratio * 100);
}
}
private void printContainerInfo(ByteContainer container) {
printlnVerbose(container.getContainerName() + ": " + container.getByteStreamSize() + " bytes");
}
void containersInfo(BinaryContainer binaryContainer) {
printContainerInfo(binaryContainer.getHeaderContainer().getContainer());
printContainerInfo(binaryContainer.getConfigContainer());
printContainerInfo(binaryContainer.getKlassesOffsetsContainer());
printContainerInfo(binaryContainer.getMethodsOffsetsContainer());
printContainerInfo(binaryContainer.getKlassesDependenciesContainer());
printContainerInfo(binaryContainer.getStubsOffsetsContainer());
printContainerInfo(binaryContainer.getMethodMetadataContainer());
printContainerInfo(binaryContainer.getCodeContainer());
printContainerInfo(binaryContainer.getCodeSegmentsContainer());
printContainerInfo(binaryContainer.getConstantDataContainer());
printContainerInfo(binaryContainer.getKlassesGotContainer());
printContainerInfo(binaryContainer.getCountersGotContainer());
printContainerInfo(binaryContainer.getMetadataGotContainer());
printContainerInfo(binaryContainer.getMethodStateContainer());
printContainerInfo(binaryContainer.getOopGotContainer());
printContainerInfo(binaryContainer.getMetaspaceNamesContainer());
}
static void openLog() {
int v = Integer.getInteger("jdk.tools.jaotc.logCompilation", 0);
if (v == 0) {
logFile = null;
return;
}
// Create log file in current directory
String fileName = "aot_compilation" + new Date().getTime() + ".log";
Path logFilePath = Paths.get("./", fileName);
String logFileName = logFilePath.toString();
try {
// Create file to which we do not append
logFile = new FileWriter(logFileName, false);
} catch (IOException e) {
System.out.println("Unable to open logfile :" + logFileName + "\nNo logs will be created");
logFile = null;
}
}
static void writeLog(String str) {
if (logFile != null) {
try {
logFile.write(str + "\n");
logFile.flush();
} catch (IOException e) {
// Print to console
System.out.println(str + "\n");
}
}
}
static void closeLog() {
if (logFile != null) {
try {
logFile.close();
} catch (IOException e) {
// Do nothing
}
}
}
void printError(String s);
}

View File

@ -27,37 +27,14 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.stream.Stream;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.collect.*;
import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
import jdk.tools.jaotc.collect.jar.JarSourceProvider;
import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
import jdk.tools.jaotc.utils.Timer;
import jdk.tools.jaotc.Options.Option;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
@ -80,227 +57,14 @@ import org.graalvm.compiler.runtime.RuntimeProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.runtime.JVMCI;
public class Main implements LogPrinter {
static class BadArgs extends Exception {
private static final long serialVersionUID = 1L;
final String key;
final Object[] args;
boolean showUsage;
public final class Main {
BadArgs(String key, Object... args) {
super(MessageFormat.format(key, args));
this.key = key;
this.args = args;
}
BadArgs showUsage(boolean b) {
showUsage = b;
return this;
}
}
abstract static class Option {
final String help;
final boolean hasArg;
final String[] aliases;
Option(String help, boolean hasArg, String... aliases) {
this.help = help;
this.hasArg = hasArg;
this.aliases = aliases;
}
boolean isHidden() {
return false;
}
boolean matches(String opt) {
for (String a : aliases) {
if (a.equals(opt)) {
return true;
} else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
return true;
}
}
return false;
}
boolean ignoreRest() {
return false;
}
abstract void process(Main task, String opt, String arg) throws BadArgs;
}
static Option[] recognizedOptions = {new Option(" --output <file> Output file name", true, "--output") {
@Override
void process(Main task, String opt, String arg) {
String name = arg;
task.options.outputName = name;
}
}, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
}
}, new Option(" --jar <jarfiles> List of jar files to compile", true, "--jar") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
}
}, new Option(" --module <modules> List of modules to compile", true, "--module") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
}
}, new Option(" --directory <dirs> List of directories where to search for files to compile", true, "--directory") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
}
}, new Option(" --search-path <dirs> List of directories where to search for specified files", true, "--search-path") {
@Override
void process(Main task, String opt, String arg) {
String[] elements = arg.split(":");
task.options.searchPath.add(elements);
}
}, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") {
@Override
void process(Main task, String opt, String arg) {
task.options.methodList = arg;
}
}, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
@Override
void process(Main task, String opt, String arg) {
task.options.tiered = true;
}
}, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") {
@Override
void process(Main task, String opt, String arg) {
task.options.compileWithAssertions = true;
}
}, new Option(" --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") {
@Override
void process(Main task, String opt, String arg) {
int threads = Integer.parseInt(arg);
final int available = Runtime.getRuntime().availableProcessors();
if (threads <= 0) {
task.warning("invalid number of threads specified: {0}, using: {1}", threads, available);
threads = available;
}
if (threads > available) {
task.warning("too many threads specified: {0}, limiting to: {1}", threads, available);
}
task.options.threads = Integer.min(threads, available);
}
}, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") {
@Override
void process(Main task, String opt, String arg) {
task.options.ignoreClassLoadingErrors = true;
}
}, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") {
@Override
void process(Main task, String opt, String arg) {
task.options.exitOnError = true;
}
}, new Option(" --info Print information during compilation", false, "--info") {
@Override
void process(Main task, String opt, String arg) throws BadArgs {
task.options.info = true;
}
}, new Option(" --verbose Print verbose information", false, "--verbose") {
@Override
void process(Main task, String opt, String arg) throws BadArgs {
task.options.info = true;
task.options.verbose = true;
}
}, new Option(" --debug Print debug information", false, "--debug") {
@Override
void process(Main task, String opt, String arg) throws BadArgs {
task.options.info = true;
task.options.verbose = true;
task.options.debug = true;
}
}, new Option(" --help Print this usage message", false, "--help") {
@Override
void process(Main task, String opt, String arg) {
task.options.help = true;
}
}, new Option(" --version Version information", false, "--version") {
@Override
void process(Main task, String opt, String arg) {
task.options.version = true;
}
}, new Option(" --linker-path Full path to linker executable", true, "--linker-path") {
@Override
void process(Main task, String opt, String arg) {
task.options.linkerpath = arg;
}
}, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") {
@Override
void process(Main task, String opt, String arg) {
}
}};
public static class Options {
public List<SearchFor> files = new LinkedList<>();
public String outputName = defaultOutputName();
public String methodList;
public List<ClassSource> sources = new ArrayList<>();
public String linkerpath = null;
public SearchPath searchPath = new SearchPath();
/**
* We don't see scaling beyond 16 threads.
*/
private static final int COMPILER_THREADS = 16;
public int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
public boolean ignoreClassLoadingErrors;
public boolean exitOnError;
public boolean info;
public boolean verbose;
public boolean debug;
public boolean help;
public boolean version;
public boolean compileWithAssertions;
public boolean tiered;
private static String defaultOutputName() {
String osName = System.getProperty("os.name");
String name = "unnamed.";
String ext;
switch (osName) {
case "Linux":
case "SunOS":
ext = "so";
break;
case "Mac OS X":
ext = "dylib";
break;
default:
if (osName.startsWith("Windows")) {
ext = "dll";
} else {
ext = "so";
}
}
return name + ext;
}
}
/* package */final Options options = new Options();
/**
* Logfile.
*/
private static FileWriter logFile = null;
final Options options = new Options();
private PrintWriter log;
LogPrinter printer;
GraalFilters filters;
private static final int EXIT_OK = 0; // No errors.
private static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches.
@ -317,12 +81,11 @@ public class Main implements LogPrinter {
}
private int run(String[] args) {
if (log == null) {
log = new PrintWriter(System.out);
}
log = new PrintWriter(System.out);
printer = new LogPrinter(this, log);
try {
handleOptions(args);
Options.handleOptions(this, args);
if (options.help) {
showHelp();
return EXIT_OK;
@ -332,17 +95,17 @@ public class Main implements LogPrinter {
return EXIT_OK;
}
printlnInfo("Compiling " + options.outputName + "...");
printer.printlnInfo("Compiling " + options.outputName + "...");
final long start = System.currentTimeMillis();
if (!run()) {
return EXIT_ABNORMAL;
}
final long end = System.currentTimeMillis();
printlnInfo("Total time: " + (end - start) + " ms");
printer.printlnInfo("Total time: " + (end - start) + " ms");
return EXIT_OK;
} catch (BadArgs e) {
reportError(e.key, e.args);
} catch (Options.BadArgs e) {
printer.reportError(e.key, e.args);
if (e.showUsage) {
showUsage();
}
@ -355,117 +118,20 @@ public class Main implements LogPrinter {
}
}
private static String humanReadableByteCount(long bytes) {
int unit = 1024;
if (bytes < unit) {
return bytes + " B";
}
int exp = (int) (Math.log(bytes) / Math.log(unit));
char pre = "KMGTPE".charAt(exp - 1);
return String.format("%.1f %cB", bytes / Math.pow(unit, exp), pre);
}
void printMemoryUsage() {
if (options.verbose) {
MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
log.format(" [used: %-7s, comm: %-7s, freeRatio ~= %.1f%%]",
humanReadableByteCount(memusage.getUsed()),
humanReadableByteCount(memusage.getCommitted()),
freeratio * 100);
}
}
/**
* Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012
*/
public enum VSVERSIONS {
VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe");
private final String envvariable;
private final String wkp;
VSVERSIONS(String envvariable, String wellknownpath) {
this.envvariable = envvariable;
this.wkp = wellknownpath;
}
String EnvVariable() {
return envvariable;
}
String WellKnownPath() {
return wkp;
}
}
/**
* Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012
*/
private static String getWindowsLinkPath() {
String link = "\\VC\\bin\\amd64\\link.exe";
/**
* First try searching the paths pointed to by the VS environment variables.
*/
for (VSVERSIONS vs : VSVERSIONS.values()) {
String vspath = System.getenv(vs.EnvVariable());
if (vspath != null) {
File commonTools = new File(vspath);
File vsRoot = commonTools.getParentFile().getParentFile();
File linkPath = new File(vsRoot, link);
if (linkPath.exists())
return linkPath.getPath();
}
}
/**
* If we didn't find via the VS environment variables, try the well known paths
*/
for (VSVERSIONS vs : VSVERSIONS.values()) {
String wkp = vs.WellKnownPath();
if (new File(wkp).exists()) {
return wkp;
}
}
return null;
}
@SuppressWarnings("try")
private boolean run() throws Exception {
openLog();
LogPrinter.openLog();
try {
CompilationSpec compilationRestrictions = collectSpecifiedMethods();
Set<Class<?>> classesToCompile = new HashSet<>();
final Linker linker = new Linker(this);
final String objectFileName = linker.objFile();
final Collector collector = new Collector(this);
Set<Class<?>> classesToCompile;
try (Timer t = new Timer(this, "")) {
FileSupport fileSupport = new FileSupport();
ClassSearch lookup = new ClassSearch();
lookup.addProvider(new ModuleSourceProvider());
lookup.addProvider(new ClassNameSourceProvider(fileSupport));
lookup.addProvider(new JarSourceProvider());
lookup.addProvider(new DirectorySourceProvider(fileSupport));
List<LoadedClass> found = null;
try {
found = lookup.search(options.files, options.searchPath);
} catch (InternalError e) {
reportError(e);
return false;
}
for (LoadedClass loadedClass : found) {
classesToCompile.add(loadedClass.getLoadedClass());
}
printInfo(classesToCompile.size() + " classes found");
classesToCompile = collector.collectClassesToCompile();
printer.printInfo(classesToCompile.size() + " classes found");
}
OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
@ -478,23 +144,22 @@ public class Main implements LogPrinter {
HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
GraalFilters filters = new GraalFilters(metaAccess);
filters = new GraalFilters(metaAccess);
List<AOTCompiledClass> classes;
try (Timer t = new Timer(this, "")) {
classes = collectMethodsToCompile(classesToCompile, compilationRestrictions, filters, metaAccess);
classes = collector.collectMethodsToCompile(classesToCompile, metaAccess);
}
// Free memory!
try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
printMemoryUsage();
compilationRestrictions = null;
printer.printMemoryUsage();
classesToCompile = null;
System.gc();
}
AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, filters);
AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend);
SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection();
AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads);
classes = compiler.compileClasses(classes);
@ -506,7 +171,7 @@ public class Main implements LogPrinter {
// Free memory!
try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
printMemoryUsage();
printer.printMemoryUsage();
aotBackend = null;
compiler = null;
System.gc();
@ -520,25 +185,11 @@ public class Main implements LogPrinter {
}
// Print information about section sizes
printContainerInfo(binaryContainer.getHeaderContainer().getContainer());
printContainerInfo(binaryContainer.getConfigContainer());
printContainerInfo(binaryContainer.getKlassesOffsetsContainer());
printContainerInfo(binaryContainer.getMethodsOffsetsContainer());
printContainerInfo(binaryContainer.getKlassesDependenciesContainer());
printContainerInfo(binaryContainer.getStubsOffsetsContainer());
printContainerInfo(binaryContainer.getMethodMetadataContainer());
printContainerInfo(binaryContainer.getCodeContainer());
printContainerInfo(binaryContainer.getCodeSegmentsContainer());
printContainerInfo(binaryContainer.getConstantDataContainer());
printContainerInfo(binaryContainer.getMetaspaceGotContainer());
printContainerInfo(binaryContainer.getMetadataGotContainer());
printContainerInfo(binaryContainer.getMethodStateContainer());
printContainerInfo(binaryContainer.getOopGotContainer());
printContainerInfo(binaryContainer.getMetaspaceNamesContainer());
printer.containersInfo(binaryContainer);
// Free memory!
try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
printMemoryUsage();
printer.printMemoryUsage();
backend = null;
for (AOTCompiledClass aotCompClass : classes) {
aotCompClass.clear();
@ -550,238 +201,59 @@ public class Main implements LogPrinter {
System.gc();
}
String name = options.outputName;
String objectFileName = name;
String libraryFileName = name;
String linkerCmd;
String linkerPath;
String osName = System.getProperty("os.name");
switch (osName) {
case "Linux":
if (name.endsWith(".so")) {
objectFileName = name.substring(0, name.length() - ".so".length());
}
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
break;
case "SunOS":
if (name.endsWith(".so")) {
objectFileName = name.substring(0, name.length() - ".so".length());
}
objectFileName = objectFileName + ".o";
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName;
break;
case "Mac OS X":
if (name.endsWith(".dylib")) {
objectFileName = name.substring(0, name.length() - ".dylib".length());
}
objectFileName = objectFileName + ".o";
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName;
break;
default:
if (osName.startsWith("Windows")) {
if (name.endsWith(".dll")) {
objectFileName = name.substring(0, name.length() - ".dll".length());
}
objectFileName = objectFileName + ".obj";
linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath();
if (linkerPath == null) {
throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe");
}
linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName;
break;
} else {
throw new InternalError("Unsupported platform: " + osName);
}
}
try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
binaryContainer.createBinary(objectFileName, JVM_VERSION);
binaryContainer.createBinary(objectFileName);
}
// Free memory!
try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
printMemoryUsage();
printer.printMemoryUsage();
binaryContainer = null;
System.gc();
}
try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) {
Process p = Runtime.getRuntime().exec(linkerCmd);
final int exitCode = p.waitFor();
if (exitCode != 0) {
InputStream stderr = p.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(stderr));
Stream<String> lines = br.lines();
StringBuilder sb = new StringBuilder();
lines.iterator().forEachRemaining(e -> sb.append(e));
throw new InternalError(sb.toString());
}
File objFile = new File(objectFileName);
if (objFile.exists()) {
if (!objFile.delete()) {
throw new InternalError("Failed to delete " + objectFileName + " file");
}
}
// Make non-executable for all.
File libFile = new File(libraryFileName);
if (libFile.exists() && !osName.startsWith("Windows")) {
if (!libFile.setExecutable(false, false)) {
throw new InternalError("Failed to change attribute for " + libraryFileName + " file");
}
}
try (Timer t = new Timer(this, "Creating shared library: " + linker.libFile())) {
linker.link();
}
printVerbose("Final memory ");
printMemoryUsage();
printlnVerbose("");
printer.printVerbose("Final memory ");
printer.printMemoryUsage();
printer.printlnVerbose("");
} finally {
closeLog();
LogPrinter.closeLog();
}
return true;
}
private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
for (ResolvedJavaMethod m : methods) {
addMethod(aotClass, m, compilationRestrictions, filters);
}
}
void handleError(ResolvedJavaMethod resolvedMethod, Throwable e, String message) {
String methodName = JavaMethodInfo.uniqueMethodName(resolvedMethod);
private void addMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method, CompilationSpec compilationRestrictions, GraalFilters filters) {
// Don't compile native or abstract methods.
if (!method.hasBytecodes()) {
return;
}
if (!compilationRestrictions.shouldCompileMethod(method)) {
return;
}
if (!filters.shouldCompileMethod(method)) {
return;
}
aotClass.addMethod(method);
printlnVerbose(" added " + method.getName() + method.getSignature().toMethodDescriptor());
}
private void printContainerInfo(ByteContainer container) {
printlnVerbose(container.getContainerName() + ": " + container.getByteStreamSize() + " bytes");
}
PrintWriter log;
private void handleOptions(String[] args) throws BadArgs {
if (args.length == 0) {
options.help = true;
return;
}
// Make checkstyle happy.
int i = 0;
for (; i < args.length; i++) {
String arg = args[i];
if (arg.charAt(0) == '-') {
Option option = getOption(arg);
String param = null;
if (option.hasArg) {
if (arg.startsWith("--") && arg.indexOf('=') > 0) {
param = arg.substring(arg.indexOf('=') + 1, arg.length());
} else if (i + 1 < args.length) {
param = args[++i];
}
if (param == null || param.isEmpty() || param.charAt(0) == '-') {
throw new BadArgs("missing argument for option: {0}", arg).showUsage(true);
}
}
option.process(this, arg, param);
if (option.ignoreRest()) {
break;
}
} else {
options.files.add(new SearchFor(arg));
}
}
}
private static Option getOption(String name) throws BadArgs {
for (Option o : recognizedOptions) {
if (o.matches(name)) {
return o;
}
}
throw new BadArgs("unknown option: {0}", name).showUsage(true);
}
public void printInfo(String message) {
if (options.info) {
log.print(message);
log.flush();
}
}
public void printlnInfo(String message) {
if (options.info) {
log.println(message);
log.flush();
}
}
public void printVerbose(String message) {
if (options.verbose) {
log.print(message);
log.flush();
}
}
public void printlnVerbose(String message) {
if (options.verbose) {
log.println(message);
log.flush();
}
}
public void printDebug(String message) {
if (options.debug) {
log.print(message);
log.flush();
printer.printError("Failed compilation: " + methodName + ": " + e);
}
}
public void printlnDebug(String message) {
if (options.debug) {
log.println(message);
log.flush();
// Ignore some exceptions when meta-compiling Graal.
if (GraalFilters.shouldIgnoreException(e)) {
return;
}
}
public void printError(String message) {
log.println("Error: " + message);
log.flush();
}
LogPrinter.writeLog("Failed compilation of method " + methodName + message);
private void reportError(Throwable e) {
log.println("Error: " + e.getMessage());
if (options.info) {
if (!options.debug) {
printer.printError("Failed compilation: " + methodName + ": " + e);
}
if (options.verbose) {
e.printStackTrace(log);
}
log.flush();
if (options.exitOnError) {
System.exit(1);
}
}
private void reportError(String key, Object... args) {
printError(MessageFormat.format(key, args));
}
private void warning(String key, Object... args) {
void warning(String key, Object... args) {
log.println("Warning: " + MessageFormat.format(key, args));
log.flush();
}
@ -789,6 +261,7 @@ public class Main implements LogPrinter {
private void showUsage() {
log.println("Usage: " + PROGNAME + " <options> list");
log.println("use --help for a list of possible options");
log.flush();
}
private void showHelp() {
@ -798,7 +271,7 @@ public class Main implements LogPrinter {
log.println(" or directories which contain class files.");
log.println();
log.println("where options include:");
for (Option o : recognizedOptions) {
for (Option o : Options.recognizedOptions) {
String name = o.aliases[0].substring(1); // there must always be at least one name
name = name.charAt(0) == '-' ? name.substring(1) : name;
if (o.isHidden() || name.equals("h")) {
@ -806,169 +279,10 @@ public class Main implements LogPrinter {
}
log.println(o.help);
}
log.flush();
}
private void showVersion() {
log.println(PROGNAME + " " + JVM_VERSION);
}
/**
* Collect all method we should compile.
*
* @return array list of AOT classes which have compiled methods.
*/
private List<AOTCompiledClass> collectMethodsToCompile(Set<Class<?>> classesToCompile, CompilationSpec compilationRestrictions, GraalFilters filters, MetaAccessProvider metaAccess) {
int total = 0;
int count = 0;
List<AOTCompiledClass> classes = new ArrayList<>();
for (Class<?> c : classesToCompile) {
ResolvedJavaType resolvedJavaType = metaAccess.lookupJavaType(c);
if (filters.shouldCompileAnyMethodInClass(resolvedJavaType)) {
AOTCompiledClass aotClass = new AOTCompiledClass(resolvedJavaType);
printlnVerbose(" Scanning " + c.getName());
// Constructors
try {
ResolvedJavaMethod[] ctors = resolvedJavaType.getDeclaredConstructors();
addMethods(aotClass, ctors, compilationRestrictions, filters);
total += ctors.length;
} catch (Throwable e) {
// If we are running in JCK mode we ignore all exceptions.
if (options.ignoreClassLoadingErrors) {
printError(c.getName() + ": " + e);
} else {
throw new InternalError(e);
}
}
// Methods
try {
ResolvedJavaMethod[] methods = resolvedJavaType.getDeclaredMethods();
addMethods(aotClass, methods, compilationRestrictions, filters);
total += methods.length;
} catch (Throwable e) {
// If we are running in JCK mode we ignore all exceptions.
if (options.ignoreClassLoadingErrors) {
printError(c.getName() + ": " + e);
} else {
throw new InternalError(e);
}
}
// Class initializer
try {
ResolvedJavaMethod clinit = resolvedJavaType.getClassInitializer();
if (clinit != null) {
addMethod(aotClass, clinit, compilationRestrictions, filters);
total++;
}
} catch (Throwable e) {
// If we are running in JCK mode we ignore all exceptions.
if (options.ignoreClassLoadingErrors) {
printError(c.getName() + ": " + e);
} else {
throw new InternalError(e);
}
}
// Found any methods to compile? Add the class.
if (aotClass.hasMethods()) {
classes.add(aotClass);
count += aotClass.getMethodCount();
}
}
}
printInfo(total + " methods total, " + count + " methods to compile");
return classes;
}
/**
* If a file with compilation limitations is specified using the java property
* jdk.tools.jaotc.compile.method.list, read the file's contents and collect the restrictions.
*/
private CompilationSpec collectSpecifiedMethods() {
CompilationSpec compilationRestrictions = new CompilationSpec();
String methodListFileName = options.methodList;
if (methodListFileName != null && !methodListFileName.equals("")) {
try {
FileReader methListFile = new FileReader(methodListFileName);
BufferedReader readBuf = new BufferedReader(methListFile);
String line = null;
while ((line = readBuf.readLine()) != null) {
String trimmedLine = line.trim();
if (!trimmedLine.startsWith("#")) {
String[] components = trimmedLine.split(" ");
if (components.length == 2) {
String directive = components[0];
String pattern = components[1];
switch (directive) {
case "compileOnly":
compilationRestrictions.addCompileOnlyPattern(pattern);
break;
case "exclude":
compilationRestrictions.addExcludePattern(pattern);
break;
default:
System.out.println("Unrecognized command " + directive + ". Ignoring\n\t" + line + "\n encountered in " + methodListFileName);
}
} else {
if (!trimmedLine.equals("")) {
System.out.println("Ignoring malformed line:\n\t " + line + "\n");
}
}
}
}
readBuf.close();
} catch (FileNotFoundException e) {
throw new InternalError("Unable to open method list file: " + methodListFileName, e);
} catch (IOException e) {
throw new InternalError("Unable to read method list file: " + methodListFileName, e);
}
}
return compilationRestrictions;
}
private static void openLog() {
int v = Integer.getInteger("jdk.tools.jaotc.logCompilation", 0);
if (v == 0) {
logFile = null;
return;
}
// Create log file in current directory
String fileName = "aot_compilation" + new Date().getTime() + ".log";
Path logFilePath = Paths.get("./", fileName);
String logFileName = logFilePath.toString();
try {
// Create file to which we do not append
logFile = new FileWriter(logFileName, false);
} catch (IOException e) {
System.out.println("Unable to open logfile :" + logFileName + "\nNo logs will be created");
logFile = null;
}
}
public static void writeLog(String str) {
if (logFile != null) {
try {
logFile.write(str + "\n");
logFile.flush();
} catch (IOException e) {
// Print to console
System.out.println(str + "\n");
}
}
}
public static void closeLog() {
if (logFile != null) {
try {
logFile.close();
} catch (IOException e) {
// Do nothing
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -59,7 +59,7 @@ enum MarkId {
this.value = (int) (long) HotSpotJVMCIRuntime.runtime().getConfigStore().getConstants().get(name);
}
public static MarkId getEnum(int value) {
static MarkId getEnum(int value) {
for (MarkId e : values()) {
if (e.value == value) {
return e;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,7 @@ import jdk.tools.jaotc.binformat.Symbol;
import jdk.vm.ci.code.site.Mark;
class MarkProcessor {
final class MarkProcessor {
private final BinaryContainer binaryContainer;
@ -65,31 +65,31 @@ class MarkProcessor {
switch (markId) {
case POLL_FAR:
case POLL_RETURN_FAR:
vmSymbolName = binaryContainer.getPollingPageSymbolName();
vmSymbolName = BinaryContainer.getPollingPageSymbolName();
break;
case CARD_TABLE_ADDRESS:
vmSymbolName = binaryContainer.getCardTableAddressSymbolName();
vmSymbolName = BinaryContainer.getCardTableAddressSymbolName();
break;
case HEAP_TOP_ADDRESS:
vmSymbolName = binaryContainer.getHeapTopAddressSymbolName();
vmSymbolName = BinaryContainer.getHeapTopAddressSymbolName();
break;
case HEAP_END_ADDRESS:
vmSymbolName = binaryContainer.getHeapEndAddressSymbolName();
vmSymbolName = BinaryContainer.getHeapEndAddressSymbolName();
break;
case NARROW_KLASS_BASE_ADDRESS:
vmSymbolName = binaryContainer.getNarrowKlassBaseAddressSymbolName();
vmSymbolName = BinaryContainer.getNarrowKlassBaseAddressSymbolName();
break;
case NARROW_OOP_BASE_ADDRESS:
vmSymbolName = binaryContainer.getNarrowOopBaseAddressSymbolName();
vmSymbolName = BinaryContainer.getNarrowOopBaseAddressSymbolName();
break;
case CRC_TABLE_ADDRESS:
vmSymbolName = binaryContainer.getCrcTableAddressSymbolName();
vmSymbolName = BinaryContainer.getCrcTableAddressSymbolName();
break;
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
vmSymbolName = binaryContainer.getLogOfHeapRegionGrainBytesSymbolName();
vmSymbolName = BinaryContainer.getLogOfHeapRegionGrainBytesSymbolName();
break;
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
vmSymbolName = binaryContainer.getInlineContiguousAllocationSupportedSymbolName();
vmSymbolName = BinaryContainer.getInlineContiguousAllocationSupportedSymbolName();
break;
default:
throw new InternalError("Unhandled mark: " + mark);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,10 +28,7 @@ import java.util.List;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.GotSymbol;
import jdk.tools.jaotc.AOTCompiledClass.AOTKlassData;
import jdk.tools.jaotc.utils.NativeOrderOutputStream;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@ -43,7 +40,7 @@ import jdk.vm.ci.code.site.Mark;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.hotspot.HotSpotMetaData;
class MetadataBuilder {
final class MetadataBuilder {
private final DataBuilder dataBuilder;
@ -58,8 +55,6 @@ class MetadataBuilder {
* Process compiled methods and create method metadata.
*/
void processMetadata(List<AOTCompiledClass> classes, AOTCompiledClass stubCompiledCode) {
binaryContainer.getMethodMetadataContainer().createSymbol(0, Kind.OBJECT, Binding.LOCAL, 0, "metaStart");
for (AOTCompiledClass c : classes) {
processMetadataClass(c);
}

View File

@ -0,0 +1,297 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import jdk.tools.jaotc.collect.ClassSearch;
import jdk.tools.jaotc.collect.ClassSource;
import jdk.tools.jaotc.collect.SearchFor;
import jdk.tools.jaotc.collect.SearchPath;
import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
import jdk.tools.jaotc.collect.jar.JarSourceProvider;
import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
final class Options {
List<SearchFor> files = new LinkedList<>();
String osName;
String outputName = defaultOutputName();
String methodList;
List<ClassSource> sources = new ArrayList<>();
String linkerpath = null;
SearchPath searchPath = new SearchPath();
/**
* We don't see scaling beyond 16 threads.
*/
private static final int COMPILER_THREADS = 16;
int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
boolean ignoreClassLoadingErrors;
boolean exitOnError;
boolean info;
boolean verbose;
boolean debug;
boolean help;
boolean version;
boolean compileWithAssertions;
boolean tiered;
private String defaultOutputName() {
osName = System.getProperty("os.name");
String name = "unnamed.";
String ext;
switch (osName) {
case "Linux":
case "SunOS":
ext = "so";
break;
case "Mac OS X":
ext = "dylib";
break;
default:
if (osName.startsWith("Windows")) {
ext = "dll";
} else {
ext = "so";
}
}
return name + ext;
}
static class BadArgs extends Exception {
private static final long serialVersionUID = 1L;
final String key;
final Object[] args;
boolean showUsage;
BadArgs(String key, Object... args) {
super(MessageFormat.format(key, args));
this.key = key;
this.args = args;
}
BadArgs showUsage(boolean b) {
showUsage = b;
return this;
}
}
abstract static class Option {
final String help;
final boolean hasArg;
final String[] aliases;
Option(String help, boolean hasArg, String... aliases) {
this.help = help;
this.hasArg = hasArg;
this.aliases = aliases;
}
boolean isHidden() {
return false;
}
boolean matches(String opt) {
for (String a : aliases) {
if (a.equals(opt)) {
return true;
} else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
return true;
}
}
return false;
}
boolean ignoreRest() {
return false;
}
abstract void process(Main task, String opt, String arg) throws BadArgs;
}
static Option[] recognizedOptions = {new Option(" --output <file> Output file name", true, "--output") {
@Override
void process(Main task, String opt, String arg) {
String name = arg;
task.options.outputName = name;
}
}, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
}
}, new Option(" --jar <jarfiles> List of jar files to compile", true, "--jar") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
}
}, new Option(" --module <modules> List of modules to compile", true, "--module") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
}
}, new Option(" --directory <dirs> List of directories where to search for files to compile", true, "--directory") {
@Override
void process(Main task, String opt, String arg) {
task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
}
}, new Option(" --search-path <dirs> List of directories where to search for specified files", true, "--search-path") {
@Override
void process(Main task, String opt, String arg) {
String[] elements = arg.split(":");
task.options.searchPath.add(elements);
}
}, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") {
@Override
void process(Main task, String opt, String arg) {
task.options.methodList = arg;
}
}, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
@Override
void process(Main task, String opt, String arg) {
task.options.tiered = true;
}
}, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") {
@Override
void process(Main task, String opt, String arg) {
task.options.compileWithAssertions = true;
}
}, new Option(" --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") {
@Override
void process(Main task, String opt, String arg) {
int threads = Integer.parseInt(arg);
final int available = Runtime.getRuntime().availableProcessors();
if (threads <= 0) {
task.warning("invalid number of threads specified: {0}, using: {1}", threads, available);
threads = available;
}
if (threads > available) {
task.warning("too many threads specified: {0}, limiting to: {1}", threads, available);
}
task.options.threads = Integer.min(threads, available);
}
}, new Option(" --ignore-errors Ignores all exceptions thrown during class loading", false, "--ignore-errors") {
@Override
void process(Main task, String opt, String arg) {
task.options.ignoreClassLoadingErrors = true;
}
}, new Option(" --exit-on-error Exit on compilation errors", false, "--exit-on-error") {
@Override
void process(Main task, String opt, String arg) {
task.options.exitOnError = true;
}
}, new Option(" --info Print information during compilation", false, "--info") {
@Override
void process(Main task, String opt, String arg) throws BadArgs {
task.options.info = true;
}
}, new Option(" --verbose Print verbose information", false, "--verbose") {
@Override
void process(Main task, String opt, String arg) throws BadArgs {
task.options.info = true;
task.options.verbose = true;
}
}, new Option(" --debug Print debug information", false, "--debug") {
@Override
void process(Main task, String opt, String arg) throws BadArgs {
task.options.info = true;
task.options.verbose = true;
task.options.debug = true;
}
}, new Option(" --help Print this usage message", false, "--help") {
@Override
void process(Main task, String opt, String arg) {
task.options.help = true;
}
}, new Option(" --version Version information", false, "--version") {
@Override
void process(Main task, String opt, String arg) {
task.options.version = true;
}
}, new Option(" --linker-path Full path to linker executable", true, "--linker-path") {
@Override
void process(Main task, String opt, String arg) {
task.options.linkerpath = arg;
}
}, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") {
@Override
void process(Main task, String opt, String arg) {
}
}};
static void handleOptions(Main task, String[] args) throws BadArgs {
if (args.length == 0) {
task.options.help = true;
return;
}
// Make checkstyle happy.
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.charAt(0) == '-') {
Option option = getOption(arg);
String param = null;
if (option.hasArg) {
if (arg.startsWith("--") && arg.indexOf('=') > 0) {
param = arg.substring(arg.indexOf('=') + 1, arg.length());
} else if (i + 1 < args.length) {
param = args[++i];
}
if (param == null || param.isEmpty() || param.charAt(0) == '-') {
throw new BadArgs("missing argument for option: {0}", arg).showUsage(true);
}
}
option.process(task, arg, param);
if (option.ignoreRest()) {
break;
}
} else {
task.options.files.add(new SearchFor(arg));
}
}
}
static Option getOption(String name) throws BadArgs {
for (Option o : recognizedOptions) {
if (o.matches(name)) {
return o;
}
}
throw new BadArgs("unknown option: {0}", name).showUsage(true);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,7 +31,7 @@ import jdk.tools.jaotc.binformat.Symbol.Binding;
*/
final class StubDirectCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
public StubDirectCallSiteRelocationSymbol(CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
StubDirectCallSiteRelocationSymbol(CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
super(binaryContainer.getSymbol(callSiteRelocation.targetSymbol));
assert symbol != null && symbol.getBinding() == Binding.LOCAL : "Stub symbol must exist and must be LOCAL";
}

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc;
public final class StubInformation {
private int stubOffset; // the offset inside the code (text + stubOffset)
private int stubSize; // the stub size
private int dispatchJumpOffset; // offset after main dispatch jump instruction
private int resolveJumpOffset; // offset after jump instruction to runtime call resolution function.
private int resolveJumpStart; // offset of jump instruction to VM runtime call resolution function.
private int c2iJumpOffset; // offset after jump instruction to c2i adapter for static calls.
private int movOffset; // offset after move instruction which loads from got cell:
// - Method* for static call
// - Klass* for virtual call
private boolean isVirtual; // virtual call stub
// maybe add type of stub as well, right now we only have static stubs
StubInformation(int stubOffset, boolean isVirtual) {
this.stubOffset = stubOffset;
this.isVirtual = isVirtual;
this.stubSize = -1;
this.movOffset = -1;
this.c2iJumpOffset = -1;
this.resolveJumpOffset = -1;
this.resolveJumpStart = -1;
this.dispatchJumpOffset = -1;
}
int getOffset() {
return stubOffset;
}
boolean isVirtual() {
return isVirtual;
}
public void setSize(int stubSize) {
this.stubSize = stubSize;
}
int getSize() {
return stubSize;
}
public void setMovOffset(int movOffset) {
this.movOffset = movOffset + stubOffset;
}
int getMovOffset() {
return movOffset;
}
public void setC2IJumpOffset(int c2iJumpOffset) {
this.c2iJumpOffset = c2iJumpOffset + stubOffset;
}
int getC2IJumpOffset() {
return c2iJumpOffset;
}
public void setResolveJumpOffset(int resolveJumpOffset) {
this.resolveJumpOffset = resolveJumpOffset + stubOffset;
}
int getResolveJumpOffset() {
return resolveJumpOffset;
}
public void setResolveJumpStart(int resolveJumpStart) {
this.resolveJumpStart = resolveJumpStart + stubOffset;
}
int getResolveJumpStart() {
return resolveJumpStart;
}
public void setDispatchJumpOffset(int dispatchJumpOffset) {
this.dispatchJumpOffset = dispatchJumpOffset + stubOffset;
}
int getDispatchJumpOffset() {
return dispatchJumpOffset;
}
void verify() {
assert stubOffset > 0 : "incorrect stubOffset: " + stubOffset;
assert stubSize > 0 : "incorrect stubSize: " + stubSize;
assert movOffset > 0 : "incorrect movOffset: " + movOffset;
assert dispatchJumpOffset > 0 : "incorrect dispatchJumpOffset: " + dispatchJumpOffset;
assert resolveJumpStart > 0 : "incorrect resolveJumpStart: " + resolveJumpStart;
assert resolveJumpOffset > 0 : "incorrect resolveJumpOffset: " + resolveJumpOffset;
if (!isVirtual) {
assert c2iJumpOffset > 0 : "incorrect c2iJumpOffset: " + c2iJumpOffset;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -21,24 +21,22 @@
* questions.
*/
package jdk.tools.jaotc.utils;
package jdk.tools.jaotc;
import jdk.tools.jaotc.Main;
public class Timer implements AutoCloseable {
final class Timer implements AutoCloseable {
private final Main main;
private final long start;
public Timer(Main main, String message) {
Timer(Main main, String message) {
this.main = main;
start = System.currentTimeMillis();
main.printInfo(message);
main.printer.printInfo(message);
}
public void close() {
final long end = System.currentTimeMillis();
main.printlnInfo(" (" + (end - start) + " ms)");
main.printer.printlnInfo(" (" + (end - start) + " ms)");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@ import static jdk.vm.ci.amd64.AMD64.rax;
import static jdk.vm.ci.amd64.AMD64.rbx;
import static jdk.vm.ci.amd64.AMD64.rip;
import jdk.tools.jaotc.CompiledMethodInfo.StubInformation;
import jdk.tools.jaotc.StubInformation;
import jdk.tools.jaotc.ELFMacroAssembler;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,43 +35,43 @@ public final class AMD64InstructionDecoder extends InstructionDecoder {
private static class Prefix {
// segment overrides
public static final int CSSegment = 0x2e;
public static final int SSSegment = 0x36;
public static final int DSSegment = 0x3e;
public static final int ESSegment = 0x26;
public static final int FSSegment = 0x64;
public static final int GSSegment = 0x65;
public static final int REX = 0x40;
public static final int REXB = 0x41;
public static final int REXX = 0x42;
public static final int REXXB = 0x43;
public static final int REXR = 0x44;
public static final int REXRB = 0x45;
public static final int REXRX = 0x46;
public static final int REXRXB = 0x47;
public static final int REXW = 0x48;
public static final int REXWB = 0x49;
public static final int REXWX = 0x4A;
public static final int REXWXB = 0x4B;
public static final int REXWR = 0x4C;
public static final int REXWRB = 0x4D;
public static final int REXWRX = 0x4E;
public static final int REXWRXB = 0x4F;
public static final int VEX_3BYTES = 0xC4;
public static final int VEX_2BYTES = 0xC5;
static final int CSSegment = 0x2e;
static final int SSSegment = 0x36;
static final int DSSegment = 0x3e;
static final int ESSegment = 0x26;
static final int FSSegment = 0x64;
static final int GSSegment = 0x65;
static final int REX = 0x40;
static final int REXB = 0x41;
static final int REXX = 0x42;
static final int REXXB = 0x43;
static final int REXR = 0x44;
static final int REXRB = 0x45;
static final int REXRX = 0x46;
static final int REXRXB = 0x47;
static final int REXW = 0x48;
static final int REXWB = 0x49;
static final int REXWX = 0x4A;
static final int REXWXB = 0x4B;
static final int REXWR = 0x4C;
static final int REXWRB = 0x4D;
static final int REXWRX = 0x4E;
static final int REXWRXB = 0x4F;
static final int VEX_3BYTES = 0xC4;
static final int VEX_2BYTES = 0xC5;
}
public static class VexPrefix {
public static final int VEX_R = 0x80;
public static final int VEX_W = 0x80;
private static class VexPrefix {
static final int VEX_R = 0x80;
static final int VEX_W = 0x80;
}
public static class VexOpcode {
public static final int VEX_OPCODE_NONE = 0x0;
public static final int VEX_OPCODE_0F = 0x1;
public static final int VEX_OPCODE_0F_38 = 0x2;
public static final int VEX_OPCODE_0F_3A = 0x3;
public static final int VEX_OPCODE_MASK = 0x1F;
private static class VexOpcode {
static final int VEX_OPCODE_NONE = 0x0;
static final int VEX_OPCODE_0F = 0x1;
static final int VEX_OPCODE_0F_38 = 0x2;
static final int VEX_OPCODE_0F_3A = 0x3;
static final int VEX_OPCODE_MASK = 0x1F;
}
public AMD64InstructionDecoder(TargetDescription target) {
@ -112,7 +112,7 @@ public final class AMD64InstructionDecoder extends InstructionDecoder {
againAfterPrefix = false;
switch (0xFF & code[ip++]) {
// These convenience macros generate groups of "case" labels for the switch.
// These convenience macros generate groups of "case" labels for the switch.
case Prefix.CSSegment:
case Prefix.SSSegment:
@ -446,7 +446,7 @@ public final class AMD64InstructionDecoder extends InstructionDecoder {
tailSize = 1; // the imm8
break;
default:
; // no imm8
break; // no imm8
}
break;
case VexOpcode.VEX_OPCODE_0F_3A:

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect;
import jdk.tools.jaotc.LoadedClass;
@ -27,8 +28,8 @@ import jdk.tools.jaotc.LoadedClass;
import java.util.ArrayList;
import java.util.List;
public class ClassSearch {
private List<SourceProvider> providers = new ArrayList<>();
public final class ClassSearch {
private final List<SourceProvider> providers = new ArrayList<>();
public void addProvider(SourceProvider provider) {
providers.add(provider);
@ -50,7 +51,7 @@ public class ClassSearch {
return loaded;
}
private LoadedClass loadClass(String name, ClassLoader loader) {
private static LoadedClass loadClass(String name, ClassLoader loader) {
try {
Class<?> clzz = loader.loadClass(name);
return new LoadedClass(name, clzz);

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect;
import java.nio.file.Path;
@ -32,17 +33,17 @@ public interface ClassSource {
}
static String stripRoot(Path path) {
if (path.getRoot() != null) {
String root = path.getRoot().toString();
String filename = path.toString().substring(root.length());
String separator = path.getFileSystem().getSeparator();
while (filename.startsWith(separator)) {
filename = filename.substring(separator.length());
if (path.getRoot() != null) {
String root = path.getRoot().toString();
String filename = path.toString().substring(root.length());
String separator = path.getFileSystem().getSeparator();
while (filename.startsWith(separator)) {
filename = filename.substring(separator.length());
}
return filename;
}
return filename;
}
return path.toString();
return path.toString();
}
static String makeClassName(Path path) {

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect;
import java.io.IOException;
@ -28,7 +29,7 @@ import java.nio.file.*;
import java.util.HashMap;
public class FileSupport {
public boolean exists(Path path) {
public boolean exists(Path path) {
return Files.exists(path);
}
@ -36,7 +37,7 @@ public class FileSupport {
return Files.isDirectory(path);
}
private FileSystem makeJarFileSystem(Path path) {
private static FileSystem makeJarFileSystem(Path path) {
try {
return FileSystems.newFileSystem(makeJarFileURI(path), new HashMap<>());
} catch (IOException e) {
@ -44,10 +45,10 @@ public class FileSupport {
}
}
private URI makeJarFileURI(Path path) {
private static URI makeJarFileURI(Path path) {
try {
String name = path.toAbsolutePath().toString();
name = name.replace('\\','/');
name = name.replace('\\', '/');
return new URI("jar:file:///" + name + "!/");
} catch (URISyntaxException e) {
throw new InternalError(e);
@ -66,8 +67,8 @@ public class FileSupport {
return URLClassLoader.newInstance(buildUrls(path));
}
private URL[] buildUrls(Path path) throws MalformedURLException {
return new URL[] { path.toUri().toURL() };
private static URL[] buildUrls(Path path) throws MalformedURLException {
return new URL[]{path.toUri().toURL()};
}
public Path getJarFileSystemRoot(Path jarFile) {
@ -80,7 +81,7 @@ public class FileSupport {
}
public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
DirectoryStream<Path> paths = fileSystem.provider().newDirectoryStream(root,null);
DirectoryStream<Path> paths = fileSystem.provider().newDirectoryStream(root, null);
for (Path entry : paths) {
Path relative = root.relativize(entry);
if (relative.equals(path)) {

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect;
import java.io.IOException;
@ -33,7 +34,7 @@ import static java.nio.file.FileVisitResult.CONTINUE;
/**
* {@link FileVisitor} implementation to find class files recursively.
*/
public class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterable<Path> {
public final class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterable<Path> {
private final ArrayList<Path> fileNames = new ArrayList<>();
private final PathMatcher filter;
@ -68,7 +69,6 @@ public class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterabl
return CONTINUE;
}
@Override
public Iterator<Path> iterator() {
return fileNames.iterator();

View File

@ -20,9 +20,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect;
public class SearchFor {
public final class SearchFor {
private final String name;
private final String type;
@ -35,15 +36,15 @@ public class SearchFor {
this.type = type;
}
public boolean isUnknown() {
boolean isUnknown() {
return "".equals(type);
}
public String getType() {
String getType() {
return this.type;
}
public String getName() {
String getName() {
return this.name;
}

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect;
import java.nio.file.FileSystem;
@ -84,4 +85,3 @@ public class SearchPath {
}
}
}

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect;
public interface SourceProvider {

View File

@ -20,17 +20,18 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.classname;
import jdk.tools.jaotc.collect.ClassSource;
import java.util.function.BiConsumer;
public class ClassNameSource implements ClassSource {
public final class ClassNameSource implements ClassSource {
private final String name;
private final ClassLoader classLoader;
public ClassNameSource(String name, ClassLoader classLoader) {
ClassNameSource(String name, ClassLoader classLoader) {
this.name = name;
this.classLoader = classLoader;
}

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.classname;
import jdk.tools.jaotc.collect.ClassSource;
@ -30,7 +31,7 @@ import jdk.tools.jaotc.collect.SourceProvider;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ClassNameSourceProvider implements SourceProvider {
public final class ClassNameSourceProvider implements SourceProvider {
public final static String TYPE = "class";
private final ClassLoader classLoader;
@ -46,7 +47,8 @@ public class ClassNameSourceProvider implements SourceProvider {
}
@Override
public ClassSource findSource(String name, SearchPath searchPath) {
public ClassSource findSource(String name0, SearchPath searchPath) {
String name = name0;
Path path = Paths.get(name);
if (ClassSource.pathIsClassFile(path)) {
name = ClassSource.makeClassName(path);

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.directory;
import jdk.tools.jaotc.collect.ClassSource;
@ -28,11 +29,11 @@ import jdk.tools.jaotc.collect.FileSystemFinder;
import java.nio.file.Path;
import java.util.function.BiConsumer;
public class DirectorySource implements ClassSource {
public final class DirectorySource implements ClassSource {
private final Path directoryPath;
private final ClassLoader classLoader;
public DirectorySource(Path directoryPath, ClassLoader classLoader) {
DirectorySource(Path directoryPath, ClassLoader classLoader) {
this.directoryPath = directoryPath;
this.classLoader = classLoader;
}

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.directory;
import jdk.tools.jaotc.collect.ClassSource;
@ -32,7 +33,7 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
public class DirectorySourceProvider implements SourceProvider {
public final class DirectorySourceProvider implements SourceProvider {
private final FileSupport fileSupport;
private final FileSystem fileSystem;
public final static String TYPE = "directory";

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.jar;
import jdk.tools.jaotc.collect.ClassSource;
@ -28,18 +29,18 @@ import jdk.tools.jaotc.collect.FileSystemFinder;
import java.nio.file.Path;
import java.util.function.BiConsumer;
public class JarFileSource implements ClassSource {
public final class JarFileSource implements ClassSource {
private final Path jarFile;
private final Path jarRootPath;
private final ClassLoader classLoader;
public JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
this.jarFile = jarFile;
this.jarRootPath = jarRootPath;
this.classLoader = classLoader;
}
@Override
public void eachClass(BiConsumer<String, ClassLoader> consumer) {
FileSystemFinder finder = new FileSystemFinder(jarRootPath, ClassSource::pathIsClassFile);

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.jar;
import jdk.tools.jaotc.collect.ClassSource;
@ -33,7 +34,7 @@ import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.ProviderNotFoundException;
public class JarSourceProvider implements SourceProvider {
public final class JarSourceProvider implements SourceProvider {
private final FileSystem fileSystem;
private final FileSupport fileSupport;
public final static String TYPE = "jar";

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.module;
import jdk.tools.jaotc.collect.ClassSource;
@ -28,15 +29,19 @@ import jdk.tools.jaotc.collect.FileSystemFinder;
import java.nio.file.Path;
import java.util.function.BiConsumer;
public class ModuleSource implements ClassSource {
public final class ModuleSource implements ClassSource {
private final Path modulePath;
private final ClassLoader classLoader;
public ModuleSource(Path modulePath, ClassLoader classLoader) {
ModuleSource(Path modulePath, ClassLoader classLoader) {
this.modulePath = modulePath;
this.classLoader = classLoader;
}
public Path getModulePath() {
return modulePath;
}
@Override
public void eachClass(BiConsumer<String, ClassLoader> consumer) {
FileSystemFinder finder = new FileSystemFinder(modulePath, ClassSource::pathIsClassFile);
@ -46,10 +51,6 @@ public class ModuleSource implements ClassSource {
}
}
public Path getModulePath() {
return modulePath;
}
@Override
public String toString() {
return "module:" + modulePath.toString();

View File

@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.tools.jaotc.collect.module;
import jdk.tools.jaotc.collect.ClassSource;
@ -33,7 +34,7 @@ import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
public class ModuleSourceProvider implements SourceProvider {
public final class ModuleSourceProvider implements SourceProvider {
private final FileSystem fileSystem;
private final ClassLoader classLoader;
private final FileSupport fileSupport;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,7 +29,7 @@ import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
public class NativeOrderOutputStream {
public final class NativeOrderOutputStream {
private final PatchableByteOutputStream os = new PatchableByteOutputStream();
private final byte[] backingArray = new byte[8];
private final ByteBuffer buffer;
@ -181,7 +181,7 @@ public class NativeOrderOutputStream {
private static class PatchableByteOutputStream extends ByteArrayOutputStream {
public void writeAt(byte[] data, int length, int position) {
long end = (long)position + (long)length;
long end = (long) position + (long) length;
if (buf.length < end) {
throw new IllegalArgumentException("Array not properly sized");
}

View File

@ -51,7 +51,7 @@ address AOTLib::load_symbol(const char *name) {
Klass* AOTCodeHeap::get_klass_from_got(const char* klass_name, int klass_len, const Method* method) {
AOTKlassData* klass_data = (AOTKlassData*)_lib->load_symbol(klass_name);
Klass* k = (Klass*)_metaspace_got[klass_data->_got_index];
Klass* k = (Klass*)_klasses_got[klass_data->_got_index];
if (k == NULL) {
Thread* thread = Thread::current();
k = lookup_klass(klass_name, klass_len, method, thread);
@ -60,7 +60,7 @@ Klass* AOTCodeHeap::get_klass_from_got(const char* klass_name, int klass_len, co
fatal("Shared file %s error: klass %s should be resolved already", _lib->name(), klass_name);
vm_exit(1);
}
_metaspace_got[klass_data->_got_index] = k;
_klasses_got[klass_data->_got_index] = k;
}
return k;
}
@ -202,8 +202,8 @@ AOTLib::AOTLib(void* handle, const char* name, int dso_id) : _valid(true), _dl_h
_name = (const char*) strdup(name);
// Verify that VM runs with the same parameters as AOT tool.
_config = (AOTConfiguration*) load_symbol("JVM.config");
_header = (AOTHeader*) load_symbol("JVM.header");
_config = (AOTConfiguration*) load_symbol("A.config");
_header = (AOTHeader*) load_symbol("A.header");
verify_config();
@ -224,31 +224,31 @@ AOTCodeHeap::AOTCodeHeap(AOTLib* lib) :
_method_count = _lib->header()->_method_count;
// Collect metaspace info: names -> address in .got section
_metaspace_names = (const char*) _lib->load_symbol("JVM.meta.names");
_method_metadata = (address) _lib->load_symbol("JVM.meth.metadata");
_methods_offsets = (address) _lib->load_symbol("JVM.methods.offsets");
_klasses_offsets = (address) _lib->load_symbol("JVM.kls.offsets");
_dependencies = (address) _lib->load_symbol("JVM.kls.dependencies");
_code_space = (address) _lib->load_symbol("JVM.text");
_metaspace_names = (const char*) _lib->load_symbol("A.meta.names");
_method_metadata = (address) _lib->load_symbol("A.meth.metadata");
_methods_offsets = (address) _lib->load_symbol("A.meth.offsets");
_klasses_offsets = (address) _lib->load_symbol("A.kls.offsets");
_dependencies = (address) _lib->load_symbol("A.kls.dependencies");
_code_space = (address) _lib->load_symbol("A.text");
// First cell is number of elements.
_metaspace_got = (Metadata**) _lib->load_symbol("JVM.meta.got");
_metaspace_got_size = _lib->header()->_metaspace_got_size;
_klasses_got = (Metadata**) _lib->load_symbol("A.kls.got");
_klasses_got_size = _lib->header()->_klasses_got_size;
_metadata_got = (Metadata**) _lib->load_symbol("JVM.metadata.got");
_metadata_got = (Metadata**) _lib->load_symbol("A.meta.got");
_metadata_got_size = _lib->header()->_metadata_got_size;
_oop_got = (oop*) _lib->load_symbol("JVM.oop.got");
_oop_got = (oop*) _lib->load_symbol("A.oop.got");
_oop_got_size = _lib->header()->_oop_got_size;
// Collect stubs info
_stubs_offsets = (int*) _lib->load_symbol("JVM.stubs.offsets");
_stubs_offsets = (int*) _lib->load_symbol("A.stubs.offsets");
// code segments table
_code_segments = (address) _lib->load_symbol("JVM.code.segments");
_code_segments = (address) _lib->load_symbol("A.code.segments");
// method state
_method_state = (jlong*) _lib->load_symbol("JVM.meth.state");
_method_state = (jlong*) _lib->load_symbol("A.meth.state");
// Create a table for mapping classes
_classes = NEW_C_HEAP_ARRAY(AOTClass, _class_count, mtCode);
@ -342,8 +342,8 @@ void AOTCodeHeap::link_primitive_array_klasses() {
if (klass_data != NULL) {
// Set both GOT cells, resolved and initialized klass pointers.
// _got_index points to second cell - resolved klass pointer.
_metaspace_got[klass_data->_got_index-1] = (Metadata*)arr_klass; // Initialized
_metaspace_got[klass_data->_got_index ] = (Metadata*)arr_klass; // Resolved
_klasses_got[klass_data->_got_index-1] = (Metadata*)arr_klass; // Initialized
_klasses_got[klass_data->_got_index ] = (Metadata*)arr_klass; // Resolved
if (PrintAOT) {
tty->print_cr("[Found %s in %s]", arr_klass->internal_name(), _lib->name());
}
@ -680,16 +680,16 @@ bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* thread) {
if (!ik->has_passed_fingerprint_check()) {
NOT_PRODUCT( aot_klasses_fp_miss++; )
log_trace(aot, class, fingerprint)("class %s%s has bad fingerprint in %s tid=" INTPTR_FORMAT,
ik->internal_name(), ik->is_shared() ? " (shared)" : "",
_lib->name(), p2i(thread));
ik->internal_name(), ik->is_shared() ? " (shared)" : "",
_lib->name(), p2i(thread));
sweep_dependent_methods(klass_data);
return false;
}
if (ik->has_been_redefined()) {
log_trace(aot, class, load)("class %s%s in %s has been redefined tid=" INTPTR_FORMAT,
ik->internal_name(), ik->is_shared() ? " (shared)" : "",
_lib->name(), p2i(thread));
ik->internal_name(), ik->is_shared() ? " (shared)" : "",
_lib->name(), p2i(thread));
sweep_dependent_methods(klass_data);
return false;
}
@ -698,7 +698,7 @@ bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* thread) {
AOTClass* aot_class = &_classes[klass_data->_class_id];
if (aot_class->_classloader != NULL && aot_class->_classloader != ik->class_loader_data()) {
log_trace(aot, class, load)("class %s in %s already loaded for classloader %p vs %p tid=" INTPTR_FORMAT,
ik->internal_name(), _lib->name(), aot_class->_classloader, ik->class_loader_data(), p2i(thread));
ik->internal_name(), _lib->name(), aot_class->_classloader, ik->class_loader_data(), p2i(thread));
NOT_PRODUCT( aot_klasses_cl_miss++; )
return false;
}
@ -715,7 +715,7 @@ bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* thread) {
aot_class->_classloader = ik->class_loader_data();
// Set klass's Resolve (second) got cell.
_metaspace_got[klass_data->_got_index] = ik;
_klasses_got[klass_data->_got_index] = ik;
// Initialize global symbols of the DSO to the corresponding VM symbol values.
link_global_lib_symbols();
@ -823,12 +823,12 @@ void AOTCodeHeap::oops_do(OopClosure* f) {
}
}
// Scan only metaspace_got cells which should have only Klass*,
// Scan only klasses_got cells which should have only Klass*,
// metadata_got cells are scanned only for alive AOT methods
// by AOTCompiledMethod::metadata_do().
void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
for (int i = 1; i < _metaspace_got_size; i++) {
Metadata** p = &_metaspace_got[i];
for (int i = 1; i < _klasses_got_size; i++) {
Metadata** p = &_klasses_got[i];
Metadata* md = *p;
if (md == NULL) continue; // skip non-oops
if (Metaspace::contains(md)) {

View File

@ -77,7 +77,7 @@ typedef struct {
int _version;
int _class_count;
int _method_count;
int _metaspace_got_size;
int _klasses_got_size;
int _metadata_got_size;
int _oop_got_size;
int _jvm_version_offset;
@ -180,11 +180,11 @@ class AOTCodeHeap : public CodeHeap {
address _klasses_offsets;
address _dependencies;
Metadata** _metaspace_got;
Metadata** _klasses_got;
Metadata** _metadata_got;
oop* _oop_got;
int _metaspace_got_size;
int _klasses_got_size;
int _metadata_got_size;
int _oop_got_size;
@ -251,7 +251,7 @@ public:
#ifdef ASSERT
bool got_contains(Metadata **p) {
return (p >= &_metadata_got[0] && p < &_metadata_got[_metadata_got_size]) ||
(p >= &_metaspace_got[0] && p < &_metaspace_got[_metaspace_got_size]);
(p >= &_klasses_got[0] && p < &_klasses_got[_klasses_got_size]);
}
#endif