This commit is contained in:
Jesper Wilhelmsson 2017-04-06 22:58:55 +02:00
commit cc14920031
1366 changed files with 37486 additions and 30689 deletions

View File

@ -47,11 +47,9 @@ ifeq ($(INCLUDE_GRAAL), true)
$(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \ $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \
SETUP := GENERATE_OLDBYTECODE, \ SETUP := GENERATE_OLDBYTECODE, \
SRC := \ SRC := \
$(SRC_DIR)/org.graalvm.compiler.common/src \
$(SRC_DIR)/org.graalvm.compiler.core/src \ $(SRC_DIR)/org.graalvm.compiler.core/src \
$(SRC_DIR)/org.graalvm.compiler.core.common/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \
$(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \ $(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \
$(SRC_DIR)/org.graalvm.compiler.api.collections/src \
$(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
$(SRC_DIR)/org.graalvm.compiler.asm/src \ $(SRC_DIR)/org.graalvm.compiler.asm/src \
$(SRC_DIR)/org.graalvm.compiler.bytecode/src \ $(SRC_DIR)/org.graalvm.compiler.bytecode/src \
@ -68,6 +66,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.phases.common/src \ $(SRC_DIR)/org.graalvm.compiler.phases.common/src \
$(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
$(SRC_DIR)/org.graalvm.compiler.virtual/src \ $(SRC_DIR)/org.graalvm.compiler.virtual/src \
$(SRC_DIR)/org.graalvm.util/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \
@ -102,6 +101,7 @@ ifeq ($(INCLUDE_GRAAL), true)
SRC := \ SRC := \
$(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.options/src \
$(SRC_DIR)/org.graalvm.compiler.options.processor/src \ $(SRC_DIR)/org.graalvm.compiler.options.processor/src \
$(SRC_DIR)/org.graalvm.util/src \
, \ , \
BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor, \
JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor.jar, \ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor.jar, \
@ -114,9 +114,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \ $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \
SETUP := GENERATE_OLDBYTECODE, \ SETUP := GENERATE_OLDBYTECODE, \
SRC := \ SRC := \
$(SRC_DIR)/org.graalvm.compiler.common/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \
$(SRC_DIR)/org.graalvm.compiler.api.collections/src \
$(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
$(SRC_DIR)/org.graalvm.compiler.code/src \ $(SRC_DIR)/org.graalvm.compiler.code/src \
$(SRC_DIR)/org.graalvm.compiler.core.common/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \
@ -125,6 +123,7 @@ ifeq ($(INCLUDE_GRAAL), true)
$(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \
$(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.options/src \
$(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
$(SRC_DIR)/org.graalvm.util/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \

View File

@ -37,7 +37,6 @@ SRC_DIR := $(HOTSPOT_TOPDIR)/src/$(MODULE)/share/classes
PROC_SRC_SUBDIRS := \ PROC_SRC_SUBDIRS := \
org.graalvm.compiler.code \ org.graalvm.compiler.code \
org.graalvm.compiler.common \
org.graalvm.compiler.core \ org.graalvm.compiler.core \
org.graalvm.compiler.core.aarch64 \ org.graalvm.compiler.core.aarch64 \
org.graalvm.compiler.core.amd64 \ org.graalvm.compiler.core.amd64 \

View File

@ -1,53 +0,0 @@
#
# Copyright (c) 2016, 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. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# 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.
#
include $(SPEC)
include NativeCompilation.gmk
$(eval $(call IncludeCustomExtension, hotspot, lib/Lib-jdk.aot.gmk))
##############################################################################
# Build libjelfshim only when AOT is enabled.
ifeq ($(ENABLE_AOT), true)
JELFSHIM_NAME := jelfshim
$(eval $(call SetupNativeCompilation, BUILD_LIBJELFSHIM, \
TOOLCHAIN := TOOLCHAIN_DEFAULT, \
OPTIMIZATION := LOW, \
LIBRARY := $(JELFSHIM_NAME), \
OUTPUT_DIR := $(call FindLibDirForModule, $(MODULE)), \
SRC := $(HOTSPOT_TOPDIR)/src/jdk.aot/unix/native/libjelfshim, \
CFLAGS := $(CFLAGS_JDKLIB) $(ELF_CFLAGS) \
-DAOT_VERSION_STRING='"$(VERSION_STRING)"' \
-I$(SUPPORT_OUTPUTDIR)/headers/$(MODULE), \
LDFLAGS := $(LDFLAGS_JDKLIB), \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lib$(JELFSHIM_NAME), \
LIBS := $(ELF_LIBS) $(LIBS_JDKLIB), \
))
TARGETS += $(BUILD_LIBJELFSHIM)
endif
##############################################################################

View File

@ -35,12 +35,14 @@ include $(SPEC)
include MakeBase.gmk include MakeBase.gmk
include TestFilesCompilation.gmk include TestFilesCompilation.gmk
$(eval $(call IncludeCustomExtension, hotspot, test/JtregNative.gmk))
################################################################################ ################################################################################
# Targets for building the native tests themselves. # Targets for building the native tests themselves.
################################################################################ ################################################################################
# Add more directories here when needed. # Add more directories here when needed.
BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ BUILD_HOTSPOT_JTREG_NATIVE_SRC += \
$(HOTSPOT_TOPDIR)/test/native_sanity \ $(HOTSPOT_TOPDIR)/test/native_sanity \
$(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -54,9 +54,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
int number_of_arguments, int number_of_arguments,
bool check_exceptions); bool check_exceptions);
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
// base routine for all dispatches // base routine for all dispatches
void dispatch_base(TosState state, address* table, bool verifyoop = true); void dispatch_base(TosState state, address* table, bool verifyoop = true);
@ -67,6 +64,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
void jump_to_entry(address entry); void jump_to_entry(address entry);
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
// Interpreter-specific registers // Interpreter-specific registers
void save_bcp() { void save_bcp() {
str(rbcp, Address(rfp, frame::interpreter_frame_bcp_offset * wordSize)); str(rbcp, Address(rfp, frame::interpreter_frame_bcp_offset * wordSize));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -55,7 +55,7 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS)
} }
} }
#endif // ASSERT #endif // ASSERT
Handle obj = HotSpotObjectConstantImpl::object(constant); Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
jobject value = JNIHandles::make_local(obj()); jobject value = JNIHandles::make_local(obj());
MacroAssembler::patch_oop(pc, (address)obj()); MacroAssembler::patch_oop(pc, (address)obj());
int oop_index = _oop_recorder->find_index(value); int oop_index = _oop_recorder->find_index(value);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -77,12 +77,6 @@ class MacroAssembler: public Assembler {
bool check_exceptions // whether to check for pending exceptions after return bool check_exceptions // whether to check for pending exceptions after return
); );
// These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
// The implementation is only non-empty for the InterpreterMacroAssembler,
// as only the interpreter handles PopFrame and ForceEarlyReturn requests.
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true);
// Maximum size of class area in Metaspace when compressed // Maximum size of class area in Metaspace when compressed
@ -97,6 +91,12 @@ class MacroAssembler: public Assembler {
> (1u << log2_intptr(CompressedClassSpaceSize)))); > (1u << log2_intptr(CompressedClassSpaceSize))));
} }
// These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
// The implementation is only non-empty for the InterpreterMacroAssembler,
// as only the interpreter handles PopFrame and ForceEarlyReturn requests.
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
// Biased locking support // Biased locking support
// lock_reg and obj_reg must be loaded up with the appropriate values. // lock_reg and obj_reg must be loaded up with the appropriate values.
// swap_reg is killed. // swap_reg is killed.

View File

@ -1,126 +0,0 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. 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.
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "memory/metaspaceShared.hpp"
// Generate the self-patching vtable method:
//
// This method will be called (as any other Klass virtual method) with
// the Klass itself as the first argument. Example:
//
// oop obj;
// int size = obj->klass()->oop_size(this);
//
// for which the virtual method call is Klass::oop_size();
//
// The dummy method is called with the Klass object as the first
// operand, and an object as the second argument.
//
//=====================================================================
// All of the dummy methods in the vtable are essentially identical,
// differing only by an ordinal constant, and they bear no relationship
// to the original method which the caller intended. Also, there needs
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#define __ masm->
extern "C" {
void aarch64_prolog(void);
}
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
#ifdef BUILTIN_SIM
// Write a dummy word to the writable shared metaspace.
// MetaspaceShared::initialize_shared_spaces will fill it with the
// address of aarch64_prolog().
address *prolog_ptr = (address*)*md_top;
*(intptr_t *)(*md_top) = (intptr_t)0;
(*md_top) += sizeof(intptr_t);
#endif
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
// Get ready to generate dummy methods.
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
Label common_code;
for (int i = 0; i < vtbl_list_size; ++i) {
for (int j = 0; j < num_virtuals; ++j) {
dummy_vtable[num_virtuals * i + j] = (void*)masm->pc();
// We're called directly from C code.
#ifdef BUILTIN_SIM
__ c_stub_prolog(8, 0, MacroAssembler::ret_type_integral, prolog_ptr);
#endif
// Load rscratch1 with a value indicating vtable/offset pair.
// -- bits[ 7..0] (8 bits) which virtual method in table?
// -- bits[12..8] (5 bits) which virtual method table?
__ mov(rscratch1, (i << 8) + j);
__ b(common_code);
}
}
__ bind(common_code);
Register tmp0 = r10, tmp1 = r11; // AAPCS64 temporary registers
__ enter();
__ lsr(tmp0, rscratch1, 8); // isolate vtable identifier.
__ mov(tmp1, (address)vtbl_list); // address of list of vtable pointers.
__ ldr(tmp1, Address(tmp1, tmp0, Address::lsl(LogBytesPerWord))); // get correct vtable pointer.
__ str(tmp1, Address(c_rarg0)); // update vtable pointer in obj.
__ add(rscratch1, tmp1, rscratch1, ext::uxtb, LogBytesPerWord); // address of real method pointer.
__ ldr(rscratch1, Address(rscratch1)); // get real method pointer.
__ blrt(rscratch1, 8, 0, 1); // jump to the real method.
__ leave();
__ ret(lr);
*mc_top = (char*)__ pc();
}
#ifdef BUILTIN_SIM
void MetaspaceShared::relocate_vtbl_list(char **buffer) {
void **sim_entry = (void**)*buffer;
*sim_entry = (void*)aarch64_prolog;
*buffer += sizeof(intptr_t);
}
#endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -63,7 +63,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
Register obj, SystemDictionary::WKID klass_id, Register obj, SystemDictionary::WKID klass_id,
const char* error_message) { const char* error_message) {
InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Klass* klass = SystemDictionary::well_known_klass(klass_id);
Register temp = rscratch2; Register temp = rscratch2;
Register temp2 = rscratch1; // used by MacroAssembler::cmpptr Register temp2 = rscratch1; // used by MacroAssembler::cmpptr
Label L_ok, L_bad; Label L_ok, L_bad;

View File

@ -402,14 +402,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(
return entry; return entry;
} }
address TemplateInterpreterGenerator::generate_continuation_for(TosState state) {
address entry = __ pc();
// NULL last_sp until next java call
__ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ dispatch_next(state);
return entry;
}
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) {
address entry = __ pc(); address entry = __ pc();
@ -444,6 +436,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
__ notify(Assembler::method_reentry); __ notify(Assembler::method_reentry);
} }
#endif #endif
__ check_and_handle_popframe(rthread);
__ check_and_handle_earlyret(rthread);
__ get_dispatch(); __ get_dispatch();
__ dispatch_next(state, step); __ dispatch_next(state, step);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -234,8 +234,15 @@ void AbstractInterpreter::layout_activation(Method* method,
#ifdef AARCH64 #ifdef AARCH64
interpreter_frame->interpreter_frame_set_stack_top(stack_top); interpreter_frame->interpreter_frame_set_stack_top(stack_top);
// We have to add extra reserved slots to max_stack. There are 3 users of the extra slots,
// none of which are at the same time, so we just need to make sure there is enough room
// for the biggest user:
// -reserved slot for exception handler
// -reserved slots for JSR292. Method::extra_stack_entries() is the size.
// -3 reserved slots so get_method_counters() can save some registers before call_VM().
int max_stack = method->constMethod()->max_stack() + MAX2(3, Method::extra_stack_entries());
intptr_t* extended_sp = (intptr_t*) monbot - intptr_t* extended_sp = (intptr_t*) monbot -
(method->max_stack() + 1) * Interpreter::stackElementWords - // +1 is reserved slot for exception handler (max_stack * Interpreter::stackElementWords) -
popframe_extra_args; popframe_extra_args;
extended_sp = (intptr_t*)round_down((intptr_t)extended_sp, StackAlignmentInBytes); extended_sp = (intptr_t*)round_down((intptr_t)extended_sp, StackAlignmentInBytes);
interpreter_frame->interpreter_frame_set_extended_sp(extended_sp); interpreter_frame->interpreter_frame_set_extended_sp(extended_sp);

View File

@ -2016,75 +2016,42 @@ void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
void InterpreterMacroAssembler::get_method_counters(Register method, void InterpreterMacroAssembler::get_method_counters(Register method,
Register Rcounters, Register Rcounters,
Label& skip) { Label& skip,
bool saveRegs,
Register reg1,
Register reg2,
Register reg3) {
const Address method_counters(method, Method::method_counters_offset()); const Address method_counters(method, Method::method_counters_offset());
Label has_counters; Label has_counters;
ldr(Rcounters, method_counters); ldr(Rcounters, method_counters);
cbnz(Rcounters, has_counters); cbnz(Rcounters, has_counters);
if (saveRegs) {
// Save and restore in use caller-saved registers since they will be trashed by call_VM
assert(reg1 != noreg, "must specify reg1");
assert(reg2 != noreg, "must specify reg2");
#ifdef AARCH64 #ifdef AARCH64
const Register tmp = Rcounters; assert(reg3 != noreg, "must specify reg3");
const int saved_regs_size = 20*wordSize; stp(reg1, reg2, Address(Rstack_top, -2*wordSize, pre_indexed));
stp(reg3, ZR, Address(Rstack_top, -2*wordSize, pre_indexed));
// Note: call_VM will cut SP according to Rstack_top value before call, and restore SP to
// extended_sp value from frame after the call.
// So make sure there is enough stack space to save registers and adjust Rstack_top accordingly.
{
Label enough_stack_space;
check_extended_sp(tmp);
sub(Rstack_top, Rstack_top, saved_regs_size);
cmp(SP, Rstack_top);
b(enough_stack_space, ls);
align_reg(tmp, Rstack_top, StackAlignmentInBytes);
mov(SP, tmp);
str(tmp, Address(FP, frame::interpreter_frame_extended_sp_offset * wordSize));
bind(enough_stack_space);
check_stack_top();
int offset = 0;
stp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize;
stp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize;
assert (offset == saved_regs_size, "should be");
}
#else #else
push(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); assert(reg3 == noreg, "must not specify reg3");
#endif // AARCH64 push(RegisterSet(reg1) | RegisterSet(reg2));
#endif
}
mov(R1, method); mov(R1, method);
call_VM(noreg, CAST_FROM_FN_PTR(address, call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), R1);
InterpreterRuntime::build_method_counters), R1);
if (saveRegs) {
#ifdef AARCH64 #ifdef AARCH64
{ ldp(reg3, ZR, Address(Rstack_top, 2*wordSize, post_indexed));
int offset = 0; ldp(reg1, reg2, Address(Rstack_top, 2*wordSize, post_indexed));
ldp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize;
ldp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize;
assert (offset == saved_regs_size, "should be");
add(Rstack_top, Rstack_top, saved_regs_size);
}
#else #else
pop(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); pop(RegisterSet(reg1) | RegisterSet(reg2));
#endif // AARCH64 #endif
}
ldr(Rcounters, method_counters); ldr(Rcounters, method_counters);
cbz(Rcounters, skip); // No MethodCounters created, OutOfMemory cbz(Rcounters, skip); // No MethodCounters created, OutOfMemory

View File

@ -53,9 +53,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
// Template interpreter specific version of call_VM_helper // Template interpreter specific version of call_VM_helper
virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions);
virtual void check_and_handle_popframe();
virtual void check_and_handle_earlyret();
// base routine for all dispatches // base routine for all dispatches
typedef enum { DispatchDefault, DispatchNormal } DispatchTableMode; typedef enum { DispatchDefault, DispatchNormal } DispatchTableMode;
void dispatch_base(TosState state, DispatchTableMode table_mode, bool verifyoop = true); void dispatch_base(TosState state, DispatchTableMode table_mode, bool verifyoop = true);
@ -63,6 +60,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
public: public:
InterpreterMacroAssembler(CodeBuffer* code); InterpreterMacroAssembler(CodeBuffer* code);
virtual void check_and_handle_popframe();
virtual void check_and_handle_earlyret();
// Interpreter-specific registers // Interpreter-specific registers
#if defined(AARCH64) && defined(ASSERT) #if defined(AARCH64) && defined(ASSERT)
@ -328,7 +328,13 @@ class InterpreterMacroAssembler: public MacroAssembler {
void trace_state(const char* msg) PRODUCT_RETURN; void trace_state(const char* msg) PRODUCT_RETURN;
void get_method_counters(Register method, Register Rcounters, Label& skip); void get_method_counters(Register method,
Register Rcounters,
Label& skip,
bool saveRegs = false,
Register reg1 = noreg,
Register reg2 = noreg,
Register reg3 = noreg);
}; };
#endif // CPU_ARM_VM_INTERP_MASM_ARM_HPP #endif // CPU_ARM_VM_INTERP_MASM_ARM_HPP

View File

@ -206,6 +206,9 @@ protected:
// may customize this version by overriding it for its purposes (e.g., to save/restore // may customize this version by overriding it for its purposes (e.g., to save/restore
// additional registers when doing a VM call). // additional registers when doing a VM call).
virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions);
public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {}
// These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
// The implementation is only non-empty for the InterpreterMacroAssembler, // The implementation is only non-empty for the InterpreterMacroAssembler,
@ -213,10 +216,6 @@ protected:
virtual void check_and_handle_popframe() {} virtual void check_and_handle_popframe() {}
virtual void check_and_handle_earlyret() {} virtual void check_and_handle_earlyret() {}
public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {}
// By default, we do not need relocation information for non // By default, we do not need relocation information for non
// patchable absolute addresses. However, when needed by some // patchable absolute addresses. However, when needed by some
// extensions, ignore_non_patchable_relocations can be modified, // extensions, ignore_non_patchable_relocations can be modified,

View File

@ -1,99 +0,0 @@
/*
* Copyright (c) 2008, 2015, 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.
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "assembler_arm.inline.hpp"
#include "memory/metaspaceShared.hpp"
// Generate the self-patching vtable method:
//
// This method will be called (as any other Klass virtual method) with
// the Klass itself as the first argument. Example:
//
// oop obj;
// int size = obj->klass()->oop_size(this);
//
// for which the virtual method call is Klass::oop_size();
//
// The dummy method is called with the Klass object as the first
// operand, and an object as the second argument.
//
//=====================================================================
// All of the dummy methods in the vtable are essentially identical,
// differing only by an ordinal constant, and they bear no relationship
// to the original method which the caller intended. Also, there needs
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#define __ masm->
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
for (int i = 0; i < vtbl_list_size; ++i) {
Label common_code;
for (int j = 0; j < num_virtuals; ++j) {
dummy_vtable[num_virtuals * i + j] = (void*) __ pc();
__ mov(Rtemp, j); // Rtemp contains an index of a virtual method in the table
__ b(common_code);
}
InlinedAddress vtable_address((address)&vtbl_list[i]);
__ bind(common_code);
const Register tmp2 = AARCH64_ONLY(Rtemp2) NOT_AARCH64(R4);
assert_different_registers(Rtemp, tmp2);
#ifndef AARCH64
__ push(tmp2);
#endif // !AARCH64
// Do not use ldr_global since the code must be portable across all ARM architectures
__ ldr_literal(tmp2, vtable_address);
__ ldr(tmp2, Address(tmp2)); // get correct vtable address
__ ldr(Rtemp, Address::indexed_ptr(tmp2, Rtemp)); // get real method pointer
__ str(tmp2, Address(R0)); // update vtable. R0 = "this"
#ifndef AARCH64
__ pop(tmp2);
#endif // !AARCH64
__ jump(Rtemp);
__ bind_literal(vtable_address);
}
__ flush();
*mc_top = (char*) __ pc();
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -67,7 +67,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
Register obj, Register temp1, Register temp2, SystemDictionary::WKID klass_id, Register obj, Register temp1, Register temp2, SystemDictionary::WKID klass_id,
const char* error_message) { const char* error_message) {
InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Klass* klass = SystemDictionary::well_known_klass(klass_id);
Label L_ok, L_bad; Label L_ok, L_bad;
BLOCK_COMMENT("verify_klass {"); BLOCK_COMMENT("verify_klass {");
__ verify_oop(obj); __ verify_oop(obj);

View File

@ -270,12 +270,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch
return entry; return entry;
} }
address TemplateInterpreterGenerator::generate_continuation_for(TosState state) {
// Not used.
STOP("generate_continuation_for");
return NULL;
}
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) {
address entry = __ pc(); address entry = __ pc();
@ -310,6 +304,9 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
__ convert_retval_to_tos(state); __ convert_retval_to_tos(state);
#endif // !AARCH64 #endif // !AARCH64
__ check_and_handle_popframe();
__ check_and_handle_earlyret();
__ dispatch_next(state, step); __ dispatch_next(state, step);
return entry; return entry;
@ -1401,7 +1398,13 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
#ifdef AARCH64 #ifdef AARCH64
// setup RmaxStack // setup RmaxStack
__ ldrh(RmaxStack, Address(RconstMethod, ConstMethod::max_stack_offset())); __ ldrh(RmaxStack, Address(RconstMethod, ConstMethod::max_stack_offset()));
__ add(RmaxStack, RmaxStack, MAX2(1, Method::extra_stack_entries())); // reserve slots for exception handler and JSR292 appendix argument // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots,
// none of which are at the same time, so we just need to make sure there is enough room
// for the biggest user:
// -reserved slot for exception handler
// -reserved slots for JSR292. Method::extra_stack_entries() is the size.
// -3 reserved slots so get_method_counters() can save some registers before call_VM().
__ add(RmaxStack, RmaxStack, MAX2(3, Method::extra_stack_entries()));
#endif // AARCH64 #endif // AARCH64
// see if we've got enough room on the stack for locals plus overhead. // see if we've got enough room on the stack for locals plus overhead.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -2286,13 +2286,18 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
} }
__ bind(no_mdo); __ bind(no_mdo);
// Increment backedge counter in MethodCounters* // Increment backedge counter in MethodCounters*
__ get_method_counters(Rmethod, Rcounters, dispatch); // Note Rbumped_taken_count is a callee saved registers for ARM32, but caller saved for ARM64
__ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/,
Rdisp, R3_bytecode,
AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg));
const Address mask(Rcounters, in_bytes(MethodCounters::backedge_mask_offset())); const Address mask(Rcounters, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(Rcounters, be_offset), increment, mask, __ increment_mask_and_jump(Address(Rcounters, be_offset), increment, mask,
Rcnt, R4_tmp, eq, &backedge_counter_overflow); Rcnt, R4_tmp, eq, &backedge_counter_overflow);
} else { } else {
// increment counter // Increment backedge counter in MethodCounters*
__ get_method_counters(Rmethod, Rcounters, dispatch); __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/,
Rdisp, R3_bytecode,
AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg));
__ ldr_u32(Rtemp, Address(Rcounters, be_offset)); // load backedge counter __ ldr_u32(Rtemp, Address(Rcounters, be_offset)); // load backedge counter
__ add(Rtemp, Rtemp, InvocationCounter::count_increment); // increment counter __ add(Rtemp, Rtemp, InvocationCounter::count_increment); // increment counter
__ str_32(Rtemp, Address(Rcounters, be_offset)); // store counter __ str_32(Rtemp, Address(Rcounters, be_offset)); // store counter

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved. * Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3177,9 +3177,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) {
assert_different_registers(val, crc, res); assert_different_registers(val, crc, res);
__ load_const_optimized(res, StubRoutines::crc_table_addr(), R0); __ load_const_optimized(res, StubRoutines::crc_table_addr(), R0);
__ nand(crc, crc, crc); // ~crc __ kernel_crc32_singleByteReg(crc, val, res, true);
__ update_byte_crc32(crc, val, res); __ mr(res, crc);
__ nand(res, crc, crc); // ~crc
} }
#undef __ #undef __

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved. * Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -63,18 +63,6 @@ void LIRItem::load_nonconstant() {
} }
inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) {
LIR_Opr r = li.value()->operand();
if (r->is_register()) {
LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register());
ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert.
} else {
// Constants or memory get loaded with sign extend on this platform.
ll->move(li.result(), dst);
}
}
//-------------------------------------------------------------- //--------------------------------------------------------------
// LIRGenerator // LIRGenerator
//-------------------------------------------------------------- //--------------------------------------------------------------
@ -1419,10 +1407,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
arg2 = cc->at(1), arg2 = cc->at(1),
arg3 = cc->at(2); arg3 = cc->at(2);
// CCallingConventionRequiresIntsAsLongs
crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits.
__ leal(LIR_OprFact::address(a), arg2); __ leal(LIR_OprFact::address(a), arg2);
load_int_as_long(gen()->lir(), len, arg3); len.load_item_force(arg3); // We skip int->long conversion here, , because CRC32 stub expects int.
__ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args());
__ move(result_reg, result); __ move(result_reg, result);
@ -1434,6 +1421,66 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
} }
} }
void LIRGenerator::do_update_CRC32C(Intrinsic* x) {
assert(UseCRC32CIntrinsics, "or should not be here");
LIR_Opr result = rlock_result(x);
switch (x->id()) {
case vmIntrinsics::_updateBytesCRC32C:
case vmIntrinsics::_updateDirectByteBufferCRC32C: {
bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C);
LIRItem crc(x->argument_at(0), this);
LIRItem buf(x->argument_at(1), this);
LIRItem off(x->argument_at(2), this);
LIRItem len(x->argument_at(3), this);
buf.load_item();
off.load_nonconstant();
LIR_Opr index = off.result();
int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0;
if (off.result()->is_constant()) {
index = LIR_OprFact::illegalOpr;
offset += off.result()->as_jint();
}
LIR_Opr base_op = buf.result();
LIR_Address* a = NULL;
if (index->is_valid()) {
LIR_Opr tmp = new_register(T_LONG);
__ convert(Bytecodes::_i2l, index, tmp);
index = tmp;
__ add(index, LIR_OprFact::intptrConst(offset), index);
a = new LIR_Address(base_op, index, T_BYTE);
} else {
a = new LIR_Address(base_op, offset, T_BYTE);
}
BasicTypeList signature(3);
signature.append(T_INT);
signature.append(T_ADDRESS);
signature.append(T_INT);
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
const LIR_Opr result_reg = result_register_for(x->type());
LIR_Opr arg1 = cc->at(0),
arg2 = cc->at(1),
arg3 = cc->at(2);
crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits.
__ leal(LIR_OprFact::address(a), arg2);
len.load_item_force(arg3); // We skip int->long conversion here, , because CRC32 stub expects int.
__ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args());
__ move(result_reg, result);
break;
}
default: {
ShouldNotReachHere();
}
}
}
void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
assert(x->number_of_arguments() == 3, "wrong type"); assert(x->number_of_arguments() == 3, "wrong type");
assert(UseFMA, "Needs FMA instructions support."); assert(UseFMA, "Needs FMA instructions support.");
@ -1460,7 +1507,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
fatal("vectorizedMismatch intrinsic is not implemented on this platform"); fatal("vectorizedMismatch intrinsic is not implemented on this platform");
} }
void LIRGenerator::do_update_CRC32C(Intrinsic* x) {
Unimplemented();
}

View File

@ -45,8 +45,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
#define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread #define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread
#define method_(field_name) in_bytes(Method::field_name ## _offset()), R19_method #define method_(field_name) in_bytes(Method::field_name ## _offset()), R19_method
virtual void check_and_handle_popframe(Register java_thread); virtual void check_and_handle_popframe(Register scratch_reg);
virtual void check_and_handle_earlyret(Register java_thread); virtual void check_and_handle_earlyret(Register scratch_reg);
// Base routine for all dispatches. // Base routine for all dispatches.
void dispatch_base(TosState state, address* table); void dispatch_base(TosState state, address* table);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved. * Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -4120,7 +4120,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl
* @param table register pointing to CRC table * @param table register pointing to CRC table
*/ */
void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table,
Register data, bool loopAlignment, bool invertCRC) { Register data, bool loopAlignment) {
assert_different_registers(crc, buf, len, table, data); assert_different_registers(crc, buf, len, table, data);
Label L_mainLoop, L_done; Label L_mainLoop, L_done;
@ -4131,10 +4131,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register
clrldi_(len, len, 32); // Enforce 32 bit. Anything to do? clrldi_(len, len, 32); // Enforce 32 bit. Anything to do?
beq(CCR0, L_done); beq(CCR0, L_done);
if (invertCRC) {
nand(crc, crc, crc); // ~c
}
mtctr(len); mtctr(len);
align(mainLoop_alignment); align(mainLoop_alignment);
BIND(L_mainLoop); BIND(L_mainLoop);
@ -4143,10 +4139,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register
update_byte_crc32(crc, data, table); update_byte_crc32(crc, data, table);
bdnz(L_mainLoop); // Iterate. bdnz(L_mainLoop); // Iterate.
if (invertCRC) {
nand(crc, crc, crc); // ~c
}
bind(L_done); bind(L_done);
} }
@ -4203,7 +4195,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab
*/ */
void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3, Register t0, Register t1, Register t2, Register t3,
Register tc0, Register tc1, Register tc2, Register tc3) { Register tc0, Register tc1, Register tc2, Register tc3,
bool invertCRC) {
assert_different_registers(crc, buf, len, table); assert_different_registers(crc, buf, len, table);
Label L_mainLoop, L_tail; Label L_mainLoop, L_tail;
@ -4217,14 +4210,16 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
const int complexThreshold = 2*mainLoop_stepping; const int complexThreshold = 2*mainLoop_stepping;
// Don't test for len <= 0 here. This pathological case should not occur anyway. // Don't test for len <= 0 here. This pathological case should not occur anyway.
// Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles. // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles
// The situation itself is detected and handled correctly by the conditional branches // for all well-behaved cases. The situation itself is detected and handled correctly
// following aghi(len, -stepping) and aghi(len, +stepping). // within update_byteLoop_crc32.
assert(tailLoop_stepping == 1, "check tailLoop_stepping!"); assert(tailLoop_stepping == 1, "check tailLoop_stepping!");
BLOCK_COMMENT("kernel_crc32_2word {"); BLOCK_COMMENT("kernel_crc32_2word {");
nand(crc, crc, crc); // ~c if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
// Check for short (<mainLoop_stepping) buffer. // Check for short (<mainLoop_stepping) buffer.
cmpdi(CCR0, len, complexThreshold); cmpdi(CCR0, len, complexThreshold);
@ -4245,7 +4240,7 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
blt(CCR0, L_tail); // For less than one mainloop_stepping left, do only tail processing blt(CCR0, L_tail); // For less than one mainloop_stepping left, do only tail processing
mr(len, tmp); // remaining bytes for main loop (>=mainLoop_stepping is guaranteed). mr(len, tmp); // remaining bytes for main loop (>=mainLoop_stepping is guaranteed).
} }
update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); update_byteLoop_crc32(crc, buf, tmp2, table, data, false);
} }
srdi(tmp2, len, log_stepping); // #iterations for mainLoop srdi(tmp2, len, log_stepping); // #iterations for mainLoop
@ -4281,9 +4276,11 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
// Process last few (<complexThreshold) bytes of buffer. // Process last few (<complexThreshold) bytes of buffer.
BIND(L_tail); BIND(L_tail);
update_byteLoop_crc32(crc, buf, len, table, data, false, false); update_byteLoop_crc32(crc, buf, len, table, data, false);
nand(crc, crc, crc); // ~c if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
BLOCK_COMMENT("} kernel_crc32_2word"); BLOCK_COMMENT("} kernel_crc32_2word");
} }
@ -4297,7 +4294,8 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
*/ */
void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len, Register table, void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3, Register t0, Register t1, Register t2, Register t3,
Register tc0, Register tc1, Register tc2, Register tc3) { Register tc0, Register tc1, Register tc2, Register tc3,
bool invertCRC) {
assert_different_registers(crc, buf, len, table); assert_different_registers(crc, buf, len, table);
Label L_mainLoop, L_tail; Label L_mainLoop, L_tail;
@ -4311,14 +4309,16 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len
const int complexThreshold = 2*mainLoop_stepping; const int complexThreshold = 2*mainLoop_stepping;
// Don't test for len <= 0 here. This pathological case should not occur anyway. // Don't test for len <= 0 here. This pathological case should not occur anyway.
// Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles. // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles
// The situation itself is detected and handled correctly by the conditional branches // for all well-behaved cases. The situation itself is detected and handled correctly
// following aghi(len, -stepping) and aghi(len, +stepping). // within update_byteLoop_crc32.
assert(tailLoop_stepping == 1, "check tailLoop_stepping!"); assert(tailLoop_stepping == 1, "check tailLoop_stepping!");
BLOCK_COMMENT("kernel_crc32_1word {"); BLOCK_COMMENT("kernel_crc32_1word {");
nand(crc, crc, crc); // ~c if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
// Check for short (<mainLoop_stepping) buffer. // Check for short (<mainLoop_stepping) buffer.
cmpdi(CCR0, len, complexThreshold); cmpdi(CCR0, len, complexThreshold);
@ -4339,7 +4339,7 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len
blt(CCR0, L_tail); // For less than one mainloop_stepping left, do only tail processing blt(CCR0, L_tail); // For less than one mainloop_stepping left, do only tail processing
mr(len, tmp); // remaining bytes for main loop (>=mainLoop_stepping is guaranteed). mr(len, tmp); // remaining bytes for main loop (>=mainLoop_stepping is guaranteed).
} }
update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); update_byteLoop_crc32(crc, buf, tmp2, table, data, false);
} }
srdi(tmp2, len, log_stepping); // #iterations for mainLoop srdi(tmp2, len, log_stepping); // #iterations for mainLoop
@ -4374,9 +4374,11 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len
// Process last few (<complexThreshold) bytes of buffer. // Process last few (<complexThreshold) bytes of buffer.
BIND(L_tail); BIND(L_tail);
update_byteLoop_crc32(crc, buf, len, table, data, false, false); update_byteLoop_crc32(crc, buf, len, table, data, false);
nand(crc, crc, crc); // ~c if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
BLOCK_COMMENT("} kernel_crc32_1word"); BLOCK_COMMENT("} kernel_crc32_1word");
} }
@ -4389,16 +4391,24 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len
* Uses R7_ARG5, R8_ARG6 as work registers. * Uses R7_ARG5, R8_ARG6 as work registers.
*/ */
void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3) { Register t0, Register t1, Register t2, Register t3,
bool invertCRC) {
assert_different_registers(crc, buf, len, table); assert_different_registers(crc, buf, len, table);
Register data = t0; // Holds the current byte to be folded into crc. Register data = t0; // Holds the current byte to be folded into crc.
BLOCK_COMMENT("kernel_crc32_1byte {"); BLOCK_COMMENT("kernel_crc32_1byte {");
// Process all bytes in a single-byte loop. if (invertCRC) {
update_byteLoop_crc32(crc, buf, len, table, data, true, true); nand(crc, crc, crc); // 1s complement of crc
}
// Process all bytes in a single-byte loop.
update_byteLoop_crc32(crc, buf, len, table, data, true);
if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
BLOCK_COMMENT("} kernel_crc32_1byte"); BLOCK_COMMENT("} kernel_crc32_1byte");
} }
@ -4416,7 +4426,8 @@ void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len
*/ */
void MacroAssembler::kernel_crc32_1word_vpmsumd(Register crc, Register buf, Register len, Register table, void MacroAssembler::kernel_crc32_1word_vpmsumd(Register crc, Register buf, Register len, Register table,
Register constants, Register barretConstants, Register constants, Register barretConstants,
Register t0, Register t1, Register t2, Register t3, Register t4) { Register t0, Register t1, Register t2, Register t3, Register t4,
bool invertCRC) {
assert_different_registers(crc, buf, len, table); assert_different_registers(crc, buf, len, table);
Label L_alignedHead, L_tail, L_alignTail, L_start, L_end; Label L_alignedHead, L_tail, L_alignTail, L_start, L_end;
@ -4434,13 +4445,15 @@ void MacroAssembler::kernel_crc32_1word_vpmsumd(Register crc, Register buf, Regi
Register tc0 = t4; Register tc0 = t4;
Register tc1 = constants; Register tc1 = constants;
Register tc2 = barretConstants; Register tc2 = barretConstants;
kernel_crc32_1word(crc, buf, len, table,t0, t1, t2, t3, tc0, tc1, tc2, table); kernel_crc32_1word(crc, buf, len, table,t0, t1, t2, t3, tc0, tc1, tc2, table, invertCRC);
b(L_end); b(L_end);
BIND(L_start); BIND(L_start);
// 2. ~c // 2. ~c
nand(crc, crc, crc); if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
// 3. calculate from 0 to first 128bit-aligned address // 3. calculate from 0 to first 128bit-aligned address
clrldi_(prealign, buf, 57); clrldi_(prealign, buf, 57);
@ -4449,7 +4462,7 @@ void MacroAssembler::kernel_crc32_1word_vpmsumd(Register crc, Register buf, Regi
subfic(prealign, prealign, 128); subfic(prealign, prealign, 128);
subf(len, prealign, len); subf(len, prealign, len);
update_byteLoop_crc32(crc, buf, prealign, table, t2, false, false); update_byteLoop_crc32(crc, buf, prealign, table, t2, false);
// 4. calculate from first 128bit-aligned address to last 128bit-aligned address // 4. calculate from first 128bit-aligned address to last 128bit-aligned address
BIND(L_alignedHead); BIND(L_alignedHead);
@ -4464,12 +4477,14 @@ void MacroAssembler::kernel_crc32_1word_vpmsumd(Register crc, Register buf, Regi
cmpdi(CCR0, postalign, 0); cmpdi(CCR0, postalign, 0);
beq(CCR0, L_tail); beq(CCR0, L_tail);
update_byteLoop_crc32(crc, buf, postalign, table, t2, false, false); update_byteLoop_crc32(crc, buf, postalign, table, t2, false);
BIND(L_tail); BIND(L_tail);
// 6. ~c // 6. ~c
nand(crc, crc, crc); if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
BIND(L_end); BIND(L_end);
@ -4961,16 +4976,35 @@ void MacroAssembler::kernel_crc32_1word_aligned(Register crc, Register buf, Regi
offsetInt -= 8; ld(R31, offsetInt, R1_SP); offsetInt -= 8; ld(R31, offsetInt, R1_SP);
} }
void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp) { void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp, bool invertCRC) {
assert_different_registers(crc, buf, /* len, not used!! */ table, tmp); assert_different_registers(crc, buf, /* len, not used!! */ table, tmp);
BLOCK_COMMENT("kernel_crc32_singleByte:"); BLOCK_COMMENT("kernel_crc32_singleByte:");
nand(crc, crc, crc); // ~c if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
lbz(tmp, 0, buf); // Byte from buffer, zero-extended. lbz(tmp, 0, buf); // Byte from buffer, zero-extended.
update_byte_crc32(crc, tmp, table); update_byte_crc32(crc, tmp, table);
nand(crc, crc, crc); // ~c if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
}
void MacroAssembler::kernel_crc32_singleByteReg(Register crc, Register val, Register table, bool invertCRC) {
assert_different_registers(crc, val, table);
BLOCK_COMMENT("kernel_crc32_singleByteReg:");
if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
update_byte_crc32(crc, val, table);
if (invertCRC) {
nand(crc, crc, crc); // 1s complement of crc
}
} }
// dest_lo += src1 + src2 // dest_lo += src1 + src2

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved. * Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -819,33 +819,47 @@ class MacroAssembler: public Assembler {
Register tmp6, Register tmp7, Register tmp8, Register tmp9, Register tmp10, Register tmp6, Register tmp7, Register tmp8, Register tmp9, Register tmp10,
Register tmp11, Register tmp12, Register tmp13); Register tmp11, Register tmp12, Register tmp13);
// CRC32 Intrinsics. // Emitters for CRC32 calculation.
// A note on invertCRC:
// Unfortunately, internal representation of crc differs between CRC32 and CRC32C.
// CRC32 holds it's current crc value in the externally visible representation.
// CRC32C holds it's current crc value in internal format, ready for updating.
// Thus, the crc value must be bit-flipped before updating it in the CRC32 case.
// In the CRC32C case, it must be bit-flipped when it is given to the outside world (getValue()).
// The bool invertCRC parameter indicates whether bit-flipping is required before updates.
void load_reverse_32(Register dst, Register src); void load_reverse_32(Register dst, Register src);
int crc32_table_columns(Register table, Register tc0, Register tc1, Register tc2, Register tc3); int crc32_table_columns(Register table, Register tc0, Register tc1, Register tc2, Register tc3);
void fold_byte_crc32(Register crc, Register val, Register table, Register tmp); void fold_byte_crc32(Register crc, Register val, Register table, Register tmp);
void fold_8bit_crc32(Register crc, Register table, Register tmp); void fold_8bit_crc32(Register crc, Register table, Register tmp);
void update_byte_crc32(Register crc, Register val, Register table); void update_byte_crc32(Register crc, Register val, Register table);
void update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, void update_byteLoop_crc32(Register crc, Register buf, Register len, Register table,
Register data, bool loopAlignment, bool invertCRC); Register data, bool loopAlignment);
void update_1word_crc32(Register crc, Register buf, Register table, int bufDisp, int bufInc, void update_1word_crc32(Register crc, Register buf, Register table, int bufDisp, int bufInc,
Register t0, Register t1, Register t2, Register t3, Register t0, Register t1, Register t2, Register t3,
Register tc0, Register tc1, Register tc2, Register tc3); Register tc0, Register tc1, Register tc2, Register tc3);
void kernel_crc32_2word(Register crc, Register buf, Register len, Register table, void kernel_crc32_2word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3, Register t0, Register t1, Register t2, Register t3,
Register tc0, Register tc1, Register tc2, Register tc3); Register tc0, Register tc1, Register tc2, Register tc3,
bool invertCRC);
void kernel_crc32_1word(Register crc, Register buf, Register len, Register table, void kernel_crc32_1word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3, Register t0, Register t1, Register t2, Register t3,
Register tc0, Register tc1, Register tc2, Register tc3); Register tc0, Register tc1, Register tc2, Register tc3,
bool invertCRC);
void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3); Register t0, Register t1, Register t2, Register t3,
bool invertCRC);
void kernel_crc32_1word_vpmsumd(Register crc, Register buf, Register len, Register table, void kernel_crc32_1word_vpmsumd(Register crc, Register buf, Register len, Register table,
Register constants, Register barretConstants, Register constants, Register barretConstants,
Register t0, Register t1, Register t2, Register t3, Register t4); Register t0, Register t1, Register t2, Register t3, Register t4,
bool invertCRC);
void kernel_crc32_1word_aligned(Register crc, Register buf, Register len, void kernel_crc32_1word_aligned(Register crc, Register buf, Register len,
Register constants, Register barretConstants, Register constants, Register barretConstants,
Register t0, Register t1, Register t2); Register t0, Register t1, Register t2);
void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp); void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp,
bool invertCRC);
void kernel_crc32_singleByteReg(Register crc, Register val, Register table,
bool invertCRC);
// //
// Debugging // Debugging

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. 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.
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "asm/codeBuffer.hpp"
#include "memory/metaspaceShared.hpp"
// Generate the self-patching vtable method:
//
// This method will be called (as any other Klass virtual method) with
// the Klass itself as the first argument. Example:
//
// oop obj;
// int size = obj->klass()->klass_part()->oop_size(this);
//
// for which the virtual method call is Klass::oop_size();
//
// The dummy method is called with the Klass object as the first
// operand, and an object as the second argument.
//
//=====================================================================
// All of the dummy methods in the vtable are essentially identical,
// differing only by an ordinal constant, and they bear no releationship
// to the original method which the caller intended. Also, there needs
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#define __ masm->
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
// Get ready to generate dummy methods.
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
// There are more general problems with CDS on ppc, so I can not
// really test this. But having this instead of Unimplementd() allows
// us to pass TestOptionsWithRanges.java.
__ unimplemented();
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -71,7 +71,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
Register temp_reg, Register temp2_reg, Register temp_reg, Register temp2_reg,
const char* error_message) { const char* error_message) {
InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Klass* klass = SystemDictionary::well_known_klass(klass_id);
Label L_ok, L_bad; Label L_ok, L_bad;
BLOCK_COMMENT("verify_klass {"); BLOCK_COMMENT("verify_klass {");
__ verify_oop(obj_reg); __ verify_oop(obj_reg);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved. * Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3276,6 +3276,36 @@ class StubGenerator: public StubCodeGenerator {
return start; return start;
} }
// Compute CRC32/CRC32C function.
void generate_CRC_updateBytes(const char* name, Register table, bool invertCRC) {
// arguments to kernel_crc32:
const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call.
const Register data = R4_ARG2; // source byte array
const Register dataLen = R5_ARG3; // #bytes to process
const Register t0 = R2;
const Register t1 = R7;
const Register t2 = R8;
const Register t3 = R9;
const Register tc0 = R10;
const Register tc1 = R11;
const Register tc2 = R12;
BLOCK_COMMENT("Stub body {");
assert_different_registers(crc, data, dataLen, table);
__ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table, invertCRC);
BLOCK_COMMENT("return");
__ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET).
__ blr();
BLOCK_COMMENT("} Stub body");
}
/** /**
* Arguments: * Arguments:
* *
@ -3296,14 +3326,14 @@ class StubGenerator: public StubCodeGenerator {
StubCodeMark mark(this, "StubRoutines", name); StubCodeMark mark(this, "StubRoutines", name);
address start = __ function_entry(); // Remember stub start address (is rtn value). address start = __ function_entry(); // Remember stub start address (is rtn value).
const Register table = R6; // crc table address
#ifdef VM_LITTLE_ENDIAN
// arguments to kernel_crc32: // arguments to kernel_crc32:
const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call.
const Register data = R4_ARG2; // source byte array const Register data = R4_ARG2; // source byte array
const Register dataLen = R5_ARG3; // #bytes to process const Register dataLen = R5_ARG3; // #bytes to process
const Register table = R6; // crc table address
#ifdef VM_LITTLE_ENDIAN
if (VM_Version::has_vpmsumb()) { if (VM_Version::has_vpmsumb()) {
const Register constants = R2; // constants address const Register constants = R2; // constants address
const Register bconstants = R8; // barret table address const Register bconstants = R8; // barret table address
@ -3321,7 +3351,7 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::ppc64::generate_load_crc_constants_addr(_masm, constants); StubRoutines::ppc64::generate_load_crc_constants_addr(_masm, constants);
StubRoutines::ppc64::generate_load_crc_barret_constants_addr(_masm, bconstants); StubRoutines::ppc64::generate_load_crc_barret_constants_addr(_masm, bconstants);
__ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4); __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4, true);
BLOCK_COMMENT("return"); BLOCK_COMMENT("return");
__ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET).
@ -3331,31 +3361,79 @@ class StubGenerator: public StubCodeGenerator {
} else } else
#endif #endif
{ {
const Register t0 = R2; StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table);
const Register t1 = R7; generate_CRC_updateBytes(name, table, true);
const Register t2 = R8; }
const Register t3 = R9;
const Register tc0 = R10; return start;
const Register tc1 = R11; }
const Register tc2 = R12;
/**
* Arguments:
*
* Inputs:
* R3_ARG1 - int crc
* R4_ARG2 - byte* buf
* R5_ARG3 - int length (of buffer)
*
* scratch:
* R2, R6-R12
*
* Ouput:
* R3_RET - int crc result
*/
// Compute CRC32C function.
address generate_CRC32C_updateBytes(const char* name) {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", name);
address start = __ function_entry(); // Remember stub start address (is rtn value).
const Register table = R6; // crc table address
#if 0 // no vector support yet for CRC32C
#ifdef VM_LITTLE_ENDIAN
// arguments to kernel_crc32:
const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call.
const Register data = R4_ARG2; // source byte array
const Register dataLen = R5_ARG3; // #bytes to process
if (VM_Version::has_vpmsumb()) {
const Register constants = R2; // constants address
const Register bconstants = R8; // barret table address
const Register t0 = R9;
const Register t1 = R10;
const Register t2 = R11;
const Register t3 = R12;
const Register t4 = R7;
BLOCK_COMMENT("Stub body {"); BLOCK_COMMENT("Stub body {");
assert_different_registers(crc, data, dataLen, table); assert_different_registers(crc, data, dataLen, table);
StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table);
StubRoutines::ppc64::generate_load_crc32c_constants_addr(_masm, constants);
StubRoutines::ppc64::generate_load_crc32c_barret_constants_addr(_masm, bconstants);
__ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table); __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4, false);
BLOCK_COMMENT("return"); BLOCK_COMMENT("return");
__ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET).
__ blr(); __ blr();
BLOCK_COMMENT("} Stub body"); BLOCK_COMMENT("} Stub body");
} else
#endif
#endif
{
StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table);
generate_CRC_updateBytes(name, table, false);
} }
return start; return start;
} }
// Initialization // Initialization
void generate_initial() { void generate_initial() {
// Generates all stubs and initializes the entry points // Generates all stubs and initializes the entry points
@ -3383,6 +3461,12 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_crc_table_adr = (address)StubRoutines::ppc64::_crc_table; StubRoutines::_crc_table_adr = (address)StubRoutines::ppc64::_crc_table;
StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes");
} }
// CRC32C Intrinsics.
if (UseCRC32CIntrinsics) {
StubRoutines::_crc32c_table_addr = (address)StubRoutines::ppc64::_crc32c_table;
StubRoutines::_updateBytesCRC32C = generate_CRC32C_updateBytes("CRC32C_updateBytes");
}
} }
void generate_all() { void generate_all() {

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved. * Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -55,13 +55,16 @@ class ppc64 {
// CRC32 Intrinsics. // CRC32 Intrinsics.
static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE];
static juint _crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE];
static juint* _constants; static juint* _constants;
static juint* _barret_constants; static juint* _barret_constants;
public: public:
// CRC32 Intrinsics. // CRC32 Intrinsics.
static void generate_load_table_addr(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents);
static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); static void generate_load_crc_table_addr(MacroAssembler* masm, Register table);
static void generate_load_crc32c_table_addr(MacroAssembler* masm, Register table);
static void generate_load_crc_constants_addr(MacroAssembler* masm, Register table); static void generate_load_crc_constants_addr(MacroAssembler* masm, Register table);
static void generate_load_crc_barret_constants_addr(MacroAssembler* masm, Register table); static void generate_load_crc_barret_constants_addr(MacroAssembler* masm, Register table);
static juint* generate_crc_constants(); static juint* generate_crc_constants();

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017 SAP SE. All rights reserved. * Copyright (c) 2015, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -643,12 +643,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch
return entry; return entry;
} }
address TemplateInterpreterGenerator::generate_continuation_for(TosState state) {
address entry = __ pc();
__ unimplemented("generate_continuation_for");
return entry;
}
// This entry is returned to when a call returns to the interpreter. // This entry is returned to when a call returns to the interpreter.
// When we arrive here, we expect that the callee stack frame is already popped. // When we arrive here, we expect that the callee stack frame is already popped.
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) {
@ -692,6 +686,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
#endif #endif
__ sldi(size, size, Interpreter::logStackElementSize); __ sldi(size, size, Interpreter::logStackElementSize);
__ add(R15_esp, R15_esp, size); __ add(R15_esp, R15_esp, size);
__ check_and_handle_popframe(R11_scratch1);
__ check_and_handle_earlyret(R11_scratch1);
__ dispatch_next(state, step); __ dispatch_next(state, step);
return entry; return entry;
} }
@ -1894,7 +1892,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
__ lwz(crc, 2*wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. __ lwz(crc, 2*wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register.
StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table);
__ kernel_crc32_singleByte(crc, data, dataLen, table, tmp); __ kernel_crc32_singleByte(crc, data, dataLen, table, tmp, true);
// Restore caller sp for c2i case and return. // Restore caller sp for c2i case and return.
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
@ -1910,6 +1908,10 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
return NULL; return NULL;
} }
// TODO: generate_CRC32_updateBytes_entry and generate_CRC32C_updateBytes_entry are identical
// except for using different crc tables and some block comment strings.
// We should provide a common implementation.
// CRC32 Intrinsics. // CRC32 Intrinsics.
/** /**
* Method entry for static native methods: * Method entry for static native methods:
@ -1986,7 +1988,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
// Performance measurements show the 1word and 2word variants to be almost equivalent, // Performance measurements show the 1word and 2word variants to be almost equivalent,
// with very light advantages for the 1word variant. We chose the 1word variant for // with very light advantages for the 1word variant. We chose the 1word variant for
// code compactness. // code compactness.
__ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3); __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, true);
// Restore caller sp for c2i case and return. // Restore caller sp for c2i case and return.
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
@ -2002,8 +2004,84 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
return NULL; return NULL;
} }
// Not supported // CRC32C Intrinsics.
/**
* Method entry for static native methods:
* int java.util.zip.CRC32C.updateBytes( int crc, byte[] b, int off, int len)
* int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long* buf, int off, int len)
**/
address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
if (UseCRC32CIntrinsics) {
address start = __ pc(); // Remember stub start address (is rtn value).
// We don't generate local frame and don't align stack because
// we not even call stub code (we generate the code inline)
// and there is no safepoint on this path.
// Load parameters.
// Z_esp is callers operand stack pointer, i.e. it points to the parameters.
const Register argP = R15_esp;
const Register crc = R3_ARG1; // crc value
const Register data = R4_ARG2; // address of java byte array
const Register dataLen = R5_ARG3; // source data len
const Register table = R6_ARG4; // address of crc32c table
const Register t0 = R9; // scratch registers for crc calculation
const Register t1 = R10;
const Register t2 = R11;
const Register t3 = R12;
const Register tc0 = R2; // registers to hold pre-calculated column addresses
const Register tc1 = R7;
const Register tc2 = R8;
const Register tc3 = table; // table address is reconstructed at the end of kernel_crc32_* emitters
const Register tmp = t0; // Only used very locally to calculate byte buffer address.
// Arguments are reversed on java expression stack.
// Calculate address of start element.
if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateDirectByteBuffer".
BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {");
// crc @ (SP + 5W) (32bit)
// buf @ (SP + 3W) (64bit ptr to long array)
// off @ (SP + 2W) (32bit)
// dataLen @ (SP + 1W) (32bit)
// data = buf + off
__ ld( data, 3*wordSize, argP); // start of byte buffer
__ lwa( tmp, 2*wordSize, argP); // byte buffer offset
__ lwa( dataLen, 1*wordSize, argP); // #bytes to process
__ lwz( crc, 5*wordSize, argP); // current crc state
__ add( data, data, tmp); // Add byte buffer offset.
} else { // Used for "updateBytes update".
BLOCK_COMMENT("CRC32C_updateBytes {");
// crc @ (SP + 4W) (32bit)
// buf @ (SP + 3W) (64bit ptr to byte array)
// off @ (SP + 2W) (32bit)
// dataLen @ (SP + 1W) (32bit)
// data = buf + off + base_offset
__ ld( data, 3*wordSize, argP); // start of byte buffer
__ lwa( tmp, 2*wordSize, argP); // byte buffer offset
__ lwa( dataLen, 1*wordSize, argP); // #bytes to process
__ add( data, data, tmp); // add byte buffer offset
__ lwz( crc, 4*wordSize, argP); // current crc state
__ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE));
}
StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table);
// Performance measurements show the 1word and 2word variants to be almost equivalent,
// with very light advantages for the 1word variant. We chose the 1word variant for
// code compactness.
__ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, false);
// Restore caller sp for c2i case and return.
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
__ blr();
BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}");
return start;
}
return NULL; return NULL;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved. * Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -172,18 +172,27 @@ void VM_Version::initialize() {
assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive");
// Implementation does not use any of the vector instructions // If defined(VM_LITTLE_ENDIAN) and running on Power8 or newer hardware,
// available with Power8. Their exploitation is still pending. // the implementation uses the vector instructions available with Power8.
// In all other cases, the implementation uses only generally available instructions.
if (!UseCRC32Intrinsics) { if (!UseCRC32Intrinsics) {
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); FLAG_SET_DEFAULT(UseCRC32Intrinsics, true);
} }
} }
if (UseCRC32CIntrinsics) { // Implementation does not use any of the vector instructions available with Power8.
if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) // Their exploitation is still pending (aka "work in progress").
warning("CRC32C intrinsics are not available on this CPU"); if (!UseCRC32CIntrinsics) {
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true);
}
}
// TODO: Provide implementation.
if (UseAdler32Intrinsics) {
warning("Adler32Intrinsics not available on this CPU.");
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
} }
// The AES intrinsic stubs require AES instruction support. // The AES intrinsic stubs require AES instruction support.
@ -245,11 +254,6 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
} }
if (UseAdler32Intrinsics) {
warning("Adler32Intrinsics not available on this CPU.");
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
}
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
UseMultiplyToLenIntrinsic = true; UseMultiplyToLenIntrinsic = true;
} }

View File

@ -28,8 +28,6 @@
#undef LUCY_DBG #undef LUCY_DBG
#define NearLabel Label
// Immediate is an abstraction to represent the various immediate // Immediate is an abstraction to represent the various immediate
// operands which exist on z/Architecture. Neither this class nor // operands which exist on z/Architecture. Neither this class nor
// instances hereof have an own state. It consists of methods only. // instances hereof have an own state. It consists of methods only.

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3048,9 +3048,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) {
assert_different_registers(val, crc, res); assert_different_registers(val, crc, res);
__ load_const_optimized(res, StubRoutines::crc_table_addr()); __ load_const_optimized(res, StubRoutines::crc_table_addr());
__ not_(crc, noreg, false); // ~crc __ kernel_crc32_singleByteReg(crc, val, res, true);
__ update_byte_crc32(crc, val, res); __ z_lgfr(res, crc);
__ not_(res, crc, false); // ~crc
} }
#undef __ #undef __

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -61,20 +61,6 @@ void LIRItem::load_nonconstant(int bits) {
} }
} }
inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) {
LIR_Opr r = li.value()->operand();
if (r->is_constant()) {
// Constants get loaded with sign extend on this platform.
ll->move(li.result(), dst);
} else {
if (!r->is_register()) {
li.load_item_force(dst);
}
LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register());
ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert.
}
}
//-------------------------------------------------------------- //--------------------------------------------------------------
// LIRGenerator // LIRGenerator
//-------------------------------------------------------------- //--------------------------------------------------------------
@ -1217,10 +1203,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
LIR_Opr arg2 = cc->at(1); LIR_Opr arg2 = cc->at(1);
LIR_Opr arg3 = cc->at(2); LIR_Opr arg3 = cc->at(2);
// CCallingConventionRequiresIntsAsLongs
crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits.
__ leal(LIR_OprFact::address(a), arg2); __ leal(LIR_OprFact::address(a), arg2);
load_int_as_long(gen()->lir(), len, arg3); len.load_item_force(arg3); // We skip int->long conversion here, because CRC32 stub expects int.
__ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args());
__ move(result_reg, result); __ move(result_reg, result);
@ -1233,7 +1218,60 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
} }
void LIRGenerator::do_update_CRC32C(Intrinsic* x) { void LIRGenerator::do_update_CRC32C(Intrinsic* x) {
Unimplemented(); assert(UseCRC32CIntrinsics, "or should not be here");
LIR_Opr result = rlock_result(x);
switch (x->id()) {
case vmIntrinsics::_updateBytesCRC32C:
case vmIntrinsics::_updateDirectByteBufferCRC32C: {
bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C);
LIRItem crc(x->argument_at(0), this);
LIRItem buf(x->argument_at(1), this);
LIRItem off(x->argument_at(2), this);
LIRItem len(x->argument_at(3), this);
buf.load_item();
off.load_nonconstant();
LIR_Opr index = off.result();
int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0;
if (off.result()->is_constant()) {
index = LIR_OprFact::illegalOpr;
offset += off.result()->as_jint();
}
LIR_Opr base_op = buf.result();
if (index->is_valid()) {
LIR_Opr tmp = new_register(T_LONG);
__ convert(Bytecodes::_i2l, index, tmp);
index = tmp;
}
LIR_Address* a = new LIR_Address(base_op, index, offset, T_BYTE);
BasicTypeList signature(3);
signature.append(T_INT);
signature.append(T_ADDRESS);
signature.append(T_INT);
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
const LIR_Opr result_reg = result_register_for (x->type());
LIR_Opr arg1 = cc->at(0);
LIR_Opr arg2 = cc->at(1);
LIR_Opr arg3 = cc->at(2);
crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32C stub doesn't care about high bits.
__ leal(LIR_OprFact::address(a), arg2);
len.load_item_force(arg3); // We skip int->long conversion here, because CRC32C stub expects int.
__ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args());
__ move(result_reg, result);
break;
}
default: {
ShouldNotReachHere();
}
}
} }
void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
@ -1264,4 +1302,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
fatal("vectorizedMismatch intrinsic is not implemented on this platform"); fatal("vectorizedMismatch intrinsic is not implemented on this platform");
} }

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.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
bool allow_relocation, bool allow_relocation,
bool check_exceptions); bool check_exceptions);
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
// Base routine for all dispatches. // Base routine for all dispatches.
void dispatch_base(TosState state, address* table); void dispatch_base(TosState state, address* table);
@ -58,6 +55,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
InterpreterMacroAssembler(CodeBuffer* c) InterpreterMacroAssembler(CodeBuffer* c)
: MacroAssembler(c) {} : MacroAssembler(c) {}
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
void jump_to_entry(address entry, Register Rscratch); void jump_to_entry(address entry, Register Rscratch);
virtual void load_earlyret_value(TosState state); virtual void load_earlyret_value(TosState state);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1616,6 +1616,8 @@ void MacroAssembler::branch_optimized(Assembler::branch_condition cond, Label& b
if (branch_target.is_bound()) { if (branch_target.is_bound()) {
address branch_addr = target(branch_target); address branch_addr = target(branch_target);
branch_optimized(cond, branch_addr); branch_optimized(cond, branch_addr);
} else if (branch_target.is_near()) {
z_brc(cond, branch_target); // Caller assures that the target will be in range for z_brc.
} else { } else {
z_brcl(cond, branch_target); // Let's hope target is in range. Otherwise, we will abort at patch time. z_brcl(cond, branch_target); // Let's hope target is in range. Otherwise, we will abort at patch time.
} }
@ -1674,7 +1676,8 @@ void MacroAssembler::compare_and_branch_optimized(Register r1,
bool has_sign) { bool has_sign) {
address branch_origin = pc(); address branch_origin = pc();
bool x2_imm8 = (has_sign && Immediate::is_simm8(x2)) || (!has_sign && Immediate::is_uimm8(x2)); bool x2_imm8 = (has_sign && Immediate::is_simm8(x2)) || (!has_sign && Immediate::is_uimm8(x2));
bool is_RelAddr16 = (branch_target.is_bound() && bool is_RelAddr16 = branch_target.is_near() ||
(branch_target.is_bound() &&
RelAddr::is_in_range_of_RelAddr16(target(branch_target), branch_origin)); RelAddr::is_in_range_of_RelAddr16(target(branch_target), branch_origin));
unsigned int casenum = (len64?2:0)+(has_sign?0:1); unsigned int casenum = (len64?2:0)+(has_sign?0:1);
@ -1744,13 +1747,21 @@ void MacroAssembler::compare_and_branch_optimized(Register r1,
Label& branch_target, Label& branch_target,
bool len64, bool len64,
bool has_sign) { bool has_sign) {
unsigned int casenum = (len64?2:0)+(has_sign?0:1); unsigned int casenum = (len64 ? 2 : 0) + (has_sign ? 0 : 1);
if (branch_target.is_bound()) { if (branch_target.is_bound()) {
address branch_addr = target(branch_target); address branch_addr = target(branch_target);
compare_and_branch_optimized(r1, r2, cond, branch_addr, len64, has_sign); compare_and_branch_optimized(r1, r2, cond, branch_addr, len64, has_sign);
} else { } else {
{ if (VM_Version::has_CompareBranch() && branch_target.is_near()) {
switch (casenum) {
case 0: z_crj( r1, r2, cond, branch_target); break;
case 1: z_clrj( r1, r2, cond, branch_target); break;
case 2: z_cgrj( r1, r2, cond, branch_target); break;
case 3: z_clgrj(r1, r2, cond, branch_target); break;
default: ShouldNotReachHere(); break;
}
} else {
switch (casenum) { switch (casenum) {
case 0: z_cr( r1, r2); break; case 0: z_cr( r1, r2); break;
case 1: z_clr(r1, r2); break; case 1: z_clr(r1, r2); break;
@ -2741,11 +2752,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
BLOCK_COMMENT("lookup_interface_method {"); BLOCK_COMMENT("lookup_interface_method {");
// Load start of itable entries into itable_entry_addr. // Load start of itable entries into itable_entry_addr.
z_llgf(vtable_len, Address(recv_klass, InstanceKlass::vtable_length_offset())); z_llgf(vtable_len, Address(recv_klass, Klass::vtable_length_offset()));
z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes()));
// Loop over all itable entries until desired interfaceOop(Rinterface) found. // Loop over all itable entries until desired interfaceOop(Rinterface) found.
const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); const int vtable_base_offset = in_bytes(Klass::vtable_start_offset());
add2reg_with_index(itable_entry_addr, add2reg_with_index(itable_entry_addr,
vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(),
@ -5927,8 +5938,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl
* @param len register containing number of bytes * @param len register containing number of bytes
* @param table register pointing to CRC table * @param table register pointing to CRC table
*/ */
void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, Register data) {
Register data, bool invertCRC) {
assert_different_registers(crc, buf, len, table, data); assert_different_registers(crc, buf, len, table, data);
Label L_mainLoop, L_done; Label L_mainLoop, L_done;
@ -5938,20 +5948,12 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register
z_ltr(len, len); z_ltr(len, len);
z_brnh(L_done); z_brnh(L_done);
if (invertCRC) {
not_(crc, noreg, false); // ~c
}
bind(L_mainLoop); bind(L_mainLoop);
z_llgc(data, Address(buf, (intptr_t)0));// Current byte of input buffer (zero extended). Avoids garbage in upper half of register. z_llgc(data, Address(buf, (intptr_t)0));// Current byte of input buffer (zero extended). Avoids garbage in upper half of register.
add2reg(buf, mainLoop_stepping); // Advance buffer position. add2reg(buf, mainLoop_stepping); // Advance buffer position.
update_byte_crc32(crc, data, table); update_byte_crc32(crc, data, table);
z_brct(len, L_mainLoop); // Iterate. z_brct(len, L_mainLoop); // Iterate.
if (invertCRC) {
not_(crc, noreg, false); // ~c
}
bind(L_done); bind(L_done);
} }
@ -5968,6 +5970,7 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab
// c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ // c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
// crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] // crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
// #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 // #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
// Pre-calculate (constant) column offsets, use columns 4..7 for big-endian.
const int ix0 = 4*(4*CRC32_COLUMN_SIZE); const int ix0 = 4*(4*CRC32_COLUMN_SIZE);
const int ix1 = 5*(4*CRC32_COLUMN_SIZE); const int ix1 = 5*(4*CRC32_COLUMN_SIZE);
const int ix2 = 6*(4*CRC32_COLUMN_SIZE); const int ix2 = 6*(4*CRC32_COLUMN_SIZE);
@ -5986,17 +5989,12 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab
rotate_then_insert(t1, t0, 56-2, 63-2, 2-16, true); // ((c >> 16) & 0xff) << 2 rotate_then_insert(t1, t0, 56-2, 63-2, 2-16, true); // ((c >> 16) & 0xff) << 2
rotate_then_insert(t0, t0, 56-2, 63-2, 2-24, true); // ((c >> 24) & 0xff) << 2 rotate_then_insert(t0, t0, 56-2, 63-2, 2-24, true); // ((c >> 24) & 0xff) << 2
// Load pre-calculated table values. // XOR indexed table values to calculate updated crc.
// Use columns 4..7 for big-endian.
z_ly(t3, Address(table, t3, (intptr_t)ix0));
z_ly(t2, Address(table, t2, (intptr_t)ix1)); z_ly(t2, Address(table, t2, (intptr_t)ix1));
z_ly(t1, Address(table, t1, (intptr_t)ix2));
z_ly(t0, Address(table, t0, (intptr_t)ix3)); z_ly(t0, Address(table, t0, (intptr_t)ix3));
z_xy(t2, Address(table, t3, (intptr_t)ix0));
// Calculate new crc from table values. z_xy(t0, Address(table, t1, (intptr_t)ix2));
z_xr(t2, t3); z_xr(t0, t2); // Now t0 contains the updated CRC value.
z_xr(t0, t1);
z_xr(t0, t2); // Now crc contains the final checksum value.
lgr_if_needed(crc, t0); lgr_if_needed(crc, t0);
} }
@ -6009,7 +6007,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab
* uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller!
*/ */
void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3) { Register t0, Register t1, Register t2, Register t3,
bool invertCRC) {
assert_different_registers(crc, buf, len, table); assert_different_registers(crc, buf, len, table);
Label L_mainLoop, L_tail; Label L_mainLoop, L_tail;
@ -6024,7 +6023,9 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
// The situation itself is detected and handled correctly by the conditional branches // The situation itself is detected and handled correctly by the conditional branches
// following aghi(len, -stepping) and aghi(len, +stepping). // following aghi(len, -stepping) and aghi(len, +stepping).
not_(crc, noreg, false); // 1s complement of crc if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
#if 0 #if 0
{ {
@ -6039,7 +6040,7 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
rotate_then_insert(ctr, ctr, 62, 63, 0, true); // TODO: should set cc rotate_then_insert(ctr, ctr, 62, 63, 0, true); // TODO: should set cc
z_sgfr(len, ctr); // Remaining len after alignment. z_sgfr(len, ctr); // Remaining len after alignment.
update_byteLoop_crc32(crc, buf, ctr, table, data, false); update_byteLoop_crc32(crc, buf, ctr, table, data);
} }
#endif #endif
@ -6047,21 +6048,23 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
z_srag(ctr, len, log_stepping); z_srag(ctr, len, log_stepping);
z_brnh(L_tail); z_brnh(L_tail);
z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data. z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data.
rotate_then_insert(len, len, 64-log_stepping, 63, 0, true); // #bytes for tailLoop rotate_then_insert(len, len, 64-log_stepping, 63, 0, true); // #bytes for tailLoop
BIND(L_mainLoop); BIND(L_mainLoop);
update_1word_crc32(crc, buf, table, 0, 0, crc, t1, t2, t3); update_1word_crc32(crc, buf, table, 0, 0, crc, t1, t2, t3);
update_1word_crc32(crc, buf, table, 4, mainLoop_stepping, crc, t1, t2, t3); update_1word_crc32(crc, buf, table, 4, mainLoop_stepping, crc, t1, t2, t3);
z_brct(ctr, L_mainLoop); // Iterate. z_brct(ctr, L_mainLoop); // Iterate.
z_lrvr(crc, crc); // Revert byte order back to original. z_lrvr(crc, crc); // Revert byte order back to original.
// Process last few (<8) bytes of buffer. // Process last few (<8) bytes of buffer.
BIND(L_tail); BIND(L_tail);
update_byteLoop_crc32(crc, buf, len, table, data, false); update_byteLoop_crc32(crc, buf, len, table, data);
not_(crc, noreg, false); // 1s complement of crc if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
} }
/** /**
@ -6073,7 +6076,8 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len
* uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller!
*/ */
void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len, Register table, void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3) { Register t0, Register t1, Register t2, Register t3,
bool invertCRC) {
assert_different_registers(crc, buf, len, table); assert_different_registers(crc, buf, len, table);
Label L_mainLoop, L_tail; Label L_mainLoop, L_tail;
@ -6087,7 +6091,9 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len
// The situation itself is detected and handled correctly by the conditional branches // The situation itself is detected and handled correctly by the conditional branches
// following aghi(len, -stepping) and aghi(len, +stepping). // following aghi(len, -stepping) and aghi(len, +stepping).
not_(crc, noreg, false); // 1s complement of crc if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
// Check for short (<4 bytes) buffer. // Check for short (<4 bytes) buffer.
z_srag(ctr, len, log_stepping); z_srag(ctr, len, log_stepping);
@ -6099,13 +6105,16 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len
BIND(L_mainLoop); BIND(L_mainLoop);
update_1word_crc32(crc, buf, table, 0, mainLoop_stepping, crc, t1, t2, t3); update_1word_crc32(crc, buf, table, 0, mainLoop_stepping, crc, t1, t2, t3);
z_brct(ctr, L_mainLoop); // Iterate. z_brct(ctr, L_mainLoop); // Iterate.
z_lrvr(crc, crc); // Revert byte order back to original. z_lrvr(crc, crc); // Revert byte order back to original.
// Process last few (<8) bytes of buffer. // Process last few (<8) bytes of buffer.
BIND(L_tail); BIND(L_tail);
update_byteLoop_crc32(crc, buf, len, table, data, false); update_byteLoop_crc32(crc, buf, len, table, data);
not_(crc, noreg, false); // 1s complement of crc if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
} }
/** /**
@ -6115,22 +6124,51 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len
* @param table register pointing to CRC table * @param table register pointing to CRC table
*/ */
void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3) { Register t0, Register t1, Register t2, Register t3,
bool invertCRC) {
assert_different_registers(crc, buf, len, table); assert_different_registers(crc, buf, len, table);
Register data = t0; Register data = t0;
update_byteLoop_crc32(crc, buf, len, table, data, true); if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
update_byteLoop_crc32(crc, buf, len, table, data);
if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
} }
void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp) { void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp,
bool invertCRC) {
assert_different_registers(crc, buf, len, table, tmp); assert_different_registers(crc, buf, len, table, tmp);
not_(crc, noreg, false); // ~c if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
z_llgc(tmp, Address(buf, (intptr_t)0)); // Current byte of input buffer (zero extended). Avoids garbage in upper half of register. z_llgc(tmp, Address(buf, (intptr_t)0)); // Current byte of input buffer (zero extended). Avoids garbage in upper half of register.
update_byte_crc32(crc, tmp, table); update_byte_crc32(crc, tmp, table);
not_(crc, noreg, false); // ~c if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
}
void MacroAssembler::kernel_crc32_singleByteReg(Register crc, Register val, Register table,
bool invertCRC) {
assert_different_registers(crc, val, table);
if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
update_byte_crc32(crc, val, table);
if (invertCRC) {
not_(crc, noreg, false); // 1s complement of crc
}
} }
// //

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1011,22 +1011,35 @@ class MacroAssembler: public Assembler {
int before = 0, int after = 0) PRODUCT_RETURN; int before = 0, int after = 0) PRODUCT_RETURN;
// Emitters for CRC32 calculation. // Emitters for CRC32 calculation.
// A note on invertCRC:
// Unfortunately, internal representation of crc differs between CRC32 and CRC32C.
// CRC32 holds it's current crc value in the externally visible representation.
// CRC32C holds it's current crc value in internal format, ready for updating.
// Thus, the crc value must be bit-flipped before updating it in the CRC32 case.
// In the CRC32C case, it must be bit-flipped when it is given to the outside world (getValue()).
// The bool invertCRC parameter indicates whether bit-flipping is required before updates.
private: private:
void fold_byte_crc32(Register crc, Register table, Register val, Register tmp); void fold_byte_crc32(Register crc, Register table, Register val, Register tmp);
void fold_8bit_crc32(Register crc, Register table, Register tmp); void fold_8bit_crc32(Register crc, Register table, Register tmp);
void update_byte_crc32( Register crc, Register val, Register table);
void update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, void update_byteLoop_crc32(Register crc, Register buf, Register len, Register table,
Register data, bool invertCRC); Register data);
void update_1word_crc32(Register crc, Register buf, Register table, int bufDisp, int bufInc, void update_1word_crc32(Register crc, Register buf, Register table, int bufDisp, int bufInc,
Register t0, Register t1, Register t2, Register t3); Register t0, Register t1, Register t2, Register t3);
public: public:
void update_byte_crc32( Register crc, Register val, Register table); void kernel_crc32_singleByteReg(Register crc, Register val, Register table,
void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp); bool invertCRC);
void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp,
bool invertCRC);
void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3); Register t0, Register t1, Register t2, Register t3,
bool invertCRC);
void kernel_crc32_1word(Register crc, Register buf, Register len, Register table, void kernel_crc32_1word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3); Register t0, Register t1, Register t2, Register t3,
bool invertCRC);
void kernel_crc32_2word(Register crc, Register buf, Register len, Register table, void kernel_crc32_2word(Register crc, Register buf, Register len, Register table,
Register t0, Register t1, Register t2, Register t3); Register t0, Register t1, Register t2, Register t3,
bool invertCRC);
// Emitters for BigInteger.multiplyToLen intrinsic // Emitters for BigInteger.multiplyToLen intrinsic
// note: length of result array (zlen) is passed on the stack // note: length of result array (zlen) is passed on the stack

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. 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.
*
*/
#include "precompiled.hpp"
#include "asm/codeBuffer.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "memory/metaspaceShared.hpp"
// Generate the self-patching vtable method:
//
// This method will be called (as any other Klass virtual method) with
// the Klass itself as the first argument. Example:
//
// oop obj;
// int size = obj->klass()->klass_part()->oop_size(this);
//
// for which the virtual method call is Klass::oop_size();.
//
// The dummy method is called with the Klass object as the first
// operand, and an object as the second argument.
//
//=====================================================================
// All of the dummy methods in the vtable are essentially identical,
// differing only by an ordinal constant, and they bear no releationship
// to the original method which the caller intended. Also, there needs
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#undef __
#define __ masm->
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
// Get ready to generate dummy methods.
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
__ unimplemented();
}

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.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -73,7 +73,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
const char* error_message) { const char* error_message) {
InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Klass* klass = SystemDictionary::well_known_klass(klass_id);
assert(temp_reg != Z_R0 && // Is used as base register! assert(temp_reg != Z_R0 && // Is used as base register!
temp_reg != noreg && temp2_reg != noreg, "need valid registers!"); temp_reg != noreg && temp2_reg != noreg, "need valid registers!");

View File

@ -6768,6 +6768,7 @@ instruct sllI_reg_imm(iRegI dst, iRegI src, immI nbits) %{
format %{ "SLL $dst,$src,$nbits\t# use RISC-like SLLG also for int" %} format %{ "SLL $dst,$src,$nbits\t# use RISC-like SLLG also for int" %}
ins_encode %{ ins_encode %{
int Nbit = $nbits$$constant; int Nbit = $nbits$$constant;
assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph");
__ z_sllg($dst$$Register, $src$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); __ z_sllg($dst$$Register, $src$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0);
%} %}
ins_pipe(pipe_class_dummy); ins_pipe(pipe_class_dummy);
@ -6841,6 +6842,7 @@ instruct sraI_reg_imm(iRegI dst, immI src, flagsReg cr) %{
format %{ "SRA $dst,$src" %} format %{ "SRA $dst,$src" %}
ins_encode %{ ins_encode %{
int Nbit = $src$$constant; int Nbit = $src$$constant;
assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph");
__ z_sra($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); __ z_sra($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0);
%} %}
ins_pipe(pipe_class_dummy); ins_pipe(pipe_class_dummy);
@ -6893,6 +6895,7 @@ instruct srlI_reg_imm(iRegI dst, immI src) %{
format %{ "SRL $dst,$src" %} format %{ "SRL $dst,$src" %}
ins_encode %{ ins_encode %{
int Nbit = $src$$constant; int Nbit = $src$$constant;
assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph");
__ z_srl($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); __ z_srl($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0);
%} %}
ins_pipe(pipe_class_dummy); ins_pipe(pipe_class_dummy);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -623,26 +623,6 @@ class StubGenerator: public StubCodeGenerator {
#define __ (Verbose ? (_masm->block_comment(FILE_AND_LINE),_masm):_masm)-> #define __ (Verbose ? (_masm->block_comment(FILE_AND_LINE),_masm):_masm)->
#endif #endif
//----------------------------------------------------------------------
// The following routine generates a subroutine to throw an asynchronous
// UnknownError when an unsafe access gets a fault that could not be
// reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
//
// Arguments:
// trapping PC: ??
//
// Results:
// Posts an asynchronous exception, skips the trapping instruction.
//
address generate_handler_for_unsafe_access() {
StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
{
address start = __ pc();
__ unimplemented("StubRoutines::handler_for_unsafe_access", 86);
return start;
}
}
// Support for uint StubRoutine::zarch::partial_subtype_check(Klass // Support for uint StubRoutine::zarch::partial_subtype_check(Klass
// sub, Klass super); // sub, Klass super);
// //
@ -2330,26 +2310,25 @@ class StubGenerator: public StubCodeGenerator {
} }
/**
// Arguments: * Arguments:
// Z_ARG1 - int crc *
// Z_ARG2 - byte* buf * Inputs:
// Z_ARG3 - int length (of buffer) * Z_ARG1 - int crc
// * Z_ARG2 - byte* buf
// Result: * Z_ARG3 - int length (of buffer)
// Z_RET - int crc result *
// * Result:
// Compute CRC32 function. * Z_RET - int crc result
address generate_CRC32_updateBytes(const char* name) { **/
__ align(CodeEntryAlignment); // Compute CRC function (generic, for all polynomials).
StubCodeMark mark(this, "StubRoutines", name); void generate_CRC_updateBytes(const char* name, Register table, bool invertCRC) {
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
// arguments to kernel_crc32: // arguments to kernel_crc32:
Register crc = Z_ARG1; // Current checksum, preset by caller or result from previous call, int. Register crc = Z_ARG1; // Current checksum, preset by caller or result from previous call, int.
Register data = Z_ARG2; // source byte array Register data = Z_ARG2; // source byte array
Register dataLen = Z_ARG3; // #bytes to process, int Register dataLen = Z_ARG3; // #bytes to process, int
Register table = Z_ARG4; // crc table address // Register table = Z_ARG4; // crc table address. Preloaded and passed in by caller.
const Register t0 = Z_R10; // work reg for kernel* emitters const Register t0 = Z_R10; // work reg for kernel* emitters
const Register t1 = Z_R11; // work reg for kernel* emitters const Register t1 = Z_R11; // work reg for kernel* emitters
const Register t2 = Z_R12; // work reg for kernel* emitters const Register t2 = Z_R12; // work reg for kernel* emitters
@ -2361,16 +2340,50 @@ class StubGenerator: public StubCodeGenerator {
// Crc used as int. // Crc used as int.
__ z_llgfr(dataLen, dataLen); __ z_llgfr(dataLen, dataLen);
StubRoutines::zarch::generate_load_crc_table_addr(_masm, table);
__ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers.
__ z_stmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 to make them available as work registers. __ z_stmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 to make them available as work registers.
__ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, invertCRC);
__ z_lmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 back from stack. __ z_lmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 back from stack.
__ resize_frame(+(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ resize_frame(+(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers.
__ z_llgfr(Z_RET, crc); // Updated crc is function result. No copying required, just zero upper 32 bits. __ z_llgfr(Z_RET, crc); // Updated crc is function result. No copying required, just zero upper 32 bits.
__ z_br(Z_R14); // Result already in Z_RET == Z_ARG1. __ z_br(Z_R14); // Result already in Z_RET == Z_ARG1.
}
// Compute CRC32 function.
address generate_CRC32_updateBytes(const char* name) {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", name);
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
assert(UseCRC32Intrinsics, "should not generate this stub (%s) with CRC32 intrinsics disabled", name);
BLOCK_COMMENT("CRC32_updateBytes {");
Register table = Z_ARG4; // crc32 table address.
StubRoutines::zarch::generate_load_crc_table_addr(_masm, table);
generate_CRC_updateBytes(name, table, true);
BLOCK_COMMENT("} CRC32_updateBytes");
return __ addr_at(start_off);
}
// Compute CRC32C function.
address generate_CRC32C_updateBytes(const char* name) {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", name);
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
assert(UseCRC32CIntrinsics, "should not generate this stub (%s) with CRC32C intrinsics disabled", name);
BLOCK_COMMENT("CRC32C_updateBytes {");
Register table = Z_ARG4; // crc32c table address.
StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table);
generate_CRC_updateBytes(name, table, false);
BLOCK_COMMENT("} CRC32C_updateBytes");
return __ addr_at(start_off); return __ addr_at(start_off);
} }
@ -2441,9 +2454,13 @@ class StubGenerator: public StubCodeGenerator {
// Entry points that are platform specific. // Entry points that are platform specific.
if (UseCRC32Intrinsics) { if (UseCRC32Intrinsics) {
// We have no CRC32 table on z/Architecture. StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table;
StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table; StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes");
StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); }
if (UseCRC32CIntrinsics) {
StubRoutines::_crc32c_table_addr = (address)StubRoutines::zarch::_crc32c_table;
StubRoutines::_updateBytesCRC32C = generate_CRC32C_updateBytes("CRC32C_updateBytes");
} }
// Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction.
@ -2461,8 +2478,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
StubRoutines::zarch::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access();
// Support for verify_oop (must happen after universe_init). // Support for verify_oop (must happen after universe_init).
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine(); StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved. * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -68,12 +68,11 @@ class zarch {
}; };
private: private:
static address _handler_for_unsafe_access_entry;
static int _atomic_memory_operation_lock; static int _atomic_memory_operation_lock;
static address _partial_subtype_check; static address _partial_subtype_check;
static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE];
static juint _crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE];
// Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction.
static address _trot_table_addr; static address _trot_table_addr;
@ -91,11 +90,11 @@ class zarch {
static int atomic_memory_operation_lock() { return _atomic_memory_operation_lock; } static int atomic_memory_operation_lock() { return _atomic_memory_operation_lock; }
static void set_atomic_memory_operation_lock(int value) { _atomic_memory_operation_lock = value; } static void set_atomic_memory_operation_lock(int value) { _atomic_memory_operation_lock = value; }
static address handler_for_unsafe_access_entry() { return _handler_for_unsafe_access_entry; }
static address partial_subtype_check() { return _partial_subtype_check; } static address partial_subtype_check() { return _partial_subtype_check; }
static void generate_load_absolute_address(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents);
static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); static void generate_load_crc_table_addr(MacroAssembler* masm, Register table);
static void generate_load_crc32c_table_addr(MacroAssembler* masm, Register table);
// Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction.
static void generate_load_trot_table_addr(MacroAssembler* masm, Register table); static void generate_load_trot_table_addr(MacroAssembler* masm, Register table);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 SAP SE. All rights reserved. * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -642,13 +642,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch
return entry; return entry;
} }
// Unused, should never pass by.
address TemplateInterpreterGenerator::generate_continuation_for (TosState state) {
address entry = __ pc();
__ should_not_reach_here();
return entry;
}
address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, int step, size_t index_size) { address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, int step, size_t index_size) {
address entry = __ pc(); address entry = __ pc();
@ -683,6 +676,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for (TosState state,
__ z_llgc(size, Address(cache, offset, flags_offset+(sizeof(size_t)-1))); __ z_llgc(size, Address(cache, offset, flags_offset+(sizeof(size_t)-1)));
__ z_sllg(size, size, Interpreter::logStackElementSize); // Each argument size in bytes. __ z_sllg(size, size, Interpreter::logStackElementSize); // Each argument size in bytes.
__ z_agr(Z_esp, size); // Pop arguments. __ z_agr(Z_esp, size); // Pop arguments.
__ check_and_handle_popframe(Z_thread);
__ check_and_handle_earlyret(Z_thread);
__ dispatch_next(state, step); __ dispatch_next(state, step);
BLOCK_COMMENT("} return_entry"); BLOCK_COMMENT("} return_entry");
@ -1964,7 +1961,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
__ z_llgf(crc, 2 * wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. __ z_llgf(crc, 2 * wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register.
StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); StubRoutines::zarch::generate_load_crc_table_addr(_masm, table);
__ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1); __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1, true);
// Restore caller sp for c2i case. // Restore caller sp for c2i case.
__ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
@ -2020,10 +2017,10 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
// data = buf + off // data = buf + off
BLOCK_COMMENT("CRC32_updateByteBuffer {"); BLOCK_COMMENT("CRC32_updateByteBuffer {");
__ z_llgf(crc, 5*wordSize, argP); // current crc state __ z_llgf(crc, 5*wordSize, argP); // current crc state
__ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_lg(data, 3*wordSize, argP); // start of byte buffer
__ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset.
__ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process
} else { // Used for "updateBytes update". } else { // Used for "updateBytes update".
// crc @ (SP + 4W) (32bit) // crc @ (SP + 4W) (32bit)
// buf @ (SP + 3W) (64bit ptr to byte array) // buf @ (SP + 3W) (64bit ptr to byte array)
// off @ (SP + 2W) (32bit) // off @ (SP + 2W) (32bit)
@ -2031,7 +2028,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
// data = buf + off + base_offset // data = buf + off + base_offset
BLOCK_COMMENT("CRC32_updateBytes {"); BLOCK_COMMENT("CRC32_updateBytes {");
__ z_llgf(crc, 4*wordSize, argP); // current crc state __ z_llgf(crc, 4*wordSize, argP); // current crc state
__ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_lg(data, 3*wordSize, argP); // start of byte buffer
__ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset.
__ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process
__ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE));
@ -2041,7 +2038,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
__ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers.
__ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers.
__ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, true);
__ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack.
// Restore caller sp for c2i case. // Restore caller sp for c2i case.
@ -2060,8 +2057,73 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI
return NULL; return NULL;
} }
// Not supported
// Method entry for static native methods:
// int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int len)
// int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long buf, int off, int len)
address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
if (UseCRC32CIntrinsics) {
uint64_t entry_off = __ offset();
// We don't generate local frame and don't align stack because
// we call stub code and there is no safepoint on this path.
// Load parameters.
// Z_esp is callers operand stack pointer, i.e. it points to the parameters.
const Register argP = Z_esp;
const Register crc = Z_ARG1; // crc value
const Register data = Z_ARG2; // address of java byte array
const Register dataLen = Z_ARG3; // source data len
const Register table = Z_ARG4; // address of crc32 table
const Register t0 = Z_R10; // work reg for kernel* emitters
const Register t1 = Z_R11; // work reg for kernel* emitters
const Register t2 = Z_R12; // work reg for kernel* emitters
const Register t3 = Z_R13; // work reg for kernel* emitters
// Arguments are reversed on java expression stack.
// Calculate address of start element.
if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateByteBuffer direct".
// crc @ (SP + 5W) (32bit)
// buf @ (SP + 3W) (64bit ptr to long array)
// off @ (SP + 2W) (32bit)
// dataLen @ (SP + 1W) (32bit)
// data = buf + off
BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {");
__ z_llgf(crc, 5*wordSize, argP); // current crc state
__ z_lg(data, 3*wordSize, argP); // start of byte buffer
__ z_agf(data, 2*wordSize, argP); // Add byte buffer offset.
__ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process
} else { // Used for "updateBytes update".
// crc @ (SP + 4W) (32bit)
// buf @ (SP + 3W) (64bit ptr to byte array)
// off @ (SP + 2W) (32bit)
// dataLen @ (SP + 1W) (32bit)
// data = buf + off + base_offset
BLOCK_COMMENT("CRC32C_updateBytes {");
__ z_llgf(crc, 4*wordSize, argP); // current crc state
__ z_lg(data, 3*wordSize, argP); // start of byte buffer
__ z_agf(data, 2*wordSize, argP); // Add byte buffer offset.
__ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process
__ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE));
}
StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table);
__ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers.
__ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers.
__ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, false);
__ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack.
// Restore caller sp for c2i case.
__ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
__ z_br(Z_R14);
BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}");
return __ addr_at(entry_off);
}
return NULL; return NULL;
} }

View File

@ -3466,7 +3466,7 @@ void TemplateTable::invokevirtual_helper(Register index,
__ z_sllg(index, index, exact_log2(vtableEntry::size_in_bytes())); __ z_sllg(index, index, exact_log2(vtableEntry::size_in_bytes()));
__ mem2reg_opt(method, __ mem2reg_opt(method,
Address(Z_tmp_2, index, Address(Z_tmp_2, index,
InstanceKlass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes()))); Klass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes())));
__ profile_arguments_type(Z_ARG4, method, Z_ARG5, true); __ profile_arguments_type(Z_ARG4, method, Z_ARG5, true);
__ jump_from_interpreted(method, Z_ARG4); __ jump_from_interpreted(method, Z_ARG4);
BLOCK_COMMENT("} invokevirtual_helper"); BLOCK_COMMENT("} invokevirtual_helper");

View File

@ -111,13 +111,23 @@ void VM_Version::initialize() {
ContendedPaddingWidth = cache_line_size; ContendedPaddingWidth = cache_line_size;
} }
// On z/Architecture, the CRC32 intrinsics had to be implemented "by hand". // On z/Architecture, the CRC32/CRC32C intrinsics are implemented "by hand".
// They cannot be based on the CHECKSUM instruction which has been there // TODO: Provide implementation based on the vector instructions available from z13.
// since the very beginning (of z/Architecture). It computes "some kind of" a checksum // Note: The CHECKSUM instruction, which has been there since the very beginning
// which has nothing to do with the CRC32 algorithm. // (of z/Architecture), computes "some kind of" a checksum.
// It has nothing to do with the CRC32 algorithm.
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); FLAG_SET_DEFAULT(UseCRC32Intrinsics, true);
} }
if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true);
}
// TODO: Provide implementation.
if (UseAdler32Intrinsics) {
warning("Adler32Intrinsics not available on this CPU.");
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
}
// On z/Architecture, we take UseAES as the general switch to enable/disable the AES intrinsics. // On z/Architecture, we take UseAES as the general switch to enable/disable the AES intrinsics.
// The specific, and yet to be defined, switches UseAESxxxIntrinsics will then be set // The specific, and yet to be defined, switches UseAESxxxIntrinsics will then be set
@ -195,11 +205,6 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
} }
if (UseAdler32Intrinsics) {
warning("Adler32Intrinsics not available on this CPU.");
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
}
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true);
} }

View File

@ -83,7 +83,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
__ load_klass(rcvr_klass, Z_ARG1); __ load_klass(rcvr_klass, Z_ARG1);
// Set method (in case of interpreted method), and destination address. // Set method (in case of interpreted method), and destination address.
int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + int entry_offset = in_bytes(Klass::vtable_start_offset()) +
vtable_index * vtableEntry::size_in_bytes(); vtable_index * vtableEntry::size_in_bytes();
#ifndef PRODUCT #ifndef PRODUCT
@ -96,8 +96,8 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
// worst case actual size // worst case actual size
padding_bytes += __ load_const_size() - __ load_const_optimized_rtn_len(vtable_idx, vtable_index*vtableEntry::size_in_bytes(), true); padding_bytes += __ load_const_size() - __ load_const_optimized_rtn_len(vtable_idx, vtable_index*vtableEntry::size_in_bytes(), true);
assert(Immediate::is_uimm12(in_bytes(InstanceKlass::vtable_length_offset())), "disp to large"); assert(Immediate::is_uimm12(in_bytes(Klass::vtable_length_offset())), "disp to large");
__ z_cl(vtable_idx, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); __ z_cl(vtable_idx, in_bytes(Klass::vtable_length_offset()), rcvr_klass);
__ z_brl(L); __ z_brl(L);
__ z_lghi(Z_ARG3, vtable_index); // Debug code, don't optimize. __ z_lghi(Z_ARG3, vtable_index); // Debug code, don't optimize.
__ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), Z_ARG1, Z_ARG3, false); __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), Z_ARG1, Z_ARG3, false);
@ -187,11 +187,11 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
__ load_klass(rcvr_klass, Z_ARG1); __ load_klass(rcvr_klass, Z_ARG1);
// Load start of itable entries into itable_entry. // Load start of itable entries into itable_entry.
__ z_llgf(vtable_len, Address(rcvr_klass, InstanceKlass::vtable_length_offset())); __ z_llgf(vtable_len, Address(rcvr_klass, Klass::vtable_length_offset()));
__ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); __ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes()));
// Loop over all itable entries until desired interfaceOop(Rinterface) found. // Loop over all itable entries until desired interfaceOop(Rinterface) found.
const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); const int vtable_base_offset = in_bytes(Klass::vtable_start_offset());
// Count unused bytes. // Count unused bytes.
start_pc = __ pc(); start_pc = __ pc();
__ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len); __ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -70,9 +70,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
bool check_exception=true bool check_exception=true
); );
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
// base routine for all dispatches // base routine for all dispatches
void dispatch_base(TosState state, address* table); void dispatch_base(TosState state, address* table);
@ -80,6 +77,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
InterpreterMacroAssembler(CodeBuffer* c) InterpreterMacroAssembler(CodeBuffer* c)
: MacroAssembler(c) {} : MacroAssembler(c) {}
virtual void check_and_handle_popframe(Register scratch_reg);
virtual void check_and_handle_earlyret(Register scratch_reg);
void jump_to_entry(address entry); void jump_to_entry(address entry);
virtual void load_earlyret_value(TosState state); virtual void load_earlyret_value(TosState state);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -44,7 +44,7 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand
void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
address pc = _instructions->start() + pc_offset; address pc = _instructions->start() + pc_offset;
Handle obj = HotSpotObjectConstantImpl::object(constant); Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
jobject value = JNIHandles::make_local(obj()); jobject value = JNIHandles::make_local(obj());
if (HotSpotObjectConstantImpl::compressed(constant)) { if (HotSpotObjectConstantImpl::compressed(constant)) {
#ifdef _LP64 #ifdef _LP64

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -604,15 +604,15 @@ class MacroAssembler : public Assembler {
bool check_exception=true // flag which indicates if exception should be checked bool check_exception=true // flag which indicates if exception should be checked
); );
public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {}
// This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code. // This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code.
// The implementation is only non-empty for the InterpreterMacroAssembler, // The implementation is only non-empty for the InterpreterMacroAssembler,
// as only the interpreter handles and ForceEarlyReturn PopFrame requests. // as only the interpreter handles and ForceEarlyReturn PopFrame requests.
virtual void check_and_handle_popframe(Register scratch_reg); virtual void check_and_handle_popframe(Register scratch_reg);
virtual void check_and_handle_earlyret(Register scratch_reg); virtual void check_and_handle_earlyret(Register scratch_reg);
public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {}
// Support for NULL-checks // Support for NULL-checks
// //
// Generates code that causes a NULL OS exception if the content of reg is NULL. // Generates code that causes a NULL OS exception if the content of reg is NULL.

View File

@ -1,120 +0,0 @@
/*
* Copyright (c) 2004, 2012, 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.
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "asm/codeBuffer.hpp"
#include "memory/metaspaceShared.hpp"
// Generate the self-patching vtable method:
//
// This method will be called (as any other Klass virtual method) with
// the Klass itself as the first argument. Example:
//
// oop obj;
// int size = obj->klass()->oop_size(this);
//
// for which the virtual method call is Klass::oop_size();
//
// The dummy method is called with the Klass object as the first
// operand, and an object as the second argument.
//
//=====================================================================
// All of the dummy methods in the vtable are essentially identical,
// differing only by an ordinal constant, and they bear no relationship
// to the original method which the caller intended. Also, there needs
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#define __ masm->
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
// Get ready to generate dummy methods.
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
Label common_code;
for (int i = 0; i < vtbl_list_size; ++i) {
for (int j = 0; j < num_virtuals; ++j) {
dummy_vtable[num_virtuals * i + j] = (void*)masm->pc();
__ save(SP, -256, SP);
int offset = (i << 8) + j;
Register src = G0;
if (!Assembler::is_simm13(offset)) {
__ sethi(offset, L0);
src = L0;
offset = offset & ((1 << 10) - 1);
}
__ brx(Assembler::always, false, Assembler::pt, common_code);
// Load L0 with a value indicating vtable/offset pair.
// -- bits[ 7..0] (8 bits) which virtual method in table?
// -- bits[13..8] (6 bits) which virtual method table?
__ delayed()->or3(src, offset, L0);
}
}
__ bind(common_code);
// Expecting to be called with the "this" pointer in O0/I0 (where
// "this" is a Klass object). In addition, L0 was set (above) to
// identify the method and table.
// Look up the correct vtable pointer.
__ set((intptr_t)vtbl_list, L2); // L2 = address of new vtable list.
__ srl(L0, 8, L3); // Isolate L3 = vtable identifier.
__ sll(L3, LogBytesPerWord, L3);
__ ld_ptr(L2, L3, L3); // L3 = new (correct) vtable pointer.
__ st_ptr(L3, Address(I0, 0)); // Save correct vtable ptr in entry.
// Restore registers and jump to the correct method;
__ and3(L0, 255, L4); // Isolate L3 = method offset;.
__ sll(L4, LogBytesPerWord, L4);
__ ld_ptr(L3, L4, L4); // Get address of correct virtual method
__ jmpl(L4, 0, G0); // Jump to correct method.
__ delayed()->restore(); // Restore registers.
__ flush();
*mc_top = (char*)__ pc();
guarantee(*mc_top <= mc_end, "Insufficient space for method wrappers.");
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -71,7 +71,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
Register temp_reg, Register temp2_reg, Register temp_reg, Register temp2_reg,
const char* error_message) { const char* error_message) {
InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Klass* klass = SystemDictionary::well_known_klass(klass_id);
bool did_save = false; bool did_save = false;
if (temp_reg == noreg || temp2_reg == noreg) { if (temp_reg == noreg || temp2_reg == noreg) {
temp_reg = L1; temp_reg = L1;

View File

@ -374,6 +374,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
__ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, parameter_size); // argument size in words __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, parameter_size); // argument size in words
__ sll(parameter_size, Interpreter::logStackElementSize, parameter_size); // each argument size in bytes __ sll(parameter_size, Interpreter::logStackElementSize, parameter_size); // each argument size in bytes
__ add(Lesp, parameter_size, Lesp); // pop arguments __ add(Lesp, parameter_size, Lesp); // pop arguments
__ check_and_handle_popframe(Gtemp);
__ check_and_handle_earlyret(Gtemp);
__ dispatch_next(state, step); __ dispatch_next(state, step);
return entry; return entry;
@ -466,12 +470,6 @@ address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state,
} }
address TemplateInterpreterGenerator::generate_continuation_for(TosState state) {
address entry = __ pc();
__ dispatch_next(state);
return entry;
}
// //
// Helpers for commoning out cases in the various type of method entries. // Helpers for commoning out cases in the various type of method entries.
// //

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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,6 +21,8 @@
* questions. * questions.
*/ */
#include "precompiled.hpp"
#include "aot/compiledIC_aot.hpp" #include "aot/compiledIC_aot.hpp"
#include "code/codeCache.hpp" #include "code/codeCache.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
int number_of_arguments, int number_of_arguments,
bool check_exceptions); bool check_exceptions);
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
// base routine for all dispatches // base routine for all dispatches
void dispatch_base(TosState state, address* table, bool verifyoop = true); void dispatch_base(TosState state, address* table, bool verifyoop = true);
@ -61,6 +58,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
void jump_to_entry(address entry); void jump_to_entry(address entry);
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
void load_earlyret_value(TosState state); void load_earlyret_value(TosState state);
// Interpreter-specific registers // Interpreter-specific registers

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -65,7 +65,7 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand
void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
address pc = _instructions->start() + pc_offset; address pc = _instructions->start() + pc_offset;
Handle obj = HotSpotObjectConstantImpl::object(constant); Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
jobject value = JNIHandles::make_local(obj()); jobject value = JNIHandles::make_local(obj());
if (HotSpotObjectConstantImpl::compressed(constant)) { if (HotSpotObjectConstantImpl::compressed(constant)) {
#ifdef _LP64 #ifdef _LP64

View File

@ -71,12 +71,6 @@ class MacroAssembler: public Assembler {
bool check_exceptions // whether to check for pending exceptions after return bool check_exceptions // whether to check for pending exceptions after return
); );
// These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
// The implementation is only non-empty for the InterpreterMacroAssembler,
// as only the interpreter handles PopFrame and ForceEarlyReturn requests.
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true);
// helpers for FPU flag access // helpers for FPU flag access
@ -87,6 +81,12 @@ class MacroAssembler: public Assembler {
public: public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {} MacroAssembler(CodeBuffer* code) : Assembler(code) {}
// These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
// The implementation is only non-empty for the InterpreterMacroAssembler,
// as only the interpreter handles PopFrame and ForceEarlyReturn requests.
virtual void check_and_handle_popframe(Register java_thread);
virtual void check_and_handle_earlyret(Register java_thread);
// Support for NULL-checks // Support for NULL-checks
// //
// Generates code that causes a NULL OS exception if the content of reg is NULL. // Generates code that causes a NULL OS exception if the content of reg is NULL.

View File

@ -1,124 +0,0 @@
/*
* Copyright (c) 2004, 2012, 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.
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/codeBuffer.hpp"
#include "memory/metaspaceShared.hpp"
// Generate the self-patching vtable method:
//
// This method will be called (as any other Klass virtual method) with
// the Klass itself as the first argument. Example:
//
// oop obj;
// int size = obj->klass()->oop_size(this);
//
// for which the virtual method call is Klass::oop_size();
//
// The dummy method is called with the Klass object as the first
// operand, and an object as the second argument.
//
//=====================================================================
// All of the dummy methods in the vtable are essentially identical,
// differing only by an ordinal constant, and they bear no relationship
// to the original method which the caller intended. Also, there needs
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#define __ masm->
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
// Get ready to generate dummy methods.
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
Label common_code;
for (int i = 0; i < vtbl_list_size; ++i) {
for (int j = 0; j < num_virtuals; ++j) {
dummy_vtable[num_virtuals * i + j] = (void*)masm->pc();
// Load rax, with a value indicating vtable/offset pair.
// -- bits[ 7..0] (8 bits) which virtual method in table?
// -- bits[12..8] (5 bits) which virtual method table?
// -- must fit in 13-bit instruction immediate field.
__ movl(rax, (i << 8) + j);
__ jmp(common_code);
}
}
__ bind(common_code);
#ifdef WIN32
// Expecting to be called with "thiscall" conventions -- the arguments
// are on the stack, except that the "this" pointer is in rcx.
#else
// Expecting to be called with Unix conventions -- the arguments
// are on the stack, including the "this" pointer.
#endif
// In addition, rax was set (above) to the offset of the method in the
// table.
#ifdef WIN32
__ push(rcx); // save "this"
#endif
__ mov(rcx, rax);
__ shrptr(rcx, 8); // isolate vtable identifier.
__ shlptr(rcx, LogBytesPerWord);
Address index(noreg, rcx, Address::times_1);
ExternalAddress vtbl((address)vtbl_list);
__ movptr(rdx, ArrayAddress(vtbl, index)); // get correct vtable address.
#ifdef WIN32
__ pop(rcx); // restore "this"
#else
__ movptr(rcx, Address(rsp, BytesPerWord)); // fetch "this"
#endif
__ movptr(Address(rcx, 0), rdx); // update vtable pointer.
__ andptr(rax, 0x00ff); // isolate vtable method index
__ shlptr(rax, LogBytesPerWord);
__ addptr(rax, rdx); // address of real method pointer.
__ jmp(Address(rax, 0)); // get real method pointer.
__ flush();
*mc_top = (char*)__ pc();
}

View File

@ -1,114 +0,0 @@
/*
* Copyright (c) 2004, 2012, 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.
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/codeBuffer.hpp"
#include "memory/metaspaceShared.hpp"
// Generate the self-patching vtable method:
//
// This method will be called (as any other Klass virtual method) with
// the Klass itself as the first argument. Example:
//
// oop obj;
// int size = obj->klass()->oop_size(this);
//
// for which the virtual method call is Klass::oop_size();
//
// The dummy method is called with the Klass object as the first
// operand, and an object as the second argument.
//
//=====================================================================
// All of the dummy methods in the vtable are essentially identical,
// differing only by an ordinal constant, and they bear no relationship
// to the original method which the caller intended. Also, there needs
// to be 'vtbl_list_size' instances of the vtable in order to
// differentiate between the 'vtable_list_size' original Klass objects.
#define __ masm->
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*);
*(intptr_t *)(*md_top) = vtable_bytes;
*md_top += sizeof(intptr_t);
void** dummy_vtable = (void**)*md_top;
*vtable = dummy_vtable;
*md_top += vtable_bytes;
// Get ready to generate dummy methods.
CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top);
MacroAssembler* masm = new MacroAssembler(&cb);
Label common_code;
for (int i = 0; i < vtbl_list_size; ++i) {
for (int j = 0; j < num_virtuals; ++j) {
dummy_vtable[num_virtuals * i + j] = (void*)masm->pc();
// Load eax with a value indicating vtable/offset pair.
// -- bits[ 7..0] (8 bits) which virtual method in table?
// -- bits[12..8] (5 bits) which virtual method table?
// -- must fit in 13-bit instruction immediate field.
__ movl(rax, (i << 8) + j);
__ jmp(common_code);
}
}
__ bind(common_code);
// Expecting to be called with "thiscall" convections -- the arguments
// are on the stack and the "this" pointer is in c_rarg0. In addition, rax
// was set (above) to the offset of the method in the table.
__ push(c_rarg1); // save & free register
__ push(c_rarg0); // save "this"
__ mov(c_rarg0, rax);
__ shrptr(c_rarg0, 8); // isolate vtable identifier.
__ shlptr(c_rarg0, LogBytesPerWord);
__ lea(c_rarg1, ExternalAddress((address)vtbl_list)); // ptr to correct vtable list.
__ addptr(c_rarg1, c_rarg0); // ptr to list entry.
__ movptr(c_rarg1, Address(c_rarg1, 0)); // get correct vtable address.
__ pop(c_rarg0); // restore "this"
__ movptr(Address(c_rarg0, 0), c_rarg1); // update vtable pointer.
__ andptr(rax, 0x00ff); // isolate vtable method index
__ shlptr(rax, LogBytesPerWord);
__ addptr(rax, c_rarg1); // address of real method pointer.
__ pop(c_rarg1); // restore register.
__ movptr(rax, Address(rax, 0)); // get real method pointer.
__ jmp(rax); // jump to the real method.
__ flush();
*mc_top = (char*)__ pc();
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -65,7 +65,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
Register obj, SystemDictionary::WKID klass_id, Register obj, SystemDictionary::WKID klass_id,
const char* error_message) { const char* error_message) {
InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
KlassHandle klass = SystemDictionary::well_known_klass(klass_id); Klass* klass = SystemDictionary::well_known_klass(klass_id);
Register temp = rdi; Register temp = rdi;
Register temp2 = noreg; Register temp2 = noreg;
LP64_ONLY(temp2 = rscratch1); // used by MacroAssembler::cmpptr LP64_ONLY(temp2 = rscratch1); // used by MacroAssembler::cmpptr

View File

@ -171,16 +171,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(
return entry; return entry;
} }
address TemplateInterpreterGenerator::generate_continuation_for(TosState state) {
address entry = __ pc();
// NULL last_sp until next java call
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
__ dispatch_next(state);
return entry;
}
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) {
address entry = __ pc(); address entry = __ pc();
@ -230,6 +220,17 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
__ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); __ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
__ andl(flags, ConstantPoolCacheEntry::parameter_size_mask); __ andl(flags, ConstantPoolCacheEntry::parameter_size_mask);
__ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale())); __ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale()));
const Register java_thread = NOT_LP64(rcx) LP64_ONLY(r15_thread);
if (JvmtiExport::can_pop_frame()) {
NOT_LP64(__ get_thread(java_thread));
__ check_and_handle_popframe(java_thread);
}
if (JvmtiExport::can_force_early_return()) {
NOT_LP64(__ get_thread(java_thread));
__ check_and_handle_earlyret(java_thread);
}
__ dispatch_next(state, step); __ dispatch_next(state, step);
return entry; return entry;

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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,16 +36,19 @@ import java.util.Map;
import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind; import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.elf.JELFRelocObject; import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
import jdk.tools.jaotc.binformat.macho.JMachORelocObject;
import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.options.OptionValues;
/** /**
* A format-agnostic container class that holds various components of a binary. * A format-agnostic container class that holds various components of a binary.
* *
* <p> * <p>
* This class holds information necessary to create platform-specific binary containers such as * This class holds information necessary to create platform-specific binary containers such as
* ELFContainer for Linux and Solaris operating systems or yet-to be created MachOContainer for Mac * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac OS or PEContainer
* OS or PEContainer for MS Windows operating systems. * for MS Windows operating systems.
* *
* <p> * <p>
* Method APIs provided by this class are used to construct and populate platform-independent * Method APIs provided by this class are used to construct and populate platform-independent
@ -56,6 +59,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
* Methods to record and access code section contents, symbols and relocations are provided. * Methods to record and access code section contents, symbols and relocations are provided.
*/ */
public class BinaryContainer implements SymbolTable { public class BinaryContainer implements SymbolTable {
private final OptionValues graalOptions;
private final int codeSegmentSize; private final int codeSegmentSize;
@ -257,36 +261,40 @@ public class BinaryContainer implements SymbolTable {
* Allocates a {@code BinaryContainer} object whose content will be generated in a file with the * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the
* prefix {@code prefix}. It also initializes internal code container, symbol table and * prefix {@code prefix}. It also initializes internal code container, symbol table and
* relocation tables. * relocation tables.
*
* @param graalOptions
*/ */
public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) { public BinaryContainer(OptionValues graalOptions, GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) {
this.graalOptions = graalOptions;
this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize; this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment; this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
// read only, code // read only, code
codeContainer = new CodeContainer(".text", this); codeContainer = new CodeContainer(".text", this);
extLinkageContainer = new CodeContainer(".hotspot.linkage.plt", this); extLinkageContainer = new CodeContainer(".hs.plt.linkage", this);
// read only, info // read only, info
configContainer = new ReadOnlyDataContainer(".config", this); configContainer = new ReadOnlyDataContainer(".config", this);
metaspaceNamesContainer = new ReadOnlyDataContainer(".metaspace.names", this); metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this);
methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this); methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this);
klassesOffsetsContainer = new ReadOnlyDataContainer(".klasses.offsets", this); klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this);
klassesDependenciesContainer = new ReadOnlyDataContainer(".klasses.dependencies", this); klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this);
headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this)); headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this); stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this);
codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this); codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this);
constantDataContainer = new ReadOnlyDataContainer(".method.constdata", this); constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this);
// needs relocation patching at load time by the loader // needs relocation patching at load time by the loader
methodMetadataContainer = new ReadOnlyDataContainer(".method.metadata", this); methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this);
// writable sections // writable sections
metaspaceGotContainer = new ByteContainer(".metaspace.got", this); metaspaceGotContainer = new ByteContainer(".meta.got", this);
metadataGotContainer = new ByteContainer(".metadata.got", this); metadataGotContainer = new ByteContainer(".metadata.got", this);
methodStateContainer = new ByteContainer(".method.state", this); methodStateContainer = new ByteContainer(".meth.state", this);
oopGotContainer = new ByteContainer(".oop.got", this); oopGotContainer = new ByteContainer(".oop.got", this);
extLinkageGOTContainer = new ByteContainer(".hotspot.linkage.got", this); extLinkageGOTContainer = new ByteContainer(".hs.got.linkage", this);
addGlobalSymbols(); addGlobalSymbols();
@ -303,17 +311,17 @@ public class BinaryContainer implements SymbolTable {
graalHotSpotVMConfig.useCMSGC, graalHotSpotVMConfig.useCMSGC,
graalHotSpotVMConfig.useTLAB, graalHotSpotVMConfig.useTLAB,
graalHotSpotVMConfig.useBiasedLocking, graalHotSpotVMConfig.useBiasedLocking,
TieredAOT.getValue(), TieredAOT.getValue(graalOptions),
graalHotSpotVMConfig.enableContended, graalHotSpotVMConfig.enableContended,
graalHotSpotVMConfig.restrictContended, graalHotSpotVMConfig.restrictContended,
graphBuilderConfig.omitAssertions() graphBuilderConfig.omitAssertions()
}; };
int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().shift, int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().getShift(),
graalHotSpotVMConfig.getKlassEncoding().shift, graalHotSpotVMConfig.getKlassEncoding().getShift(),
graalHotSpotVMConfig.contendedPaddingWidth, graalHotSpotVMConfig.contendedPaddingWidth,
graalHotSpotVMConfig.fieldsAllocationStyle, graalHotSpotVMConfig.fieldsAllocationStyle,
1 << graalHotSpotVMConfig.getOopEncoding().alignment, 1 << graalHotSpotVMConfig.logMinObjAlignment(),
graalHotSpotVMConfig.codeSegmentSize, graalHotSpotVMConfig.codeSegmentSize,
}; };
// @formatter:on // @formatter:on
@ -497,11 +505,20 @@ public class BinaryContainer implements SymbolTable {
switch (osName) { switch (osName) {
case "Linux": case "Linux":
case "SunOS": case "SunOS":
JELFRelocObject elfso = new JELFRelocObject(this, outputFileName, aotVersion); JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName, aotVersion);
elfso.createELFRelocObject(relocationTable, symbolTable.values()); elfobj.createELFRelocObject(relocationTable, symbolTable.values());
break;
case "Mac OS X":
JMachORelocObject machobj = new JMachORelocObject(this, outputFileName);
machobj.createMachORelocObject(relocationTable, symbolTable.values());
break; break;
default: default:
throw new InternalError("Unsupported platform: " + osName); if (osName.startsWith("Windows")) {
JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion);
pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values());
break;
} else
throw new InternalError("Unsupported platform: " + osName);
} }
} }
@ -742,11 +759,11 @@ public class BinaryContainer implements SymbolTable {
} }
/** /**
* Add constant data as follows. - Adding the data to the method.constdata section * Add constant data as follows. - Adding the data to the meth.constdata section
* *
* @param data * @param data
* @param alignment * @param alignment
* @return the offset in the method.constdata of the data * @return the offset in the meth.constdata of the data
*/ */
public int addConstantData(byte[] data, int alignment) { public int addConstantData(byte[] data, int alignment) {
// Get the current length of the metaspaceNameContainer // Get the current length of the metaspaceNameContainer

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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat;
import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind; import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.jnilibelf.ELFContainer; import jdk.tools.jaotc.binformat.Container;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -41,7 +41,7 @@ import java.util.Arrays;
* The method {@code putIntAt} updates the content of {@code contentBytes}. Changes are not * The method {@code putIntAt} updates the content of {@code contentBytes}. Changes are not
* reflected in {@code contentStream}. * reflected in {@code contentStream}.
*/ */
public class ByteContainer implements ELFContainer { public class ByteContainer implements Container {
/** /**
* {@code ByteBuffer} representation of {@code BinaryContainer}. * {@code ByteBuffer} representation of {@code 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,9 +21,9 @@
* questions. * questions.
*/ */
package jdk.tools.jaotc.jnilibelf; package jdk.tools.jaotc.binformat;
public interface ELFContainer { public interface Container {
String getContainerName(); 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -21,27 +21,31 @@
* questions. * questions.
*/ */
package jdk.tools.jaotc.jnilibelf.sunos; package jdk.tools.jaotc.binformat;
/** /**
* Represent Elf_Cmd enums defined in libelf.h on SunOS as they slightly different from libelf.h on * This class represents ia native OS specific Symbol
* Linux.
*/ */
public enum Elf_Cmd { public abstract class NativeSymbol {
/** Must be first, 0. */
ELF_C_NULL,
ELF_C_READ, /** String table index. */
ELF_C_WRITE, private int index;
ELF_C_CLR,
ELF_C_SET,
ELF_C_FDDONE,
ELF_C_FDREAD,
ELF_C_RDWR,
ELF_C_WRIMAGE,
ELF_C_IMAGE,
/** Must be last. */ public NativeSymbol(int index) {
ELF_C_NUM this.index = index;
}
/**
* @return the index
*/
public int getIndex() {
return index;
}
/**
* @index
*/
public void setIndex(int index) {
this.index = index;
}
} }

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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat;
import java.util.Objects; import java.util.Objects;
import jdk.tools.jaotc.jnilibelf.ELFSymbol; import jdk.tools.jaotc.binformat.NativeSymbol;
public class Symbol { public class Symbol {
@ -51,7 +51,7 @@ public class Symbol {
private final Kind kind; private final Kind kind;
private ByteContainer section; private ByteContainer section;
private ELFSymbol elfSymbol; private NativeSymbol nativeSymbol;
/** /**
* Create symbol info. * Create symbol info.
@ -77,12 +77,12 @@ public class Symbol {
return name; return name;
} }
public ELFSymbol getElfSymbol() { public NativeSymbol getNativeSymbol() {
return elfSymbol; return nativeSymbol;
} }
public void setElfSymbol(ELFSymbol elfSymbol) { public void setNativeSymbol(NativeSymbol nativeSym) {
this.elfSymbol = elfSymbol; this.nativeSymbol = nativeSym;
} }
public Binding getBinding() { public Binding getBinding() {

View File

@ -0,0 +1,256 @@
/*
* 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
* 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.binformat.elf;
/**
*
* Support for the creation of Elf Object files.
* Current support is limited to 64 bit x86_64.
*
*/
public class Elf {
/**
* Elf64_Ehdr structure defines
*/
public enum Elf64_Ehdr {
e_ident( 0,16),
e_type(16, 2),
e_machine(18, 2),
e_version(20, 4),
e_entry(24, 8),
e_phoff(32, 8),
e_shoff(40, 8),
e_flags(48, 4),
e_ehsize(52, 2),
e_phentsize(54, 2),
e_phnum(56, 2),
e_shentsize(58, 2),
e_shnum(60, 2),
e_shstrndx(62, 2);
public final int off;
public final int sz;
Elf64_Ehdr(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 64;
/**
* Elf64_Ehdr defines
*/
/**
* 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;
public static final int EI_CLASS = 4;
public static final byte ELFCLASS64 = 0x2;
public static final int EI_DATA = 5;
public static final byte ELFDATA2LSB = 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;
/**
* e_type
*/
public 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;
}
/**
* Elf64_Shdr structure defines
*/
public enum Elf64_Shdr {
sh_name( 0, 4),
sh_type( 4, 4),
sh_flags( 8, 8),
sh_addr(16, 8),
sh_offset(24, 8),
sh_size(32, 8),
sh_link(40, 4),
sh_info(44, 4),
sh_addralign(48, 8),
sh_entsize(56, 8);
public final int off;
public final int sz;
Elf64_Shdr(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 64;
/**
* Elf64_Shdr defines
*/
/**
* 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;
public 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;
}
/**
* Symbol table entry definitions
*
* Elf64_Sym structure defines
*/
public enum Elf64_Sym {
st_name( 0, 4),
st_info( 4, 1),
st_other( 5, 1),
st_shndx( 6, 2),
st_value( 8, 8),
st_size(16, 8);
public final int off;
public final int sz;
Elf64_Sym(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
public static final byte STT_NOTYPE = 0x0;
public static final byte STT_OBJECT = 0x1;
public static final byte STT_FUNC = 0x2;
public static byte ELF64_ST_INFO(byte bind, byte type) {
return (byte)(((bind) << 4) + ((type) & 0xf));
}
}
/**
* Elf64_Rel structure defines
*/
public enum Elf64_Rel {
r_offset( 0, 8),
r_info( 8, 8);
public final int off;
public final int sz;
Elf64_Rel(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
}
/**
* Elf64_Rela structure defines
*/
public enum Elf64_Rela {
r_offset( 0, 8),
r_info( 8, 8),
r_addend(16, 8);
public final int off;
public final int sz;
Elf64_Rela(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
public static long ELF64_R_INFO(int symidx, int type) {
return (((long)symidx << 32) + ((long)type));
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -20,20 +20,24 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package org.graalvm.compiler.salver.serialize;
import java.io.Flushable; package jdk.tools.jaotc.binformat.elf;
import java.io.IOException;
import org.graalvm.compiler.salver.writer.DumpWriter;
public interface Serializer extends Flushable { import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
DumpWriter getWriter(); public class ElfByteBuffer {
void setWriter(DumpWriter writer); public static ByteBuffer allocate(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
if (ElfTargetInfo.getElfEndian() == Elf64_Ehdr.ELFDATA2LSB)
buf.order(ByteOrder.LITTLE_ENDIAN);
else
buf.order(ByteOrder.BIG_ENDIAN);
return (buf);
}
Serializer serialize(Object obj) throws IOException;
void reset() throws IOException;
} }

View File

@ -0,0 +1,85 @@
/*
* 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
* 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.binformat.elf;
import java.io.File;
import java.io.FileOutputStream;
public class ElfContainer {
File outputFile;
FileOutputStream outputStream;
long fileOffset;
public ElfContainer(String fileName, String aotVersion) {
String baseName;
outputFile = new File(fileName);
if (outputFile.exists()) {
outputFile.delete();
}
try {
outputStream = new FileOutputStream(outputFile);
} catch (Exception e) {
System.out.println("ElfContainer: Can't create file " + fileName);
}
fileOffset = 0;
}
public void close() {
try {
outputStream.close();
} catch (Exception e) {
System.out.println("ElfContainer: close failed");
}
}
public void writeBytes(byte [] bytes) {
if (bytes == null) return;
try {
outputStream.write(bytes);
} catch (Exception e) {
System.out.println("ElfContainer: writeBytes failed");
}
fileOffset += bytes.length;
}
// Write bytes to output file with up front alignment padding
public void writeBytes(byte [] bytes, int alignment) {
if (bytes == null) return;
try {
// Pad to alignment
while ((fileOffset & (long)(alignment-1)) != 0) {
outputStream.write(0);
fileOffset++;
}
outputStream.write(bytes);
} catch (Exception e) {
System.out.println("ElfContainer: writeBytes failed");
}
fileOffset += bytes.length;
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.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;
public 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.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);
}
// Update header with file offset of first section
public 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);
}
// 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);
}
public byte[] getArray() {
return header.array();
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -20,32 +20,32 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package org.graalvm.compiler.salver.writer;
import java.io.Closeable; package jdk.tools.jaotc.binformat.elf;
import java.io.Flushable;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public interface DumpWriter extends Closeable, Flushable, AutoCloseable { 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;
DumpWriter write(byte b) throws IOException; public class ElfRelocEntry {
ByteBuffer entry;
DumpWriter write(byte[] arr) throws IOException; public ElfRelocEntry(int offset, int symno, int type, int addend) {
DumpWriter write(ByteBuffer buf) throws IOException; entry = ElfByteBuffer.allocate(Elf64_Rela.totalsize);
DumpWriter write(CharSequence csq) throws IOException; 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_addend.off, addend);
}
DumpWriter writeChar(char v) throws IOException; public byte[] getArray() {
return entry.array();
DumpWriter writeShort(short v) throws IOException; }
DumpWriter writeInt(int v) throws IOException;
DumpWriter writeLong(long v) throws IOException;
DumpWriter writeFloat(float v) throws IOException;
DumpWriter writeDouble(double v) throws IOException;
} }

View File

@ -0,0 +1,81 @@
/*
* 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
* 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.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;
public ElfRelocTable(int numsects) {
relocEntries = new ArrayList<ArrayList<ElfRelocEntry>>(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);
relocEntries.get(sectindex).add(entry);
}
public 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) {
ArrayList<ElfRelocEntry> entryList = relocEntries.get(section_index);
if (entryList.size() == 0)
return null;
ByteBuffer relocData = ElfByteBuffer.allocate(entryList.size() * Elf64_Rela.totalsize);
// Copy each entry to a single ByteBuffer
for (int i = 0; i < entryList.size(); i++) {
ElfRelocEntry entry = entryList.get(i);
relocData.put(entry.getArray());
}
return (relocData.array());
}
}

View File

@ -0,0 +1,181 @@
/*
* 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
* 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.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;
/**
* String holding section name strings
*/
private static StringBuilder sectNameTab = new StringBuilder();
/**
* 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 sectIndex) {
long align;
section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize);
// Return all 0's for NULL section
if (sectIndex == 0) {
sectNameTab.append('\0');
shStrTabNrOfBytes += 1;
data = null;
hasrelocations = false;
sectionIndex = 0;
return;
}
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);
section.putLong(Elf64_Shdr.sh_addr.off, 0);
section.putLong(Elf64_Shdr.sh_offset.off, 0);
if (sectName.equals(".shstrtab")) {
section.putLong(Elf64_Shdr.sh_size.off, shStrTabNrOfBytes);
data = sectNameTab.toString().getBytes();
}
else {
data = sectData;
section.putLong(Elf64_Shdr.sh_size.off, sectData.length);
}
section.putLong(Elf64_Shdr.sh_entsize.off, 0);
// Determine the alignment and entrysize
// based on type of section
switch (sectType) {
case Elf64_Shdr.SHT_PROGBITS:
if ((sectFlags & Elf64_Shdr.SHF_EXECINSTR) != 0)
align = 16;
else
align = 4;
break;
case Elf64_Shdr.SHT_SYMTAB:
align = 8;
section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Sym.totalsize);
break;
case Elf64_Shdr.SHT_STRTAB:
align = 1;
break;
case Elf64_Shdr.SHT_RELA:
align = 8;
section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rela.totalsize);
break;
case Elf64_Shdr.SHT_REL:
align = 8;
section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rel.totalsize);
break;
case Elf64_Shdr.SHT_NOBITS:
align = 4;
break;
default:
align = 8;
break;
}
section.putLong(Elf64_Shdr.sh_addralign.off, align);
hasrelocations = hasRelocations;
sectionIndex = sectIndex;
}
public String getName() {
return name;
}
public long getSize() {
return section.getLong(Elf64_Shdr.sh_size.off);
}
public int getDataAlign() {
return ((int)section.getLong(Elf64_Shdr.sh_addralign.off));
}
// Alignment requirements for the Elf64_Shdr structures
public static int getShdrAlign() {
return (4);
}
public byte[] getArray() {
return section.array();
}
public byte[] getDataArray() {
return data;
}
public void setOffset(long offset) {
section.putLong(Elf64_Shdr.sh_offset.off, offset);
}
public void setLink(int link) {
section.putInt(Elf64_Shdr.sh_link.off, link);
}
public void setInfo(int info) {
section.putInt(Elf64_Shdr.sh_info.off, info);
}
public long getOffset() {
return (section.getLong(Elf64_Shdr.sh_offset.off));
}
public boolean hasRelocations() {
return hasrelocations;
}
public int getSectionId() {
return sectionIndex;
}
}

View File

@ -0,0 +1,57 @@
/*
* 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.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;
public 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);
// Section indexes start at 1 but we manage the index internally
// as 0 relative
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() {
return sym.array();
}
}

View File

@ -0,0 +1,147 @@
/*
* 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.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 {
ArrayList<ElfSymbol>localSymbols = new ArrayList<ElfSymbol>();
ArrayList<ElfSymbol>globalSymbols = new ArrayList<ElfSymbol>();
/**
* number of symbols added
*/
int symbolCount;
/**
* String holding symbol table strings
*/
private StringBuilder strTabContent = new StringBuilder();
/**
* Keeps track of bytes in string table since strTabContent.length()
* is number of chars, not bytes.
*/
private int strTabNrOfBytes = 0;
public ElfSymtab() {
symbolCount = 0;
}
public 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;
if (name.isEmpty()) {
index = 0;
strTabContent.append('\0');
strTabNrOfBytes += 1;
sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size);
localSymbols.add(sym);
} else {
// We can't trust strTabContent.length() since that is
// chars (UTF16), keep track of bytes on our own.
index = strTabNrOfBytes;
// 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);
sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size);
if ((bind & Elf64_Sym.STB_GLOBAL) != 0)
globalSymbols.add(sym);
else
localSymbols.add(sym);
}
symbolCount++;
return (sym);
}
// 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() {
int index = 0;
// Update the local symbol indexes
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++ ) {
ElfSymbol sym = globalSymbols.get(i);
sym.setIndex(index++);
}
}
public int getNumLocalSyms() { return localSymbols.size(); }
public 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;
updateIndexes();
// Add the local symbols
for (int i = 0; i < localSymbols.size(); i++ ) {
ElfSymbol sym = localSymbols.get(i);
byte [] arr = sym.getArray();
symtabData.put(arr);
}
// Add the global symbols
for (int i = 0; i < globalSymbols.size(); i++ ) {
ElfSymbol sym = globalSymbols.get(i);
byte [] arr = sym.getArray();
symtabData.put(arr);
}
retarray = symtabData.array();
return (retarray);
}
// Return the string table array
public byte[] getStrtabArray() {
byte [] strs = strTabContent.toString().getBytes();
return (strs);
}
}

View File

@ -0,0 +1,83 @@
/*
* 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
* 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.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 {
/**
* Target architecture.
*/
private static final char arch;
/**
* Architecture endian-ness.
*/
private static final int endian = Elf64_Ehdr.ELFDATA2LSB;
/**
* Target OS string.
*/
private static String osName;
static {
// Find the target arch details
String archStr = System.getProperty("os.arch").toLowerCase();
if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) {
System.out.println("Only Little Endian byte order supported!");
}
if (archStr.equals("amd64") || archStr.equals("x86_64")) {
arch = Elf64_Ehdr.EM_X86_64;
} else {
System.out.println("Unsupported architecture " + archStr);
arch = Elf64_Ehdr.EM_NONE;
}
osName = System.getProperty("os.name").toLowerCase();
if (!osName.equals("linux") && !osName.equals("sunos")) {
System.out.println("Unsupported Operating System " + osName);
osName = "Unknown";
}
}
public static char getElfArch() {
return arch;
}
public static int getElfEndian() {
return endian;
}
public 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import jdk.tools.jaotc.binformat.Container;
import jdk.tools.jaotc.binformat.BinaryContainer; import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer; import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.CodeContainer; import jdk.tools.jaotc.binformat.CodeContainer;
@ -37,36 +38,60 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Relocation; import jdk.tools.jaotc.binformat.Relocation;
import jdk.tools.jaotc.binformat.Relocation.RelocType; import jdk.tools.jaotc.binformat.Relocation.RelocType;
import jdk.tools.jaotc.binformat.Symbol; 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.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind; import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.jnilibelf.ELFContainer;
import jdk.tools.jaotc.jnilibelf.ELFSymbol; import jdk.tools.jaotc.binformat.elf.Elf;
import jdk.tools.jaotc.jnilibelf.JNIELFContainer; import jdk.tools.jaotc.binformat.elf.ElfSymbol;
import jdk.tools.jaotc.jnilibelf.JNIELFRelocation; import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.jnilibelf.JNIELFTargetInfo; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel;
import jdk.tools.jaotc.jnilibelf.Pointer; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
public class JELFRelocObject { public class JELFRelocObject {
private final BinaryContainer binContainer; private final BinaryContainer binContainer;
private final JNIELFContainer elfContainer; private final ElfContainer elfContainer;
private final int segmentSize; private final int segmentSize;
public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) { public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
this.binContainer = binContainer; this.binContainer = binContainer;
this.elfContainer = new JNIELFContainer(outputFileName, aotVersion); this.elfContainer = new ElfContainer(outputFileName, aotVersion);
this.segmentSize = binContainer.getCodeSegmentSize(); this.segmentSize = binContainer.getCodeSegmentSize();
} }
private void createByteSection(ByteContainer c, int scnFlags) { private ElfSection createByteSection(ArrayList<ElfSection>sections,
String sectName,
byte [] scnData,
boolean hasRelocs,
int scnFlags,
int scnType) {
ElfSection sect = new ElfSection(sectName,
scnData,
scnFlags,
scnType,
hasRelocs,
sections.size());
// Add this section to our list
sections.add(sect);
return (sect);
}
private void createByteSection(ArrayList<ElfSection>sections,
ByteContainer c, int scnFlags) {
ElfSection sect;
boolean hasRelocs = c.hasRelocations();
byte[] scnData = c.getByteArray(); byte[] scnData = c.getByteArray();
int scnType = ELF.SHT_PROGBITS;
boolean zeros = !c.hasRelocations(); int scnType = Elf64_Shdr.SHT_PROGBITS;
boolean zeros = hasRelocs;
if (zeros) { if (zeros) {
for (byte b : scnData) { for (byte b : scnData) {
if (b != 0) { if (b != 0) {
@ -75,30 +100,30 @@ public class JELFRelocObject {
} }
} }
if (zeros) { if (zeros) {
scnType = ELF.SHT_NOBITS; scnType = Elf64_Shdr.SHT_NOBITS;
} }
} }
int sectionId = elfContainer.createSection(c.getContainerName(), scnData, Elf_Type.ELF_T_BYTE, segmentSize, scnType, scnFlags, ELF.SHN_UNDEF, 0); sect = createByteSection(sections, c.getContainerName(),
c.setSectionId(sectionId); scnData, hasRelocs,
// Clear out code section data to allow for GC scnFlags, scnType);
c.clear(); c.setSectionId(sect.getSectionId());
} }
private void createCodeSection(CodeContainer c) { private void createCodeSection(ArrayList<ElfSection>sections, CodeContainer c) {
createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_EXECINSTR); createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR);
} }
private void createReadOnlySection(ReadOnlyDataContainer c) { private void createReadOnlySection(ArrayList<ElfSection>sections, ReadOnlyDataContainer c) {
createByteSection(c, ELF.SHF_ALLOC); createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC);
} }
private void createReadWriteSection(ByteContainer c) { private void createReadWriteSection(ArrayList<ElfSection>sections, ByteContainer c) {
createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_WRITE); createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE);
} }
/** /**
* Create an ELF relocatable object using jdk.tools.jaotc.jnilibelf API. * Create an ELF relocatable object
* *
* @param relocationTable * @param relocationTable
* @param symbols * @param symbols
@ -106,145 +131,171 @@ public class JELFRelocObject {
*/ */
public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException { public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
// Allocate ELF Header // Allocate ELF Header
elfContainer.createELFHeader(ELF.ET_REL); ElfHeader eh = new ElfHeader();
ArrayList<ElfSection> sections = new ArrayList<ElfSection>();
// Create the null section
createByteSection(sections, null, null, false, 0, 0);
// Create text section // Create text section
createCodeSection(binContainer.getCodeContainer()); createCodeSection(sections, binContainer.getCodeContainer());
createReadOnlySection(binContainer.getMetaspaceNamesContainer()); createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
createReadOnlySection(binContainer.getKlassesOffsetsContainer()); createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
createReadOnlySection(binContainer.getMethodsOffsetsContainer()); createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
createReadOnlySection(binContainer.getKlassesDependenciesContainer()); createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
createReadWriteSection(binContainer.getMetaspaceGotContainer()); createReadWriteSection(sections, binContainer.getMetaspaceGotContainer());
createReadWriteSection(binContainer.getMetadataGotContainer()); createReadWriteSection(sections, binContainer.getMetadataGotContainer());
createReadWriteSection(binContainer.getMethodStateContainer()); createReadWriteSection(sections, binContainer.getMethodStateContainer());
createReadWriteSection(binContainer.getOopGotContainer()); createReadWriteSection(sections, binContainer.getOopGotContainer());
createReadWriteSection(binContainer.getMethodMetadataContainer()); createReadWriteSection(sections, binContainer.getMethodMetadataContainer());
createReadOnlySection(binContainer.getStubsOffsetsContainer()); createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
createReadOnlySection(binContainer.getHeaderContainer().getContainer()); createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
createReadOnlySection(binContainer.getCodeSegmentsContainer()); createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
createReadOnlySection(binContainer.getConstantDataContainer()); createReadOnlySection(sections, binContainer.getConstantDataContainer());
createReadOnlySection(binContainer.getConfigContainer()); createReadOnlySection(sections, binContainer.getConfigContainer());
// createExternalLinkage(); // createExternalLinkage();
createCodeSection(binContainer.getExtLinkageContainer()); createCodeSection(sections, binContainer.getExtLinkageContainer());
createReadWriteSection(binContainer.getExtLinkageGOTContainer()); createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
// Get ELF symbol data from BinaryContainer object's symbol tables // Get ELF symbol data from BinaryContainer object's symbol tables
createELFSymbolTables(symbols); ElfSymtab symtab = createELFSymbolTables(sections, symbols);
// Create string table section and symbol table sections in // 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 // that order since symtab section needs to set the index of
int strTabSectionIndex = elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); // strtab in sh_link field
ElfSection strTabSection = createByteSection(sections,
".strtab",
symtab.getStrtabArray(),
false,
0,
Elf64_Shdr.SHT_STRTAB);
// Now create .symtab section with the symtab data constructed. On Linux, sh_link of symtab // Now create .symtab section with the symtab data constructed.
// contains the index of string table its symbols reference and // On Linux, sh_link of symtab contains the index of string table
// sh_info contains the index of first non-local symbol // its symbols reference and sh_info contains the index of first
int scnInfo = elfContainer.getFirstNonLocalSymbolIndex(); // non-local symbol
int symTabSectionIndex = elfContainer.createSection(".symtab", getELFSymbolTableData(), Elf_Type.ELF_T_SYM, 8, ELF.SHT_SYMTAB, ELF.SHF_ALLOC, strTabSectionIndex, scnInfo); ElfSection symTabSection = createByteSection(sections,
".symtab",
symtab.getSymtabArray(),
false,
0,
Elf64_Shdr.SHT_SYMTAB);
symTabSection.setLink(strTabSection.getSectionId());
symTabSection.setInfo(symtab.getNumLocalSyms());
buildRelocations(relocationTable, symTabSectionIndex); ElfRelocTable elfRelocTable = createElfRelocTable(sections,
relocationTable);
createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId());
// Now, finally, after creating all sections, create shstrtab section // Now, finally, after creating all sections, create shstrtab section
elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); ElfSection shStrTabSection = createByteSection(sections,
".shstrtab",
null,
false,
0,
Elf64_Shdr.SHT_STRTAB);
eh.setSectionStrNdx(shStrTabSection.getSectionId());
// Run elf_update // Update all section offsets and the Elf header section offset
elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL); // Write the Header followed by the contents of each section
// and then the section structures (section table).
int file_offset = Elf64_Ehdr.totalsize;
// Run elfUpdate again to write it out. // and round it up
elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE); file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) &
// Finish ELF processing ~((sections.get(1).getDataAlign()-1));
elfContainer.elfEnd();
// 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));
sect.setOffset(file_offset);
file_offset += sect.getSize();
}
// Align the section table
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.
eh.setSectionOff(file_offset);
eh.setSectionNum(sections.size());
// Write out the Header
elfContainer.writeBytes(eh.getArray());
// Write out each section contents skipping null section
for (int i = 1; i < sections.size(); i++) {
ElfSection sect = sections.get(i);
elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
}
// Write out the section table
for (int i = 0; i < sections.size(); i++) {
ElfSection sect = sections.get(i);
elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign());
}
elfContainer.close();
} }
private void buildRelocations(Map<Symbol, List<Relocation>> relocationTable, final int symTabSectionIndex) {
/*
* Create relocation sections. This needs to be done after symbol table sections were
* created since relocation entries will need indices of sections to which they apply.
*/
createELFRelocationTables(relocationTable);
createAllRelocationSections(new SymTabELFContainer(symTabSectionIndex));
}
/** /**
* Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF * 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. * symbol table and ELF symbol table are created from BinaryContainer's symbol info.
* *
* @param symbols * @param symbols
*/ */
private void createELFSymbolTables(Collection<Symbol> symbols) { private ElfSymtab createELFSymbolTables(ArrayList<ElfSection> sections, Collection<Symbol> symbols) {
ElfSymtab symtab = new ElfSymtab();
// First, create the initial null symbol. This is a local symbol. // First, create the initial null symbol. This is a local symbol.
elfContainer.createELFSymbolEntry("", 0, 0, ELF.SHN_UNDEF, 0, 0, true); symtab.addSymbolEntry("", (byte)0, (byte)0, Elf64_Shdr.SHN_UNDEF, 0, 0);
// Now create ELF symbol entries for all symbols. // Now create ELF symbol entries for all symbols.
for (Symbol symbol : symbols) { for (Symbol symbol : symbols) {
// Get the index of section this symbol is defined in. // Get the index of section this symbol is defined in.
int secHdrIndex = symbol.getSection().getSectionId(); int secHdrIndex = symbol.getSection().getSectionId();
boolean isLocal = (symbol.getBinding() == Binding.LOCAL); ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize());
ELFSymbol elfSymbol = elfContainer.createELFSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), secHdrIndex, symbol.getSize(), symbol.getOffset(), isLocal); symbol.setNativeSymbol((NativeSymbol)elfSymbol);
symbol.setElfSymbol(elfSymbol);
} }
return (symtab);
} }
/** private static byte getELFTypeOf(Symbol sym) {
* Construct ELF symbol data from BinaryContainer object's symbol tables.
*
* @return a byte array containing the symbol table
*/
private byte[] getELFSymbolTableData() {
final int entrySize = JNIELFTargetInfo.sizeOfSymtabEntry();
// First, add all local symbols.
List<ELFSymbol> localSymbols = elfContainer.getLocalSymbols();
List<ELFSymbol> globalSymbols = elfContainer.getGlobalSymbols();
int localSymCount = localSymbols.size();
int globalSymCount = globalSymbols.size();
byte[] sectionDataArray = new byte[(localSymCount + globalSymCount) * entrySize];
for (int i = 0; i < localSymCount; i++) {
ELFSymbol symbol = localSymbols.get(i);
Pointer address = symbol.getAddress();
address.copyBytesTo(sectionDataArray, entrySize, i * entrySize);
}
// Next, add all global symbols.
for (int i = 0; i < globalSymCount; i++) {
ELFSymbol symbol = globalSymbols.get(i);
Pointer address = symbol.getAddress();
address.copyBytesTo(sectionDataArray, entrySize, (localSymCount + i) * entrySize);
}
return sectionDataArray;
}
private static int getELFTypeOf(Symbol sym) {
Kind kind = sym.getKind(); Kind kind = sym.getKind();
if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) { if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
return ELF.STT_FUNC; return Elf64_Sym.STT_FUNC;
} else if (kind == Symbol.Kind.OBJECT) { } else if (kind == Symbol.Kind.OBJECT) {
return ELF.STT_OBJECT; return Elf64_Sym.STT_OBJECT;
} }
return ELF.STT_NOTYPE; return Elf64_Sym.STT_NOTYPE;
} }
private static int getELFBindOf(Symbol sym) { private static byte getELFBindOf(Symbol sym) {
Binding binding = sym.getBinding(); Binding binding = sym.getBinding();
if (binding == Symbol.Binding.GLOBAL) { if (binding == Symbol.Binding.GLOBAL) {
return ELF.STB_GLOBAL; return Elf64_Sym.STB_GLOBAL;
} }
return ELF.STB_LOCAL; return Elf64_Sym.STB_LOCAL;
} }
/** /**
* Construct ELF relocation section data from BinaryContainer object's relocation tables. * Construct a Elf relocation table from BinaryContainer object's relocation tables.
* *
* @param sections
* @param relocationTable * @param relocationTable
*/ */
private void createELFRelocationTables(Map<Symbol, List<Relocation>> relocationTable) { private ElfRelocTable createElfRelocTable(ArrayList<ElfSection> sections,
Map<Symbol, List<Relocation>> relocationTable) {
ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size());
/* /*
* For each of the symbols with associated relocation records, create an ELF relocation * For each of the symbols with associated relocation records, create a Elf relocation
* entry. * entry.
*/ */
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) { for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
@ -252,18 +303,26 @@ public class JELFRelocObject {
Symbol symbol = entry.getKey(); Symbol symbol = entry.getKey();
for (Relocation reloc : relocs) { for (Relocation reloc : relocs) {
createRelocation(symbol, reloc); createRelocation(symbol, reloc, elfRelocTable);
} }
} }
for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) { for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
createRelocation(entry.getKey(), entry.getValue()); createRelocation(entry.getKey(), entry.getValue(), elfRelocTable);
} }
return (elfRelocTable);
} }
private void createRelocation(Symbol symbol, Relocation reloc) { private void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
RelocType relocType = reloc.getType(); RelocType relocType = reloc.getType();
int elfRelocType = getELFRelocationType(relocType); int elfRelocType = getELFRelocationType(relocType);
ElfSymbol sym = (ElfSymbol)symbol.getNativeSymbol();
int symno = sym.getIndex();
int sectindex = reloc.getSection().getSectionId();
int offset = reloc.getOffset();
int addend = 0;
switch (relocType) { switch (relocType) {
case FOREIGN_CALL_DIRECT: case FOREIGN_CALL_DIRECT:
@ -271,85 +330,89 @@ public class JELFRelocObject {
case STUB_CALL_DIRECT: case STUB_CALL_DIRECT:
case FOREIGN_CALL_INDIRECT_GOT: { case FOREIGN_CALL_INDIRECT_GOT: {
// Create relocation entry // Create relocation entry
int addend = -4; // Size in bytes of the patch location // 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 // Relocation should be applied at the location after call operand
int offset = reloc.getOffset() + reloc.getSize() + addend; offset = offset + reloc.getSize() + addend;
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
break; break;
} }
case FOREIGN_CALL_DIRECT_FAR: { case FOREIGN_CALL_DIRECT_FAR: {
// Create relocation entry // Create relocation entry
int addend = -8; // Size in bytes of the patch location addend = -8; // Size in bytes of the patch location
// Relocation should be applied at the location after call operand // Relocation should be applied at the location after call operand
// 10 = 2 (jmp [r]) + 8 (imm64) // 10 = 2 (jmp [r]) + 8 (imm64)
int offset = reloc.getOffset() + reloc.getSize() + addend - 2; offset = offset + reloc.getSize() + addend - 2;
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
break; break;
} }
case FOREIGN_CALL_INDIRECT: case FOREIGN_CALL_INDIRECT:
case JAVA_CALL_INDIRECT: case JAVA_CALL_INDIRECT:
case STUB_CALL_INDIRECT: { case STUB_CALL_INDIRECT: {
// Do nothing. // Do nothing.
break; return;
} }
case EXTERNAL_DATA_REFERENCE_FAR: { case EXTERNAL_DATA_REFERENCE_FAR: {
// Create relocation entry // Create relocation entry
int addend = -4; // Size of 32-bit address of the GOT addend = -4; // Size of 32-bit address of the GOT
/* /*
* Relocation should be applied before the test instruction to the move instruction. * Relocation should be applied before the test instruction to the move instruction.
* reloc.getOffset() points to the test instruction after the instruction that loads * offset points to the test instruction after the instruction that loads
* the address of polling page. So set the offset appropriately. * the address of polling page. So set the offset appropriately.
*/ */
int offset = reloc.getOffset() + addend; offset = offset + addend;
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
break; break;
} }
case METASPACE_GOT_REFERENCE: case METASPACE_GOT_REFERENCE:
case EXTERNAL_PLT_TO_GOT: case EXTERNAL_PLT_TO_GOT:
case STATIC_STUB_TO_STATIC_METHOD: case STATIC_STUB_TO_STATIC_METHOD:
case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: {
int addend = -4; // Size of 32-bit address of the GOT addend = -4; // Size of 32-bit address of the GOT
/* /*
* Relocation should be applied before the test instruction to the move instruction. * Relocation should be applied before the test instruction to
* reloc.getOffset() points to the test instruction after the instruction that loads * the move instruction. reloc.getOffset() points to the
* the address of polling page. So set the offset appropriately. * test instruction after the instruction that loads the
* address of polling page. So set the offset appropriately.
*/ */
int offset = reloc.getOffset() + addend; offset = offset + addend;
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
break; break;
} }
case EXTERNAL_GOT_TO_PLT: case EXTERNAL_GOT_TO_PLT:
case LOADTIME_ADDRESS: { case LOADTIME_ADDRESS: {
// this is load time relocations // this is load time relocations
elfContainer.createELFRelocationEntry(reloc.getSection(), reloc.getOffset(), elfRelocType, 0, symbol.getElfSymbol());
break; break;
} }
default: default:
throw new InternalError("Unhandled relocation type: " + relocType); throw new InternalError("Unhandled relocation type: " + relocType);
} }
elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
} }
// TODO: Populate the mapping of RelocType to ELF relocation types
private static int getELFRelocationType(RelocType relocType) { private static int getELFRelocationType(RelocType relocType) {
int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
switch (JNIELFTargetInfo.getELFArch()) { switch (ElfTargetInfo.getElfArch()) {
case ELF.EM_X64_64: case Elf64_Ehdr.EM_X86_64:
// Return R_X86_64_* entries based on relocType // Return R_X86_64_* entries based on relocType
if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { if (relocType == RelocType.FOREIGN_CALL_DIRECT ||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PLT32; 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) { } else if (relocType == RelocType.STUB_CALL_DIRECT) {
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; elfRelocType = Elf64_Rela.R_X86_64_PC32;
} else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; 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.FOREIGN_CALL_INDIRECT ||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_NONE; relocType == RelocType.JAVA_CALL_INDIRECT ||
relocType == RelocType.STUB_CALL_INDIRECT) {
elfRelocType = Elf64_Rela.R_X86_64_NONE;
} else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_GOTPCREL; 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 || } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { relocType == RelocType.EXTERNAL_PLT_TO_GOT ||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) { relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; elfRelocType = Elf64_Rela.R_X86_64_PC32;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT ||
relocType == RelocType.LOADTIME_ADDRESS) {
elfRelocType = Elf64_Rela.R_X86_64_64;
} else { } else {
assert false : "Unhandled relocation type: " + relocType; assert false : "Unhandled relocation type: " + relocType;
} }
@ -360,61 +423,26 @@ public class JELFRelocObject {
return elfRelocType; return elfRelocType;
} }
private void createAllRelocationSections(ELFContainer symtab) { private void createElfRelocSections(ArrayList<ElfSection> sections,
for (Map.Entry<ELFContainer, ArrayList<Pointer>> entry : elfContainer.getRelocTables().entrySet()) { ElfRelocTable elfRelocTable,
createRelocationSection(entry.getKey(), entry.getValue(), symtab); int symtabsectidx) {
}
}
private void createRelocationSection(ELFContainer container, ArrayList<Pointer> relocations, ELFContainer symtab) { // Grab count before we create new sections
String secName = container.getContainerName(); int count = sections.size();
int entrySize = JNIELFTargetInfo.sizeOfRelocEntry();
int numEntries = relocations.size();
byte[] sectionDataBytes = new byte[numEntries * entrySize];
for (int index = 0; index < relocations.size(); index++) { for (int i = 0; i < count; i++) {
Pointer entry = relocations.get(index); if (elfRelocTable.getNumRelocs(i) > 0) {
entry.copyBytesTo(sectionDataBytes, entrySize, index * entrySize); ElfSection sect = sections.get(i);
} String relname = ".rela" + sect.getName();
String fullSecName; ElfSection relocSection = createByteSection(sections,
// If relocDat is non-null create section relname,
if (sectionDataBytes.length > 0) { elfRelocTable.getRelocData(i),
int scnType; false,
Elf_Type dataType; 0,
if (JNIELFTargetInfo.createReloca() == 0) { Elf64_Shdr.SHT_RELA);
scnType = ELF.SHT_REL; relocSection.setLink(symtabsectidx);
dataType = Elf_Type.ELF_T_REL; relocSection.setInfo(sect.getSectionId());
fullSecName = ".rel" + secName;
} else {
scnType = ELF.SHT_RELA;
dataType = Elf_Type.ELF_T_RELA;
fullSecName = ".rela" + secName;
} }
// assert compareBytes(relocData.toByteArray(), sectionDataBytes) : "******* Bad array
// copy";
// sh_link holds the index of section header of symbol table associated with this
// relocation table.
// sh_info holds the index of section header to which this relocation table applies
// to.
elfContainer.createSection(fullSecName, sectionDataBytes, dataType, 8, scnType, ELF.SHF_ALLOC, symtab.getSectionId(), container.getSectionId());
}
}
private static class SymTabELFContainer implements ELFContainer {
private final int symTabSectionIndex;
public SymTabELFContainer(int symTabSectionIndex) {
this.symTabSectionIndex = symTabSectionIndex;
}
@Override
public String getContainerName() {
return ".symtab";
}
@Override
public int getSectionId() {
return symTabSectionIndex;
} }
} }
} }

View File

@ -0,0 +1,474 @@
/*
* 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.
*/
/*
*
* File Layout generated by JMachORelocObject
*
* MachO Header
* Load Commands
* LC_SEGMENT_64
* - Sections
* LC_VERSION_MIN_MAX
* LC_SYMTAB
* LC_DYSYMTAB
* Section Data
* Relocation entries
* Symbol table
*
*/
package jdk.tools.jaotc.binformat.macho;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
import jdk.tools.jaotc.binformat.CodeContainer;
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;
import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
import jdk.tools.jaotc.binformat.macho.MachO.symtab_command;
import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command;
import jdk.tools.jaotc.binformat.macho.MachO.nlist_64;
import jdk.tools.jaotc.binformat.macho.MachO.reloc_info;
import jdk.tools.jaotc.binformat.macho.MachOContainer;
import jdk.tools.jaotc.binformat.macho.MachOTargetInfo;
import jdk.tools.jaotc.binformat.macho.MachOSymtab;
import jdk.tools.jaotc.binformat.macho.MachORelocTable;
public class JMachORelocObject {
private final BinaryContainer binContainer;
private final MachOContainer machoContainer;
private final int segmentSize;
public JMachORelocObject(BinaryContainer binContainer, String outputFileName) {
this.binContainer = binContainer;
this.machoContainer = new MachOContainer(outputFileName);
this.segmentSize = binContainer.getCodeSegmentSize();
}
private void createByteSection(ArrayList<MachOSection>sections,
ByteContainer c, String sectName, String segName, int scnFlags) {
if (c.getByteArray().length == 0) {
// System.out.println("Skipping creation of " + sectName + " section, no data\n");
}
MachOSection sect = new MachOSection(sectName,
segName,
c.getByteArray(),
scnFlags,
c.hasRelocations());
// Add this section to our list
sections.add(sect);
// Record the section Id (0 relative)
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|
section_64.S_ATTR_SOME_INSTRUCTIONS);
}
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) {
createByteSection(sections, c, c.getContainerName(), "__DATA", section_64.S_REGULAR);
}
/**
* Create an MachO relocatable object
*
* @param relocationTable
* @param symbols
* @throws IOException throws {@code IOException} as a result of file system access failures.
*/
public void createMachORelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
// Allocate MachO Header
// with 4 load commands
// LC_SEGMENT_64
// LC_VERSION_MIN_MACOSX
// LC_SYMTAB
// LC_DYSYMTAB
MachOHeader mh = new MachOHeader();
ArrayList<MachOSection> sections = new ArrayList<MachOSection>();
// Create Sections contained in the main Segment LC_SEGMENT_64
createCodeSection(sections, binContainer.getCodeContainer());
createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
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.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.getExtLinkageGOTContainer());
// Update the Header sizeofcmds size.
// This doesn't include the Header struct size
mh.setCmdSizes(4, segment_command_64.totalsize +
(section_64.totalsize * sections.size()) +
version_min_command.totalsize +
symtab_command.totalsize +
dysymtab_command.totalsize);
// 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));
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));
sect.setOffset(file_offset);
sect.setAddr(address);
file_offset += sect.getSize();
address += sect.getSize();
}
// File size for Segment data
int segment_size = file_offset - segment_offset;
// Create the LC_SEGMENT_64 Segment which contains the MachOSections
MachOSegment seg = new MachOSegment(segment_command_64.totalsize +
(section_64.totalsize * sections.size()),
segment_offset,
segment_size,
sections.size());
MachOVersion vers = new MachOVersion();
// Get symbol data from BinaryContainer object's symbol tables
MachOSymtab symtab = createMachOSymbolTables(sections, symbols);
// Create LC_DYSYMTAB command
MachODySymtab dysymtab = new MachODySymtab(symtab.getNumLocalSyms(),
symtab.getNumGlobalSyms(),
symtab.getNumUndefSyms());
// 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));
// Update relocation sizing information in each section
for (int i = 0; i < sections.size(); i++) {
MachOSection sect = sections.get(i);
if (sect.hasRelocations()) {
int nreloc = machORelocs.getNumRelocs(i);
sect.setReloff(file_offset);
sect.setRelcount(nreloc);
file_offset += (nreloc * reloc_info.totalsize);
}
}
// Calculate and set file offset for symbol table data
file_offset = (file_offset + (symtab.getAlign()-1)) & ~((symtab.getAlign()-1));
symtab.setOffset(file_offset);
// Write Out Header
machoContainer.writeBytes(mh.getArray());
// Write out first Segment
machoContainer.writeBytes(seg.getArray());
// Write out sections within first Segment
for (int i = 0; i < sections.size(); i++) {
MachOSection sect = sections.get(i);
machoContainer.writeBytes(sect.getArray());
}
// Write out LC_VERSION_MIN_MACOSX command
machoContainer.writeBytes(vers.getArray());
// Write out LC_SYMTAB command
symtab.calcSizes();
machoContainer.writeBytes(symtab.getCmdArray());
// Write out LC_DYSYMTAB command
machoContainer.writeBytes(dysymtab.getArray());
// Write out data associated with each Section
for (int i = 0; i < sections.size(); i++) {
MachOSection sect = sections.get(i);
machoContainer.writeBytes(sect.getDataArray(), sect.getAlign());
}
// 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());
}
// Write out data associated with LC_SYMTAB
machoContainer.writeBytes(symtab.getDataArray(), symtab.getAlign());
machoContainer.close();
}
/**
* 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 symbols
* @param symtab
*/
private 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);
// Now create MachO symbol entries for all symbols.
for (Symbol symbol : symbols) {
int sectionId = symbol.getSection().getSectionId();
// Symbol offsets are relative to the section memory addr
long sectionAddr = sections.get(sectionId).getAddr();
MachOSymbol machoSymbol = symtab.addSymbolEntry(symbol.getName(),
getMachOTypeOf(symbol),
(byte)sectionId,
symbol.getOffset() + sectionAddr);
symbol.setNativeSymbol((NativeSymbol)machoSymbol);
}
// Now that all symbols are enterred, update the
// symbol indexes. This is necessary since they will
// be reordered based on local, global and undefined.
symtab.updateIndexes();
return (symtab);
}
private static byte getMachOTypeOf(Symbol sym) {
Kind kind = sym.getKind();
byte type = nlist_64.N_UNDF;
// Global or Local
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 ||
kind == Symbol.Kind.OBJECT) {
type |= (nlist_64.N_SECT);
}
return (type);
}
/**
* Construct a MachO relocation table from BinaryContainer object's relocation tables.
*
* @param sections
* @param relocationTable
* @param symtab
*/
private MachORelocTable createMachORelocTable(ArrayList<MachOSection> sections,
Map<Symbol, List<Relocation>> relocationTable,
MachOSymtab symtab) {
MachORelocTable machORelocTable = new MachORelocTable(sections.size());
/*
* 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();
Symbol symbol = entry.getKey();
for (Relocation reloc : relocs) {
createRelocation(symbol, reloc, machORelocTable);
}
}
for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
createRelocation(entry.getKey(), entry.getValue(), machORelocTable);
}
return (machORelocTable);
}
private void createRelocation(Symbol symbol, Relocation reloc, MachORelocTable machORelocTable) {
RelocType relocType = reloc.getType();
int machORelocType = getMachORelocationType(relocType);
MachOSymbol sym = (MachOSymbol)symbol.getNativeSymbol();
int symno = sym.getIndex();
int sectindex = reloc.getSection().getSectionId();
int offset = reloc.getOffset();
int pcrel = 0;
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;
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: {
// Do nothing.
return;
}
case EXTERNAL_DATA_REFERENCE_FAR: {
// Create relocation entry
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.
*/
offset = offset + addend;
pcrel = 0; 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: {
// this is load time relocations
pcrel = 0; length = 3;
break;
}
default:
throw new InternalError("Unhandled relocation type: " + relocType);
}
machORelocTable.createRelocationEntry(sectindex, offset, symno,
pcrel, length, isextern,
machORelocType);
}
private static int getMachORelocationType(RelocType relocType) {
int machORelocType = 0;
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) {
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) {
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) {
machORelocType = reloc_info.X86_64_RELOC_BRANCH;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) {
machORelocType = reloc_info.X86_64_RELOC_UNSIGNED;
} else {
assert false : "Unhandled relocation type: " + relocType;
}
break;
default:
System.out.println("Relocation Type mapping: Unhandled architecture");
}
return machORelocType;
}
}

View File

@ -0,0 +1,307 @@
/*
* 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.binformat.macho;
/**
*
* Support for the creation of Mach-o Object files.
* Current support is limited to 64 bit x86_64.
*
* File Format Overview:
*
* mach_header
* load_commands
* Typical Mac OSX 64-bit object files have these 4 load_commands
* (LC_SEGMENT_64, LC_SYMTAB, LC_VERSIN_MIN_MACOSX, LC_DYSYMTAB)
* Segments corresponding to load_commands
* (which each include multiple Sections)
*/
public class MachO {
/**
* mach_header_64 structure defines
*/
public enum mach_header_64 {
magic( 0, 4),
cputype( 4, 4),
cpusubtype( 8, 4),
filetype(12, 4),
ncmds(16, 4),
sizeofcmds(20, 4),
flags(24, 4),
reserved(28, 4);
public final int off;
public final int sz;
mach_header_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
/**
* filetype
*/
public 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;
/**
* 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;
}
/**
* segment_command_64 structure defines
*/
public enum segment_command_64 {
cmd( 0, 4),
cmdsize( 4, 4),
segname( 8,16),
vmaddr(24, 8),
vmsize(32, 8),
fileoff(40, 8),
filesize(48, 8),
maxprot(56, 4),
initprot(60, 4),
nsects(64, 4),
flags(68, 4);
public final int off;
public final int sz;
segment_command_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 72;
public static final int LC_SEGMENT_64 = 0x19;
}
/**
* section_64 structure defines
*/
public enum section_64 {
sectname( 0,16),
segname(16,16),
addr(32, 8),
size(40, 8),
offset(48, 4),
align(52, 4),
reloff(56, 4),
nreloc(60, 4),
flags(64, 4),
reserved1(68, 4),
reserved2(72, 4),
reserved3(76, 4);
public final int off;
public final int sz;
section_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
}
/**
* version_min_command structure defines
*/
public enum version_min_command {
cmd( 0, 4),
cmdsize( 4, 4),
version( 8, 4),
sdk(12, 4);
public final int off;
public final int sz;
version_min_command(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 16;
public static final int LC_VERSION_MIN_MACOSX = 0x24;
public static final int LC_VERSION_MIN_IPHONEOS = 0x25;
}
/**
* symtab_command structure defines
*/
public enum symtab_command {
cmd( 0, 4),
cmdsize( 4, 4),
symoff( 8, 4),
nsyms(12, 4),
stroff(16, 4),
strsize(20, 4);
public final int off;
public final int sz;
symtab_command(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 24;
public static final int LC_SYMTAB = 0x2;
}
/**
* Symbol table entry definitions
*
* nlist_64 structure defines
*/
public 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;
nlist_64(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
}
/**
* dysymtab_command structure defines
*/
public enum dysymtab_command {
cmd( 0, 4),
cmdsize( 4, 4),
ilocalsym( 8, 4),
nlocalsym(12, 4),
iextdefsym(16, 4),
nextdefsym(20, 4),
iundefsym(24, 4),
nundefsym(28, 4),
tocoff(32, 4),
ntoc(36, 4),
modtaboff(40, 4),
nmodtab(44, 4),
extrefsymoff(48, 4),
nextrefsyms(52, 4),
indirectsymoff(56, 4),
nindirectsyms(60, 4),
extreloff(64, 4),
nextrel(68, 4),
locreloff(72, 4),
nlocrel(76, 4);
public final int off;
public final int sz;
dysymtab_command(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 80;
public static final int LC_DYSYMTAB = 0xb;
}
/**
* relocation_info structure defines
*/
public enum reloc_info {
r_address( 0, 4),
r_relocinfo( 4, 4);
public final int off;
public final int sz;
reloc_info(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
/* 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;
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.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 {
public static ByteBuffer allocate(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
if (MachOTargetInfo.getMachOEndian() ==
MachO.mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN)
buf.order(ByteOrder.LITTLE_ENDIAN);
else
buf.order(ByteOrder.BIG_ENDIAN);
return (buf);
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.binformat.macho;
import java.io.File;
import java.io.FileOutputStream;
public class MachOContainer {
File outputFile;
FileOutputStream outputStream;
long fileOffset;
public MachOContainer(String fileName) {
String baseName;
outputFile = new File(fileName);
if (outputFile.exists()) {
outputFile.delete();
}
try {
outputStream = new FileOutputStream(outputFile);
} catch (Exception e) {
System.out.println("MachOContainer: Can't create file " + fileName);
}
fileOffset = 0;
}
public void close() {
try {
outputStream.close();
} catch (Exception e) {
System.out.println("MachOContainer: close failed");
}
}
public void writeBytes(byte [] bytes) {
try {
outputStream.write(bytes);
} catch (Exception e) {
System.out.println("MachOContainer: writeBytes failed");
}
fileOffset += bytes.length;
}
// Write bytes to output file with up front alignment padding
public void writeBytes(byte [] bytes, int alignment) {
try {
// Pad to alignment
while ((fileOffset & (long)(alignment-1)) != 0) {
outputStream.write(0);
fileOffset++;
}
outputStream.write(bytes);
} catch (Exception e) {
System.out.println("MachOContainer: writeBytes failed");
}
fileOffset += bytes.length;
}
}

View File

@ -0,0 +1,54 @@
/*
* 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.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;
public MachODySymtab(int nlocal, int nglobal, int nundef) {
dysymtab = MachOByteBuffer.allocate(dysymtab_command.totalsize);
dysymtab.putInt(dysymtab_command.cmd.off, dysymtab_command.LC_DYSYMTAB);
dysymtab.putInt(dysymtab_command.cmdsize.off, dysymtab_command.totalsize);
dysymtab.putInt(dysymtab_command.ilocalsym.off, 0);
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.nundefsym.off, nundef);
}
public byte[] getArray() {
return dysymtab.array();
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.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;
public MachOHeader() {
header = MachOByteBuffer.allocate(mach_header_64.totalsize);
header.putInt(mach_header_64.magic.off, mach_header_64.MH_MAGIC_64);
header.putInt(mach_header_64.cputype.off, MachOTargetInfo.getMachOArch());
header.putInt(mach_header_64.cpusubtype.off, MachOTargetInfo.getMachOSubArch());
header.putInt(mach_header_64.flags.off, 0x2000);
header.putInt(mach_header_64.filetype.off, mach_header_64.MH_OBJECT);
}
public 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() {
return (header.getInt(mach_header_64.sizeofcmds.off));
}
public byte[] getArray() {
return header.array();
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.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;
public 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
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));
}
public byte[] getArray() {
return entry.array();
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.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;
int fileOffset;
public MachORelocTable(int numsects) {
relocEntries = new ArrayList<ArrayList<MachORelocEntry>>(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);
relocEntries.get(sectindex).add(entry);
}
public int getAlign() {
return (4);
}
public 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) {
ArrayList<MachORelocEntry> entryList = relocEntries.get(section_index);
if (entryList.size() == 0)
return null;
ByteBuffer relocData = MachOByteBuffer.allocate(entryList.size() * reloc_info.totalsize);
// Copy each entry to a single ByteBuffer
for (int i = 0; i < entryList.size(); i++) {
MachORelocEntry entry = entryList.get(i);
relocData.put(entry.getArray());
}
return (relocData.array());
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.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;
public MachOSection(String sectName, String segName, byte [] sectData, int sectFlags, boolean hasRelocations) {
section = MachOByteBuffer.allocate(section_64.totalsize);
// TODO: Hotspot uses long section names.
// 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]);
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]);
section.putLong(section_64.size.off, sectData.length);
// For now use 8 byte alignment
section.putInt(section_64.align.off, 3);
section.putInt(section_64.flags.off, sectFlags);
data = sectData;
hasrelocations = hasRelocations;
}
public long getSize() {
return section.getLong(section_64.size.off);
}
public int getAlign() {
return (1 << section.getInt(section_64.align.off));
}
public byte[] getArray() {
return section.array();
}
public byte[] getDataArray() {
return data;
}
public void setAddr(long addr) {
section.putLong(section_64.addr.off, addr);
}
public long getAddr() {
return (section.getLong(section_64.addr.off));
}
public void setOffset(int offset) {
section.putInt(section_64.offset.off, offset);
}
public int getOffset() {
return (section.getInt(section_64.offset.off));
}
public void setReloff(int offset) {
section.putInt(section_64.reloff.off, offset);
}
public void setRelcount(int count) {
section.putInt(section_64.nreloc.off, count);
}
public boolean hasRelocations() {
return hasrelocations;
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.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;
public class MachOSegment {
ByteBuffer segment;
public MachOSegment(int size, int fileoff, int filesize, int nsects) {
segment = MachOByteBuffer.allocate(segment_command_64.totalsize);
segment.putInt(segment_command_64.cmd.off, segment_command_64.LC_SEGMENT_64);
segment.putInt(segment_command_64.cmdsize.off, size);
segment.putInt(segment_command_64.maxprot.off, 7);
segment.putInt(segment_command_64.initprot.off, 7);
segment.putInt(segment_command_64.nsects.off, nsects);
segment.putInt(segment_command_64.flags.off, 0);
segment.putLong(segment_command_64.vmaddr.off, 0);
segment.putLong(segment_command_64.vmsize.off, filesize);
segment.putLong(segment_command_64.fileoff.off, fileoff);
segment.putLong(segment_command_64.filesize.off, filesize);
}
public byte[] getArray() {
return segment.array();
}
}

View File

@ -0,0 +1,54 @@
/*
* 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.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;
public MachOSymbol(int symbolindex, int strindex, byte type, byte sectindex, long offset) {
super(symbolindex);
sym = MachOByteBuffer.allocate(nlist_64.totalsize);
sym.putInt(nlist_64.n_strx.off, strindex);
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.putLong(nlist_64.n_value.off, offset);
}
public byte[] getArray() {
return sym.array();
}
}

View File

@ -0,0 +1,211 @@
/*
* 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.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 {
/**
* ByteBuffer holding the LC_SYMTAB command contents
*/
ByteBuffer symtabCmd;
/**
* ByteBuffer holding the symbol table entries and strings
*/
ByteBuffer symtabData;
int symtabDataSize;
ArrayList<MachOSymbol>localSymbols = new ArrayList<MachOSymbol>();
ArrayList<MachOSymbol>globalSymbols = new ArrayList<MachOSymbol>();
ArrayList<MachOSymbol>undefSymbols = new ArrayList<MachOSymbol>();
/**
* number of symbols added
*/
int symbolCount;
/**
* String holding symbol table strings
*/
private StringBuilder strTabContent = new StringBuilder();
/**
* Keeps track of bytes in string table since strTabContent.length()
* is number of chars, not bytes.
*/
private int strTabNrOfBytes = 0;
public MachOSymtab() {
symtabCmd = MachOByteBuffer.allocate(symtab_command.totalsize);
symtabCmd.putInt(symtab_command.cmd.off, symtab_command.LC_SYMTAB);
symtabCmd.putInt(symtab_command.cmdsize.off, symtab_command.totalsize);
symbolCount = 0;
}
public int getAlign() {
return (4);
}
public 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;
if (name.isEmpty()) {
index = 0;
strTabContent.append('\0');
strTabNrOfBytes += 1;
sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset);
localSymbols.add(sym);
} else {
// We can't trust strTabContent.length() since that is
// chars (UTF16), keep track of bytes on our own.
index = strTabNrOfBytes;
strTabContent.append("_").append(name).append('\0');
// + 1 for null, + 1 for "_"
strTabNrOfBytes += (name.getBytes().length + 1 + 1);
sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset);
switch (type) {
case nlist_64.N_EXT:
undefSymbols.add(sym);
break;
case nlist_64.N_SECT:
case nlist_64.N_UNDF: // null symbol
localSymbols.add(sym);
break;
case nlist_64.N_SECT|nlist_64.N_EXT:
globalSymbols.add(sym);
break;
default:
System.out.println("Unsupported Symbol type " + type);
break;
}
}
symbolCount++;
return (sym);
}
public 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() {
int index = 0;
// Update the local symbol indexes
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++ ) {
MachOSymbol sym = globalSymbols.get(i);
sym.setIndex(index++);
}
// Update the undefined symbol indexes
for (int i = index; i < undefSymbols.size(); i++ ) {
MachOSymbol sym = undefSymbols.get(i);
sym.setIndex(index++);
}
}
// 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 stroff;
stroff = symtabCmd.getInt(symtab_command.symoff.off) + (nlist_64.totalsize * symbolCount);
symtabCmd.putInt(symtab_command.nsyms.off, symbolCount);
symtabCmd.putInt(symtab_command.stroff.off, stroff);
symtabCmd.putInt(symtab_command.strsize.off, strTabNrOfBytes);
symtabDataSize = (nlist_64.totalsize * symbolCount) + strTabNrOfBytes;
return (symtabDataSize);
}
public int getNumLocalSyms() { return localSymbols.size(); }
public int getNumGlobalSyms() { return globalSymbols.size(); }
public int getNumUndefSyms() { return undefSymbols.size(); }
public 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;
// Add the local symbols
for (int i = 0; i < localSymbols.size(); i++ ) {
MachOSymbol sym = localSymbols.get(i);
byte [] arr = sym.getArray();
symtabData.put(arr);
}
// Add the global symbols
for (int i = 0; i < globalSymbols.size(); i++ ) {
MachOSymbol sym = globalSymbols.get(i);
byte [] arr = sym.getArray();
symtabData.put(arr);
}
// Add the undefined symbols
for (int i = 0; i < undefSymbols.size(); i++ ) {
MachOSymbol sym = undefSymbols.get(i);
byte [] arr = sym.getArray();
symtabData.put(arr);
}
// Add the stringtable
byte [] strs = strTabContent.toString().getBytes();
symtabData.put(strs);
retarray = symtabData.array();
return (retarray);
}
}

View File

@ -0,0 +1,87 @@
/*
* 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.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 {
/**
* Target architecture and subtype.
*/
private static final int arch;
private static final int subarch;
/**
* Architecture endian-ness.
*/
private static final int endian = mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN;
/**
* Target OS string.
*/
private static final String osName;
static {
// Find the target arch details
String archStr = System.getProperty("os.arch").toLowerCase();
if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) {
System.out.println("Only Little Endian byte order supported!");
}
if (archStr.equals("amd64") || archStr.equals("x86_64")) {
arch = mach_header_64.CPU_TYPE_X86_64;
subarch = mach_header_64.CPU_SUBTYPE_I386_ALL;
} else {
System.out.println("Unsupported architecture " + archStr);
arch = mach_header_64.CPU_TYPE_ANY;
subarch = 0;
}
osName = System.getProperty("os.name").toLowerCase();
}
public static int getMachOArch() {
return arch;
}
public static int getMachOSubArch() {
return subarch;
}
public static int getMachOEndian() {
return endian;
}
public static String getOsName() {
return osName;
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -20,36 +20,30 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package org.graalvm.compiler.api.collections;
import java.util.Collections; package jdk.tools.jaotc.binformat.macho;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
/** import java.nio.ByteBuffer;
* A default implementation of {@link CollectionsProvider} that creates standard JDK collection import java.nio.ByteOrder;
* class objects.
*/
public class DefaultCollectionsProvider implements CollectionsProvider {
@Override import jdk.tools.jaotc.binformat.macho.MachO;
public <E> Set<E> newIdentitySet() { import jdk.tools.jaotc.binformat.macho.MachO.version_min_command;
return Collections.newSetFromMap(newIdentityMap()); import jdk.tools.jaotc.binformat.macho.MachOByteBuffer;
public class MachOVersion {
ByteBuffer version;
public MachOVersion() {
version = MachOByteBuffer.allocate(version_min_command.totalsize);
version.putInt(version_min_command.cmd.off, version_min_command.LC_VERSION_MIN_MACOSX);
version.putInt(version_min_command.cmdsize.off, version_min_command.totalsize);
version.putInt(version_min_command.version.off, (10 << 16) | (10 << 8)); /* MacOSX 10.10 */
version.putInt(version_min_command.sdk.off, 0); /* N/A SDK */
} }
@Override public byte[] getArray() {
public <K, V> Map<K, V> newIdentityMap() { return version.array();
return new IdentityHashMap<>();
}
@Override
public <K, V> Map<K, V> newIdentityMap(int expectedMaxSize) {
return new IdentityHashMap<>(expectedMaxSize);
}
@Override
public <K, V> Map<K, V> newIdentityMap(Map<K, V> initFrom) {
return new IdentityHashMap<>(initFrom);
} }
} }

View File

@ -0,0 +1,422 @@
/*
* 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.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;
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;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
public class JPECoffRelocObject {
private final BinaryContainer binContainer;
private final PECoffContainer pecoffContainer;
private final int segmentSize;
public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
this.binContainer = binContainer;
this.pecoffContainer = new PECoffContainer(outputFileName, aotVersion);
this.segmentSize = binContainer.getCodeSegmentSize();
}
private PECoffSection createByteSection(ArrayList<PECoffSection>sections,
String sectName,
byte [] scnData,
boolean hasRelocs,
int scnFlags) {
PECoffSection sect = new PECoffSection(sectName,
scnData,
scnFlags,
hasRelocs,
sections.size());
// Add this section to our list
sections.add(sect);
return (sect);
}
private void createByteSection(ArrayList<PECoffSection>sections,
ByteContainer c, int scnFlags) {
PECoffSection sect;
boolean hasRelocs = c.hasRelocations();
byte[] scnData = c.getByteArray();
sect = createByteSection(sections, c.getContainerName(),
scnData, hasRelocs,
scnFlags);
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_16BYTES |
IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE);
}
private void createReadOnlySection(ArrayList<PECoffSection>sections, ReadOnlyDataContainer c) {
createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_16BYTES |
IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA);
}
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_8BYTES;
if (c.getByteArray().length > 0)
scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
else
scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA;
createByteSection(sections, c, scnFlags);
}
/**
* Create an PECoff relocatable object
*
* @param relocationTable
* @param symbols
* @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>();
// Create text section
createCodeSection(sections, binContainer.getCodeContainer());
createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
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.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.getExtLinkageGOTContainer());
// Allocate PECoff Header
PECoffHeader header = new PECoffHeader();
// Get PECoff symbol data from BinaryContainer object's symbol tables
PECoffSymtab symtab = createPECoffSymbolTables(sections, 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);
// 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
// Calculate Offset for Symbol table
int file_offset = IMAGE_FILE_HEADER.totalsize +
(IMAGE_SECTION_HEADER.totalsize*sections.size());
// Update Header fields
header.setSectionCount(sections.size());
header.setSymbolCount(symtab.getSymtabCount());
header.setSymbolOff(file_offset);
// Calculate file offset for first section
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));
// 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));
sect.setOffset(file_offset);
file_offset += sect.getSize();
}
// Update relocation sizing information in each section
for (int i = 0; i < sections.size(); i++) {
PECoffSection sect = sections.get(i);
if (sect.hasRelocations()) {
int nreloc = pecoffRelocs.getNumRelocs(i);
sect.setReloff(file_offset);
sect.setRelcount(nreloc);
// extended relocations add an addition entry
if (nreloc > 0xFFFF) nreloc++;
file_offset += (nreloc * IMAGE_RELOCATION.totalsize);
}
}
// Write out the Header
pecoffContainer.writeBytes(header.getArray());
// Write out the section table
for (int i = 0; i < sections.size(); i++) {
PECoffSection sect = sections.get(i);
pecoffContainer.writeBytes(sect.getArray(), PECoffSection.getShdrAlign());
}
// Write out the symbol table and string table
pecoffContainer.writeBytes(symtab.getSymtabArray(), 4);
pecoffContainer.writeBytes(symtab.getStrtabArray(), 1);
// Write out each section contents
for (int i = 0; i < sections.size(); i++) {
PECoffSection sect = sections.get(i);
pecoffContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
}
// Write out Relocation Tables
for (int i = 0; i < sections.size(); i++) {
if (pecoffRelocs.getNumRelocs(i) > 0) {
pecoffContainer.writeBytes(pecoffRelocs.getRelocData(i));
}
}
pecoffContainer.close();
}
/**
* Construct PECoff symbol data from BinaryContainer object's symbol tables. Both dynamic PECoff
* symbol table and PECoff symbol table are created from BinaryContainer's symbol info.
*
* @param symbols
*/
private PECoffSymtab createPECoffSymbolTables(ArrayList<PECoffSection> sections, Collection<Symbol> symbols) {
PECoffSymtab symtab = new PECoffSymtab();
// First, create the initial null symbol. This is a local symbol.
// symtab.addSymbolEntry("", (byte)0, (byte)0, (byte)0, 0, 0);
// Now create PECoff symbol entries for all symbols.
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);
}
return (symtab);
}
private static byte getPECoffTypeOf(Symbol sym) {
Kind kind = sym.getKind();
if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION;
}
return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_NONE;
}
private static byte getPECoffClassOf(Symbol sym) {
Binding binding = sym.getBinding();
if (binding == Symbol.Binding.GLOBAL) {
return IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL;
}
return IMAGE_SYMBOL.IMAGE_SYM_CLASS_STATIC;
}
/**
* Construct a PECoff relocation table from BinaryContainer object's relocation tables.
*
* @param sections
* @param 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 (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
List<Relocation> relocs = entry.getValue();
Symbol symbol = entry.getKey();
for (Relocation reloc : relocs) {
createRelocation(symbol, reloc, pecoffRelocTable);
}
}
for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
createRelocation(entry.getKey(), entry.getValue(), pecoffRelocTable);
}
return (pecoffRelocTable);
}
private void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) {
RelocType relocType = reloc.getType();
int pecoffRelocType = getPECoffRelocationType(relocType);
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: {
// Create relocation entry
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
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.
*/
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: {
// this is load time relocations
break;
}
default:
throw new InternalError("Unhandled relocation type: " + relocType);
}
pecoffRelocTable.createRelocationEntry(sectindex, offset, symno, pecoffRelocType);
}
// Return IMAGE_RELOCATION Type based on relocType
private static int getPECoffRelocationType(RelocType relocType) {
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 ||
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) {
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) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT ||
relocType == RelocType.LOADTIME_ADDRESS) {
pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
} else {
assert false : "Unhandled relocation type: " + relocType;
}
break;
default:
System.out.println("Relocation Type mapping: Unhandled architecture");
}
return pecoffRelocType;
}
}

View File

@ -0,0 +1,200 @@
/*
* 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.binformat.pecoff;
/**
*
* Support for the creation of Coff files.
* Current support is limited to 64 bit x86_64.
*
*/
public class PECoff {
/**
* IMAGE_FILE_HEADER structure defines
*/
public enum IMAGE_FILE_HEADER {
Machine( 0, 2),
NumberOfSections( 2, 2),
TimeDateStamp( 4, 4),
PointerToSymbolTable( 8, 4),
NumberOfSymbols(12, 4),
SizeOfOptionalHeader(16, 2),
Characteristics(18, 2);
public final int off;
public final int sz;
IMAGE_FILE_HEADER(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 20;
/**
* IMAGE_FILE_HEADER defines
*/
/**
* Machine
*/
public static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
public static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664;
}
/**
* IMAGE_SECTION_HEADER structure defines
*/
public enum IMAGE_SECTION_HEADER {
Name( 0, 8),
PhysicalAddress( 8, 4),
VirtualSize( 8, 4),
VirtualAddress(12, 4),
SizeOfRawData(16, 4),
PointerToRawData(20, 4),
PointerToRelocations(24, 4),
PointerToLinenumbers(28, 4),
NumberOfRelocations(32, 2),
NumberOfLinenumbers(34, 2),
Characteristics(36, 4);
public final int off;
public final int sz;
IMAGE_SECTION_HEADER(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 40;
/**
* IMAGE_SECTION_HEADER defines
*/
/**
* 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;
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_MASK = 0xf00000;
public static final int IMAGE_SCN_ALIGN_SHIFT = 20;
public 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;
}
/**
* Symbol table entry definitions
*
* IMAGE_SYMBOL structure defines
*/
public enum IMAGE_SYMBOL {
ShortName( 0, 8),
Short( 0, 4),
Long( 4, 4),
Value( 8, 4),
SectionNumber(12, 2),
Type(14, 2),
StorageClass(16, 1),
NumberOfAuxSymbols(17, 1);
public final int off;
public final int sz;
IMAGE_SYMBOL(int offset, int size) {
this.off = offset;
this.sz = size;
}
public static int totalsize = 18;
/**
* Type
*/
public static final int IMAGE_SYM_DTYPE_NONE = 0x0;
public 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;
}
/**
* IMAGE_RELOCATION structure defines
*/
public enum IMAGE_RELOCATION {
VirtualAddress( 0, 4),
SymbolTableIndex( 4, 4),
Type( 8, 2);
public final int off;
public final int sz;
IMAGE_RELOCATION(int offset, int size) {
this.off = offset;
this.sz = size;
}
public 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;
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -20,11 +20,19 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package org.graalvm.compiler.salver.data;
import java.util.LinkedHashMap; package jdk.tools.jaotc.binformat.pecoff;
public class DataDict extends LinkedHashMap<Object, Object> { import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class PECoffByteBuffer {
public static ByteBuffer allocate(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
// Only support Little Endian on Windows
buf.order(ByteOrder.LITTLE_ENDIAN);
return (buf);
}
private static final long serialVersionUID = 1L;
} }

View File

@ -0,0 +1,85 @@
/*
* 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.binformat.pecoff;
import java.io.File;
import java.io.FileOutputStream;
public class PECoffContainer {
File outputFile;
FileOutputStream outputStream;
long fileOffset;
public PECoffContainer(String fileName, String aotVersion) {
String baseName;
outputFile = new File(fileName);
if (outputFile.exists()) {
outputFile.delete();
}
try {
outputStream = new FileOutputStream(outputFile);
} catch (Exception e) {
System.out.println("PECoffContainer: Can't create file " + fileName);
}
fileOffset = 0;
}
public void close() {
try {
outputStream.close();
} catch (Exception e) {
System.out.println("PECoffContainer: close failed");
}
}
public void writeBytes(byte [] bytes) {
if (bytes == null) return;
try {
outputStream.write(bytes);
} catch (Exception e) {
System.out.println("PECoffContainer: writeBytes failed");
}
fileOffset += bytes.length;
}
// Write bytes to output file with up front alignment padding
public void writeBytes(byte [] bytes, int alignment) {
if (bytes == null) return;
try {
// Pad to alignment
while ((fileOffset & (long)(alignment-1)) != 0) {
outputStream.write(0);
fileOffset++;
}
outputStream.write(bytes);
} catch (Exception e) {
System.out.println("PECoffContainer: writeBytes failed");
}
fileOffset += bytes.length;
}
}

View File

@ -0,0 +1,68 @@
/*
* 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.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;
public 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.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);
}
// Update header with the number of total sections
public 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) {
header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, count);
}
// Update header with the offset of symbol table
public void setSymbolOff(int offset) {
header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, offset);
}
public byte[] getArray() {
return header.array();
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -20,38 +20,30 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package org.graalvm.compiler.core.common.util;
import java.util.ArrayList; package jdk.tools.jaotc.binformat.pecoff;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/** import java.nio.ByteBuffer;
* Mimic a set implementation with an ArrayList. Beneficial for small sets (compared to import java.nio.ByteOrder;
* {@link HashSet}).
*/
public class ArraySet<E> extends ArrayList<E> implements Set<E> {
private static final long serialVersionUID = 4476957522387436654L;
public ArraySet() { import jdk.tools.jaotc.binformat.pecoff.PECoff;
super(); import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer;
public class PECoffRelocEntry {
ByteBuffer entry;
public 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);
} }
public ArraySet(int i) { public byte[] getArray() {
super(i); return entry.array();
}
public ArraySet(Collection<? extends E> c) {
super(c);
}
@Override
public boolean add(E e) {
// avoid duplicated entries
if (contains(e)) {
return false;
}
return super.add(e);
} }
} }

View File

@ -0,0 +1,92 @@
/*
* 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.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 {
ArrayList<ArrayList<PECoffRelocEntry>> relocEntries;
public PECoffRelocTable(int numsects) {
relocEntries = new ArrayList<ArrayList<PECoffRelocEntry>>(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);
relocEntries.get(sectindex).add(entry);
}
public int getAlign() { return (4); }
public 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) {
ArrayList<PECoffRelocEntry> entryList = relocEntries.get(section_index);
int entryCount = entryList.size();
int allocCount = entryCount;
if (entryCount == 0)
return null;
if (entryCount > 0xFFFF)
allocCount++;
ByteBuffer relocData = PECoffByteBuffer.allocate(allocCount * IMAGE_RELOCATION.totalsize);
// If number of relocs exceeds 65K, add the real size
// in a dummy first reloc entry
if (entryCount > 0xFFFF) {
PECoffRelocEntry entry = new PECoffRelocEntry(allocCount, 0, 0);
relocData.put(entry.getArray());
}
// Copy each entry to a single ByteBuffer
for (int i = 0; i < entryCount; i++) {
PECoffRelocEntry entry = entryList.get(i);
relocData.put(entry.getArray());
}
return (relocData.array());
}
}

View File

@ -0,0 +1,140 @@
/*
* 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.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;
public PECoffSection(String sectName, byte [] sectData, int sectFlags,
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];
// 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;
section.put(Name, IMAGE_SECTION_HEADER.Name.off, max);
section.putInt(IMAGE_SECTION_HEADER.VirtualSize.off, 0);
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.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() {
return section.getInt(IMAGE_SECTION_HEADER.SizeOfRawData.off);
}
public int getDataAlign() {
return (align);
}
// Alignment requirements for the IMAGE_SECTION_HEADER structures
public static int getShdrAlign() {
return (4);
}
public byte[] getArray() {
return section.array();
}
public byte[] getDataArray() {
return data;
}
public void setOffset(long offset) {
section.putInt(IMAGE_SECTION_HEADER.PointerToRawData.off, (int)offset);
}
public long getOffset() {
return (section.getInt(IMAGE_SECTION_HEADER.PointerToRawData.off));
}
public void setReloff(int offset) {
section.putInt(IMAGE_SECTION_HEADER.PointerToRelocations.off, offset);
}
public 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 first reloc entry for this section.
if (count > 0xFFFF) {
int flags;
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);
}
}
public boolean hasRelocations() {
return hasrelocations;
}
public int getSectionId() {
return sectionIndex;
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.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;
public PECoffSymbol(int symbolindex, int strindex, byte type, byte storageclass,
byte sectindex, long offset, long size) {
super(symbolindex);
sym = PECoffByteBuffer.allocate(IMAGE_SYMBOL.totalsize);
// We don't use short names
sym.putInt(IMAGE_SYMBOL.Short.off, 0);
sym.putInt(IMAGE_SYMBOL.Long.off, strindex);
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.Type.off, (char)type);
sym.put(IMAGE_SYMBOL.StorageClass.off, storageclass);
sym.put(IMAGE_SYMBOL.NumberOfAuxSymbols.off, (byte)0);
}
public byte[] getArray() {
return sym.array();
}
}

View File

@ -0,0 +1,151 @@
/*
* 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.binformat.pecoff;
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>();
/**
* number of symbols added
*/
int symbolCount;
/**
* String holding symbol table strings
*/
private StringBuilder strTabContent;
/**
* 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;
public PECoffSymtab() {
symbolCount = 0;
strTabContent = new StringBuilder();
directives = new StringBuilder();
// The first 4 bytes of the string table contain
// the length of the table (including this length field).
strTabNrOfBytes = 4;
// Make room for the 4 byte length field
strTabContent.append('\0').append('\0').append('\0').append('\0');
// Linker Directives start with 3 spaces to signify ANSI
directives.append(" ");
}
public PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass,
byte secHdrIndex, long offset, long size) {
// Get the current symbol index and append symbol name to string table.
int index;
PECoffSymbol sym;
if (name.isEmpty()) {
index = 0;
strTabContent.append('\0');
strTabNrOfBytes += 1;
sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size);
symbols.add(sym);
} else {
int nameSize = name.getBytes().length;
// We can't trust strTabContent.length() since that is
// chars (UTF16), keep track of bytes on our own.
index = strTabNrOfBytes;
// strTabContent.append('_').append(name).append('\0');
strTabContent.append(name).append('\0');
strTabNrOfBytes += (nameSize + 1);
sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size);
symbols.add(sym);
if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL)
addDirective(name, type);
}
symbolCount++;
return (sym);
}
private void addDirective(String name, byte type) {
directives.append("/EXPORT:" + name);
if(type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) {
directives.append(",DATA");
}
directives.append(" ");
}
public int getSymtabCount() {
return symbolCount;
}
public 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);
symtabData.order(ByteOrder.LITTLE_ENDIAN);
// copy all symbols
for (int i = 0; i < symbolCount; i++ ) {
PECoffSymbol sym = symbols.get(i);
byte [] arr = sym.getArray();
symtabData.put(arr);
}
return (symtabData.array());
}
// Return the string table array
public byte[] getStrtabArray() {
byte [] strs = strTabContent.toString().getBytes();
// Update the size of the string table
ByteBuffer buff = ByteBuffer.wrap(strs);
buff.order(ByteOrder.LITTLE_ENDIAN);
buff.putInt(0, strTabNrOfBytes);
return (strs);
}
public byte[] getDirectiveArray() {
return (directives.toString().getBytes());
}
}

Some files were not shown because too many files have changed in this diff Show More