This commit is contained in:
Coleen Phillimore 2017-03-14 14:07:24 -04:00
commit 35e8433c1c
322 changed files with 8650 additions and 6767 deletions

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

@ -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
@ -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) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 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.
* *
@ -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

@ -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
@ -2195,75 +2195,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

@ -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
@ -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)
@ -349,7 +349,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

@ -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
@ -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
@ -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;
@ -1404,7 +1401,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, 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
@ -4092,7 +4092,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;
@ -4103,10 +4103,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);
@ -4115,10 +4111,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);
} }
@ -4175,7 +4167,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;
@ -4189,14 +4182,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);
@ -4217,7 +4212,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
@ -4253,9 +4248,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");
} }
@ -4269,7 +4266,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;
@ -4283,14 +4281,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);
@ -4311,7 +4311,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
@ -4346,9 +4346,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");
} }
@ -4361,16 +4363,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");
} }
@ -4388,7 +4398,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;
@ -4406,13 +4417,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);
@ -4421,7 +4434,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);
@ -4436,12 +4449,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);
@ -4933,16 +4948,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, 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
@ -817,33 +817,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,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, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2016 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
@ -646,12 +646,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) {
@ -695,6 +689,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;
} }
@ -1897,7 +1895,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.
@ -1913,6 +1911,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:
@ -1989,7 +1991,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.
@ -2005,8 +2007,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(),
@ -5899,8 +5910,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;
@ -5910,20 +5920,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);
} }
@ -5940,6 +5942,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);
@ -5958,17 +5961,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);
} }
@ -5981,7 +5979,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;
@ -5996,7 +5995,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
{ {
@ -6011,7 +6012,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
@ -6019,21 +6020,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
}
} }
/** /**
@ -6045,7 +6048,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;
@ -6059,7 +6063,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);
@ -6071,13 +6077,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
}
} }
/** /**
@ -6087,22 +6096,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
@ -1009,22 +1009,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

@ -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, 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
@ -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");
@ -1967,7 +1964,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.
@ -2023,10 +2020,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)
@ -2034,7 +2031,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));
@ -2044,7 +2041,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.
@ -2063,8 +2060,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) 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
@ -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

@ -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
@ -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) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 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
@ -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,6 +36,8 @@ 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;
@ -44,7 +46,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
* *
* <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 for MS Windows operating systems. * OS or PEContainer for MS Windows operating systems.
* *
* <p> * <p>
@ -264,29 +266,29 @@ public class BinaryContainer implements SymbolTable {
// 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();
@ -497,11 +499,21 @@ 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 +754,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,6 +1,5 @@
/* /*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007 Red Hat, Inc.
* 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,18 +19,25 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 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 * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*
*/ */
#include "precompiled.hpp" package jdk.tools.jaotc.binformat.elf;
#include "assembler_zero.inline.hpp"
#include "memory/metaspaceShared.hpp"
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
public class ElfByteBuffer {
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);
}
void MetaspaceShared::generate_vtable_methods(void** vtbl_list,
void** vtable,
char** md_top,
char* md_end,
char** mc_top,
char* mc_end) {
ShouldNotCallThis();
} }

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

@ -0,0 +1,51 @@
/*
* 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_Rela;
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
public class ElfRelocEntry {
ByteBuffer entry;
public ElfRelocEntry(int offset, int symno, int type, int addend) {
entry = ElfByteBuffer.allocate(Elf64_Rela.totalsize);
entry.putLong(Elf64_Rela.r_offset.off, offset);
entry.putLong(Elf64_Rela.r_info.off, Elf64_Rela.ELF64_R_INFO(symno,type));
entry.putLong(Elf64_Rela.r_addend.off, addend);
}
public byte[] getArray() {
return entry.array();
}
}

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

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

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) 2016, 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
@ -21,15 +21,18 @@
* questions. * questions.
*/ */
package jdk.tools.jaotc.jnilibelf; package jdk.tools.jaotc.binformat.pecoff;
import jdk.internal.misc.Unsafe; import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/** public class PECoffByteBuffer {
* Package private access to the {@link Unsafe} capability.
*/
class UnsafeAccess {
static final Unsafe UNSAFE = Unsafe.getUnsafe(); public static ByteBuffer allocate(int size) {
ByteBuffer buf = ByteBuffer.allocate(size);
// Only support Little Endian on Windows
buf.order(ByteOrder.LITTLE_ENDIAN);
return (buf);
}
} }

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

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

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());
}
}

View file

@ -0,0 +1,74 @@
/*
* 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.ByteOrder;
import jdk.tools.jaotc.binformat.pecoff.PECoff;
import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
/**
* Class that abstracts MACH-O target details.
*
*/
public class PECoffTargetInfo {
/**
* Target architecture.
*/
private static final char arch;
/**
* 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 = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64;
} else {
System.out.println("Unsupported architecture " + archStr);
arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN;
}
osName = System.getProperty("os.name").toLowerCase();
if (!osName.contains("windows")) {
System.out.println("Unsupported Operating System " + osName);
osName = "Unknown";
}
}
public static char getPECoffArch() {
return arch;
}
public static String getOsName() {
return osName;
}
}

View file

@ -1,76 +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.
*
* 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.jnilibelf;
/**
* This class represents a {@code Elf32_Sym} or {@code Elf64_Sym} as defined in {@code elf.h}.
*/
public class ELFSymbol {
/** Symbol name. */
private final String name;
/** String table index. */
private final int index;
/** Native memory address of ELF sym entry. */
private final Pointer address;
private final boolean isLocal;
public ELFSymbol(String name, int index, Pointer address, boolean isLocal) {
this.name = name;
this.index = index;
this.address = address;
this.isLocal = isLocal;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the index
*/
public int getIndex() {
return index;
}
/**
* @return the address
*/
public Pointer getAddress() {
return address;
}
@Override
public String toString() {
return "name=" + name + ", index=" + index + ", address=" + address;
}
public boolean isLocal() {
return isLocal;
}
}

View file

@ -1,476 +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.
*
* 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.jnilibelf;
import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF;
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type;
/**
* A class abstraction of an ELF file.
*
*/
public class JNIELFContainer {
private String outputFileName;
private File outFile;
private int outFileDesc;
/**
* Pointer to Elf file. This is the same as struct Elf found in libelf.h
*/
private Pointer elfPtr;
/**
* Class of the ELF container - one of ELFCLASS32 or ELFCLASS64.
*/
private final int elfClass;
/**
* Pointer to ELF Header.
*/
private Pointer ehdrPtr;
/**
* Pointer to Program Header.
*/
private Pointer phdrPtr;
/**
* String holding .shstrtab contents.
*/
private String shStrTabContent = "";
/**
* Map of local symbol indexes to ELF symbol entries.
*/
private List<ELFSymbol> localSymbolIndex = new ArrayList<>();
/**
* Map of global symbol indexes to ELF symbol entries.
*/
private List<ELFSymbol> globalSymbolIndex = new ArrayList<>();
/**
* String holding .strtab contents.
*/
private StringBuilder strTabContent = new StringBuilder();
/**
* Keeps track of nr of bytes in .strtab since strTabContent.length() is number of chars, not
* bytes.
*/
private int strTabNrOfBytes = 0;
/**
* A hashtable that holds (section-name, relocation-table) pairs. For example, [(".rela.text",
* rela-text-reloc-entries), (".rela.plt", rela-plt-reloc-entries), ...].
*/
private Map<ELFContainer, ArrayList<Pointer>> relocTables = new HashMap<>();
/**
* Create reloca; 0 => false and non-zero => true.
*/
private final int createReloca;
/**
* Construct an ELFContainer in preparation for a disk image with file {@code prefix}.
*
* @param fileName name of ELF file to be created
*/
public JNIELFContainer(String fileName, String aotVersion) {
// Check for version compatibility
if (!JNILibELFAPI.elfshim_version().equals(aotVersion)) {
throw new InternalError("libelfshim version mismatch: " + JNILibELFAPI.elfshim_version() + " vs " + aotVersion);
}
elfClass = JNIELFTargetInfo.getELFClass();
createReloca = JNIELFTargetInfo.createReloca();
outputFileName = fileName;
}
/**
* Get the local ELF symbol table.
*
* @return local symbol table
*/
public List<ELFSymbol> getLocalSymbols() {
return localSymbolIndex;
}
/**
* Get the global ELF symbol table.
*
* @return list of global ELF symbol table entries
*/
public List<ELFSymbol> getGlobalSymbols() {
return globalSymbolIndex;
}
/**
* Get string table content (.strtab).
*
* @return string table content
*/
public String getStrTabContent() {
return strTabContent.toString();
}
/**
* Get section header string table content (.shstrtab).
*
* @return section header string table content
*/
public String getShStrTabContent() {
return shStrTabContent;
}
/**
* Get relocation tables.
*
* @return relocation tables
*/
public Map<ELFContainer, ArrayList<Pointer>> getRelocTables() {
return relocTables;
}
/**
* Get the index of first non-local symbol in symbol table.
*
* @return symbol table index
*/
public int getFirstNonLocalSymbolIndex() {
return localSymbolIndex.size();
}
/**
* Create ELF header of type {@code ececType}.
*
* @param type type of ELF executable
*/
public void createELFHeader(int type) {
// Check for version compatibility
if (JNILibELFAPI.elf_version(ELF.EV_CURRENT) == ELF.EV_NONE) {
throw new InternalError("ELF version mismatch");
}
outFile = constructRelocFile(outputFileName);
// Open a temporary file for the shared library to be created
// TODO: Revisit file permissions; need to add execute permission
outFileDesc = JNILibELFAPI.open_rw(outFile.getPath());
if (outFileDesc == -1) {
System.out.println("Failed to open file " + outFile.getPath() + " to write relocatable object.");
}
elfPtr = JNILibELFAPI.elf_begin(outFileDesc, LibELF.Elf_Cmd.ELF_C_WRITE.intValue(), new Pointer(0L));
if (elfPtr == null) {
throw new InternalError("elf_begin failed");
}
// Allocate new Ehdr of current architecture class
ehdrPtr = JNILibELFAPI.gelf_newehdr(elfPtr, elfClass);
JNILibELFAPI.ehdr_set_data_encoding(ehdrPtr, JNIELFTargetInfo.getELFEndian());
JNILibELFAPI.set_Ehdr_e_machine(elfClass, ehdrPtr, JNIELFTargetInfo.getELFArch());
JNILibELFAPI.set_Ehdr_e_type(elfClass, ehdrPtr, type);
JNILibELFAPI.set_Ehdr_e_version(elfClass, ehdrPtr, ELF.EV_CURRENT);
}
/**
* If the file name has a .so extension, replace it with .o extension. Else just add .o
* extension
*
* @param fileName
* @return File object
*/
private static File constructRelocFile(String fileName) {
File relocFile = new File(fileName);
if (relocFile.exists()) {
if (!relocFile.delete()) {
throw new InternalError("Failed to delete existing " + fileName + " file");
}
}
return relocFile;
}
/**
* Create {@code count} number of Program headers.
*
* @param count number of program headers to create
* @return true upon success; false upon failure
*/
public boolean createProgramHeader(int count) {
phdrPtr = JNILibELFAPI.gelf_newphdr(elfPtr, count);
if (phdrPtr == null) {
System.out.println("gelf_newphdr error");
return false;
}
return true;
}
/**
* Set program header to be of type self.
*
* @return true
*/
public boolean setProgHdrTypeToSelf() {
// Set program header to be of type self
JNILibELFAPI.phdr_set_type_self(elfClass, ehdrPtr, phdrPtr);
// And thus mark it as dirty so that elfUpdate can recompute the structures
JNILibELFAPI.elf_flagphdr(elfPtr, LibELF.Elf_Cmd.ELF_C_SET.intValue(), LibELF.ELF_F_DIRTY);
// TODO: Error checking; look at the return value of elf_update
// and call elf_errmsg appropriately.
return true;
}
/**
* Create a section. The corresponding section header and section data are created by calling
* the necessary libelf APIs. The section that is created is inserted into the ELF container.
*
* @param secName name of the section
* @param scnData section data
* @param dataType data type
* @param align section alignment
* @param scnType section type
* @param scnFlags section flags
* @param scnLink sh_link field of Elf{32,64}_Shdr
* @param scnInfo sh_info field of Elf{32,64}_Shdr
* @return section index
*/
public int createSection(String secName, byte[] scnData, Elf_Type dataType, int align, int scnType, int scnFlags, int scnLink, int scnInfo) {
// Create a new section
Pointer scnPtr = JNILibELFAPI.elf_newscn(elfPtr);
if (scnPtr == null) {
throw new InternalError("elf_newscn error");
}
// Allocate section data for the section
Pointer scnDataPtr = JNILibELFAPI.elf_newdata(scnPtr);
if (scnDataPtr == null) {
String errMsg = JNILibELFAPI.elf_errmsg(-1);
throw new InternalError("elf_newdata error: " + errMsg);
}
// Get the pointer to section header associated with the new section
Pointer scnHdrPtr = JNILibELFAPI.elf64_getshdr(scnPtr);
// Add name of the section to section name string
// If secName is null, point the name to the 0th index
// that holds `\0'
byte[] modScnData;
if (secName.isEmpty()) {
JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, 0);
modScnData = scnData;
} else {
if (secName.equals(".shstrtab")) {
// Modify .shstrtab data by inserting '\0' at index 0
String shstrtabSecName = ".shstrtab" + '\0';
// Additional byte for the '\0' at position 0
ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1 + shstrtabSecName.length());
nbuf.put(0, (byte) 0);
nbuf.position(1);
nbuf.put(scnData);
nbuf.position(scnData.length + 1);
// Add the section name ".shstrtab" to its own data
nbuf.put(shstrtabSecName.getBytes(StandardCharsets.UTF_8));
modScnData = nbuf.array();
JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, scnData.length + 1);
// Set strtab section index
JNILibELFAPI.set_Ehdr_e_shstrndx(elfClass, ehdrPtr, JNILibELFAPI.elf_ndxscn(scnPtr));
} else if (secName.equals(".strtab")) {
// Modify strtab section data to insert '\0' at position 0.
// Additional byte for the '\0' at position 0
ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1);
nbuf.put(0, (byte) 0);
nbuf.position(1);
nbuf.put(scnData);
modScnData = nbuf.array();
// Set the sh_name
JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1);
// Add scnName to stringList
shStrTabContent += secName + '\0';
} else {
// Set the sh_name
JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1);
// Add scnName to stringList
shStrTabContent += secName + '\0';
modScnData = scnData;
}
}
final int scnDataBufSize = modScnData.length;
Pointer scnDataBufPtr = null;
if (scnType != ELF.SHT_NOBITS) {
// Allocate native memory for section data
final long address = UNSAFE.allocateMemory(scnDataBufSize + 1);
scnDataBufPtr = new Pointer(address);
scnDataBufPtr.put(modScnData);
} else {
scnDataBufPtr = new Pointer(0L);
}
// Set data descriptor fields
JNILibELFAPI.set_Data_d_align(scnDataPtr, align);
JNILibELFAPI.set_Data_d_buf(scnDataPtr, scnDataBufPtr);
JNILibELFAPI.set_Data_d_size(scnDataPtr, scnDataBufSize);
JNILibELFAPI.set_Data_d_off(scnDataPtr, 0);
JNILibELFAPI.set_Data_d_type(scnDataPtr, dataType.intValue());
JNILibELFAPI.set_Data_d_version(scnDataPtr, ELF.EV_CURRENT);
JNILibELFAPI.set_Shdr_sh_type(elfClass, scnHdrPtr, scnType);
JNILibELFAPI.set_Shdr_sh_flags(elfClass, scnHdrPtr, scnFlags);
JNILibELFAPI.set_Shdr_sh_entsize(elfClass, scnHdrPtr, 0); // TODO: Is this right??
JNILibELFAPI.set_Shdr_sh_link(elfClass, scnHdrPtr, scnLink);
JNILibELFAPI.set_Shdr_sh_info(elfClass, scnHdrPtr, scnInfo);
// Add hash section to section pointer list
int index = JNILibELFAPI.elf_ndxscn(scnPtr);
return index;
}
/**
* Create an ELF symbol entry for a symbol with the given properties.
*
* @param name name of the section in which symName is referenced
* @param type type of symName
* @param bind binding of symName
* @param secHdrIndex section header index of the section in which symName is referenced
* (st_shndx of ELF symbol entry)
* @param size symName size (st_size of ELF symbol entry)
* @param value symName value (st_value of ELF symbol entry)
* @param isLocal true if symbol is local.
*/
public ELFSymbol createELFSymbolEntry(String name, int type, int bind, int secHdrIndex, int size, int value, boolean isLocal) {
// Get the current symbol index and append symbol name to string table.
int index;
if (name.isEmpty()) {
index = 0;
} else {
// NOTE: The +1 comes from the null symbol!
// We can't trust strTabContent.length() since that is chars (UTF16), keep track of
// bytes on our own.
index = strTabNrOfBytes + 1;
strTabContent.append(name).append('\0');
strTabNrOfBytes += name.getBytes(StandardCharsets.UTF_8).length + 1;
}
// Create ELF symbol entry
long address = JNILibELFAPI.create_sym_entry(elfClass, index, type, bind, secHdrIndex, size, value);
if (address == 0) {
throw new InternalError("create_sym_entry failed");
}
Pointer ptr = new Pointer(address);
if (isLocal) {
final int localIndex = localSymbolIndex.size();
ELFSymbol symbol = new ELFSymbol(name, localIndex, ptr, isLocal);
localSymbolIndex.add(symbol);
return symbol;
} else {
final int globalIndex = globalSymbolIndex.size();
ELFSymbol symbol = new ELFSymbol(name, globalIndex, ptr, isLocal);
globalSymbolIndex.add(symbol);
return symbol;
}
}
/**
* Create an ELF relocation entry for given symbol {@code name} to section {@code secname}.
*
* @param container the section
* @param offset offset into the section contents at which the relocation needs to be applied
* @param type ELF type of the relocation entry
* @param addend Addend for for relocation of type reloca
*/
public void createELFRelocationEntry(ELFContainer container, int offset, int type, int addend, ELFSymbol elfSymbol) {
// Get the index of the symbol.
int index;
if (elfSymbol.isLocal()) {
index = elfSymbol.getIndex();
} else {
/*
* For global symbol entries the index will be offset by the number of local symbols
* which will be listed first in the symbol table.
*/
index = elfSymbol.getIndex() + localSymbolIndex.size();
}
long address = JNILibELFAPI.create_reloc_entry(elfClass, offset, index, type, addend, createReloca);
if (address == 0) {
throw new InternalError("create_reloc_entry failed");
}
Pointer ptr = new Pointer(address);
/*
* If section name associated with this symbol is set to undefined i.e., secname is null,
* symIndex is undef i.e., 0.
*/
if (relocTables.get(container) == null) {
// Allocate a new table and add it to the hash table of reloc tables
relocTables.put(container, new ArrayList<>());
}
// Add the entry
relocTables.get(container).add(ptr);
}
/**
* Invokes native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd).
*
* @param cmd command
* @return return value of the native function called
*/
public boolean elfUpdate(LibELF.Elf_Cmd cmd) {
JNILibELFAPI.elf_update(elfPtr, cmd.intValue());
// TODO: Error checking; look at the return value of elf_update
// and call elf_errmsg appropriately.
return true;
}
/**
* Wrapper function that invokes int elf_end (Elf *elfPtr). and closes ELF output file
* descriptor
*
* @return true
*/
public boolean elfEnd() {
// Finish ELF processing
JNILibELFAPI.elf_end(elfPtr);
// Close file descriptor
JNILibELFAPI.close(outFileDesc);
return true;
}
}

View file

@ -1,148 +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.
*
* 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.jnilibelf;
/**
* Class that abstracts ELF relocations.
*
*/
public interface JNIELFRelocation {
int R_UNDEF = -1;
/**
* x86-specific relocation types.
*
*/
public interface I386 {
/* i386 relocs. */
int R_386_NONE = 0; /* No reloc */
int R_386_32 = 1; /* Direct 32 bit */
int R_386_PC32 = 2; /* PC relative 32 bit */
int R_386_GOT32 = 3; /* 32 bit GOT entry */
int R_386_PLT32 = 4; /* 32 bit PLT address */
int R_386_COPY = 5; /* Copy symbol at runtime */
int R_386_GLOB_DAT = 6; /* Create GOT entry */
int R_386_JMP_SLOT = 7; /* Create PLT entry */
int R_386_RELATIVE = 8; /* Adjust by program base */
int R_386_GOTOFF = 9; /* 32 bit offset to GOT */
int R_386_GOTPC = 10; /* 32 bit PC relative offset to GOT */
int R_386_32PLT = 11;
int R_386_TLS_TPOFF = 14; /* Offset in static TLS block */
int R_386_TLS_IE = 15; /* Address of GOT entry for static TLS block offset */
int R_386_TLS_GOTIE = 16; /* GOT entry for static TLS block offset */
int R_386_TLS_LE = 17; /* Offset relative to static TLS block */
int R_386_TLS_GD = 18; /* Direct 32 bit for GNU version of general dynamic thread local data */
int R_386_TLS_LDM = 19; /*
* Direct 32 bit for GNU version of local dynamic thread local data
* in LE code
*/
int R_386_16 = 20;
int R_386_PC16 = 21;
int R_386_8 = 22;
int R_386_PC8 = 23;
int R_386_TLS_GD_32 = 24; /* Direct 32 bit for general dynamic thread local data */
int R_386_TLS_GD_PUSH = 25; /* Tag for pushl in GD TLS code */
int R_386_TLS_GD_CALL = 26; /* Relocation for call to __tls_get_addr() */
int R_386_TLS_GD_POP = 27; /* Tag for popl in GD TLS code */
int R_386_TLS_LDM_32 = 28; /* Direct 32 bit for local dynamic thread local data in LE code */
int R_386_TLS_LDM_PUSH = 29; /* Tag for pushl in LDM TLS code */
int R_386_TLS_LDM_CALL = 30; /* Relocation for call to __tls_get_addr() in LDM code */
int R_386_TLS_LDM_POP = 31; /* Tag for popl in LDM TLS code */
int R_386_TLS_LDO_32 = 32; /* Offset relative to TLS block */
int R_386_TLS_IE_32 = 33; /* GOT entry for negated static TLS block offset */
int R_386_TLS_LE_32 = 34; /* Negated offset relative to static TLS block */
int R_386_TLS_DTPMOD32 = 35; /* ID of module containing symbol */
int R_386_TLS_DTPOFF32 = 36; /* Offset in TLS block */
int R_386_TLS_TPOFF32 = 37; /* Negated offset in static TLS block */
int R_386_SIZE32 = 38; /* 32-bit symbol size */
int R_386_TLS_GOTDESC = 39; /* GOT offset for TLS descriptor. */
int R_386_TLS_DESC_CALL = 40; /* Marker of call through TLS descriptor for relaxation. */
int R_386_TLS_DESC = 41; /*
* TLS descriptor containing pointer to code and to argument,
* returning the TLS offset for the symbol.
*/
int R_386_IRELATIVE = 42; /* Adjust indirectly by program base */
/* Keep this the last entry. */
int R_386_NUM = 43;
}
/**
* x86_64-specific relocation types.
*/
public interface X86_64 {
/* AMD x86-64 relocations. */
int R_X86_64_NONE = 0; /* No reloc */
int R_X86_64_64 = 1; /* Direct 64 bit */
int R_X86_64_PC32 = 2; /* PC relative 32 bit signed */
int R_X86_64_GOT32 = 3; /* 32 bit GOT entry */
int R_X86_64_PLT32 = 4; /* 32 bit PLT address */
int R_X86_64_COPY = 5; /* Copy symbol at runtime */
int R_X86_64_GLOB_DAT = 6; /* Create GOT entry */
int R_X86_64_JUMP_SLOT = 7; /* Create PLT entry */
int R_X86_64_RELATIVE = 8; /* Adjust by program base */
int R_X86_64_GOTPCREL = 9; /* 32 bit signed PC relative offset to GOT */
int R_X86_64_32 = 10; /* Direct 32 bit zero extended */
int R_X86_64_32S = 11; /* Direct 32 bit sign extended */
int R_X86_64_16 = 12; /* Direct 16 bit zero extended */
int R_X86_64_PC16 = 13; /* 16 bit sign extended pc relative */
int R_X86_64_8 = 14; /* Direct 8 bit sign extended */
int R_X86_64_PC8 = 15; /* 8 bit sign extended pc relative */
int R_X86_64_DTPMOD64 = 16; /* ID of module containing symbol */
int R_X86_64_DTPOFF64 = 17; /* Offset in module's TLS block */
int R_X86_64_TPOFF64 = 18; /* Offset in initial TLS block */
int R_X86_64_TLSGD = 19; /*
* 32 bit signed PC relative offset to two GOT entries for GD
* symbol
*/
int R_X86_64_TLSLD = 20; /*
* 32 bit signed PC relative offset to two GOT entries for LD
* symbol
*/
int R_X86_64_DTPOFF32 = 21; /* Offset in TLS block */
int R_X86_64_GOTTPOFF = 22; /*
* 32 bit signed PC relative offset to GOT entry for IE symbol
*/
int R_X86_64_TPOFF32 = 23; /* Offset in initial TLS block */
int R_X86_64_PC64 = 24; /* PC relative 64 bit */
int R_X86_64_GOTOFF64 = 25; /* 64 bit offset to GOT */
int R_X86_64_GOTPC32 = 26; /* 32 bit signed pc relative offset to GOT */
int R_X86_64_GOT64 = 27; /* 64-bit GOT entry offset */
int R_X86_64_GOTPCREL64 = 28; /* 64-bit PC relative offset to GOT entry */
int R_X86_64_GOTPC64 = 29; /* 64-bit PC relative offset to GOT */
int R_X86_64_GOTPLT64 = 30; /* like GOT64, says PLT entry needed */
int R_X86_64_PLTOFF64 = 31; /* 64-bit GOT relative offset to PLT entry */
int R_X86_64_SIZE32 = 32; /* Size of symbol plus 32-bit addend */
int R_X86_64_SIZE64 = 33; /* Size of symbol plus 64-bit addend */
int R_X86_64_GOTPC32_TLSDESC = 34; /* GOT offset for TLS descriptor. */
int R_X86_64_TLSDESC_CALL = 35; /*
* Marker for call through TLS descriptor.
*/
int R_X86_64_TLSDESC = 36; /* TLS descriptor. */
int R_X86_64_IRELATIVE = 37; /* Adjust indirectly by program base */
int R_X86_64_RELATIVE64 = 38; /* 64-bit adjust by program base */
int R_X86_64_NUM = 39;
}
}

View file

@ -1,127 +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.
*
* 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.jnilibelf;
import java.nio.ByteOrder;
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
/**
* Class that abstracts ELF target details.
*
*/
public class JNIELFTargetInfo {
/**
* ELF Class of the target.
*/
private static final int elfClass;
/**
* Target architecture.
*/
private static final int arch;
/**
* Architecture endian-ness.
*/
private static final int endian;
/**
* Target OS string.
*/
private static final String osName;
static {
// Find the target arch details
String archStr = System.getProperty("os.arch").toLowerCase();
String datamodelStr = System.getProperty("sun.arch.data.model");
if (datamodelStr.equals("32")) {
elfClass = ELF.ELFCLASS32;
} else if (datamodelStr.equals("64")) {
elfClass = ELF.ELFCLASS64;
} else {
System.out.println("Failed to discover ELF class!");
elfClass = ELF.ELFCLASSNONE;
}
ByteOrder bo = ByteOrder.nativeOrder();
if (bo == ByteOrder.LITTLE_ENDIAN) {
endian = ELF.ELFDATA2LSB;
} else if (bo == ByteOrder.BIG_ENDIAN) {
endian = ELF.ELFDATA2MSB;
} else {
System.out.println("Failed to discover endian-ness!");
endian = ELF.ELFDATANONE;
}
if (archStr.equals("x86")) {
arch = ELF.EM_386;
} else if (archStr.equals("amd64") || archStr.equals("x86_64")) {
arch = ELF.EM_X64_64;
} else if (archStr.equals("sparcv9")) {
arch = ELF.EM_SPARCV9;
} else {
System.out.println("Unsupported architecture " + archStr);
arch = ELF.EM_NONE;
}
osName = System.getProperty("os.name").toLowerCase();
}
public static int getELFArch() {
return arch;
}
public static int getELFClass() {
return elfClass;
}
public static int getELFEndian() {
return endian;
}
public static String getOsName() {
return osName;
}
public static int createReloca() {
switch (arch) {
case ELF.EM_X64_64:
return 1;
default:
return 0;
}
}
public static int sizeOfSymtabEntry() {
return JNILibELFAPI.size_of_Sym(elfClass);
}
public static int sizeOfRelocEntry() {
if (createReloca() == 1) {
return JNILibELFAPI.size_of_Rela(elfClass);
} else {
return JNILibELFAPI.size_of_Rel(elfClass);
}
}
}

View file

@ -1,677 +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.
*
* 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.jnilibelf;
public class JNILibELFAPI {
static {
System.loadLibrary("jelfshim");
}
/**
* Definitions for file open.
*/
public static enum OpenFlags {
O_RDONLY(0x0),
O_WRONLY(0x1),
O_RDWR(0x2),
O_CREAT(0x40);
private final int intVal;
private OpenFlags(int v) {
intVal = v;
}
public int intValue() {
return intVal;
}
}
/**
* Definitions reflecting those in elf.h.
*
*/
public interface ELF {
int EI_NIDENT = 16;
int EI_CLASS = 4; /* File class byte index */
int ELFCLASSNONE = 0; /* Invalid class */
int ELFCLASS32 = 1; /* 32-bit objects */
int ELFCLASS64 = 2; /* 64-bit objects */
int ELFCLASSNUM = 3;
int EI_DATA = 5; /* Data encoding byte index */
int ELFDATANONE = 0; /* Invalid data encoding */
int ELFDATA2LSB = 1; /* 2's complement, little endian */
int ELFDATA2MSB = 2; /* 2's complement, big endian */
int ELFDATANUM = 3;
// Legal architecture values for e_machine (add others as needed)
int EM_NONE = 0; /* No machine */
int EM_SPARC = 2; /* SUN SPARC */
int EM_386 = 3; /* Intel 80386 */
int EM_SPARCV9 = 43; /* SPARC v9 64-bit */
int EM_X64_64 = 62; /* AMD x86-64 architecture */
/* Legal values for e_type (object file type). */
int ET_NONE = 0; /* No file type */
int ET_REL = 1; /* Relocatable file */
int ET_EXEC = 2; /* Executable file */
int ET_DYN = 3; /* Shared object file */
int ET_CORE = 4; /* Core file */
int ET_NUM = 5; /* Number of defined types */
int ET_LOOS = 0xfe00; /* OS-specific range start */
int ET_HIOS = 0xfeff; /* OS-specific range end */
int ET_LOPROC = 0xff00; /* Processor-specific range start */
int ET_HIPROC = 0xffff; /* Processor-specific range end */
/* Legal values for e_version (version). */
int EV_NONE = 0; /* Invalid ELF version */
int EV_CURRENT = 1; /* Current version */
int EV_NUM = 2;
/* Legal values for p_type (segment type). */
int PT_NULL = 0; /* Program header table entry unused */
int PT_LOAD = 1; /* Loadable program segment */
int PT_DYNAMIC = 2; /* Dynamic linking information */
int PT_INTERP = 3; /* Program interpreter */
int PT_NOTE = 4; /* Auxiliary information */
int PT_SHLIB = 5; /* Reserved */
int PT_PHDR = 6; /* Entry for header table itself */
int PT_TLS = 7; /* Thread-local storage segment */
int PT_NUM = 8; /* Number of defined types */
int PT_LOOS = 0x60000000; /* Start of OS-specific */
int PT_GNU_EH_FRAME = 0x6474e550; /* GCC .eh_frame_hdr segment */
int PT_GNU_STACK = 0x6474e551; /* Indicates stack executability */
int PT_GNU_RELRO = 0x6474e552; /* Read-only after relocation */
int PT_LOSUNW = 0x6ffffffa;
int PT_SUNWBSS = 0x6ffffffa; /* Sun Specific segment */
int PT_SUNWSTACK = 0x6ffffffb; /* Stack segment */
int PT_HISUNW = 0x6fffffff;
int PT_HIOS = 0x6fffffff; /* End of OS-specific */
int PT_LOPROC = 0x70000000; /* Start of processor-specific */
int PT_HIPROC = 0x7fffffff; /* End of processor-specific */
/* Special section indices. */
int SHN_UNDEF = 0; /* Undefined section */
int SHN_LORESERVE = 0xff00; /* Start of reserved indices */
int SHN_LOPROC = 0xff00; /* Start of processor-specific */
int SHN_BEFORE = 0xff00; /* Order section before all others (Solaris). */
int SHN_AFTER = 0xff01; /* Order section after all others (Solaris). */
int SHN_HIPROC = 0xff1f; /* End of processor-specific */
int SHN_LOOS = 0xff20; /* Start of OS-specific */
int SHN_HIOS = 0xff3f; /* End of OS-specific */
int SHN_ABS = 0xfff1; /* Associated symbol is absolute */
int SHN_COMMON = 0xfff2; /* Associated symbol is common */
int SHN_XINDEX = 0xffff; /* Index is in extra table. */
int SHN_HIRESERVE = 0xffff; /* End of reserved indices */
/* Legal values for sh_type (section type). */
int SHT_NULL = 0; /* Section header table entry unused */
int SHT_PROGBITS = 1; /* Program data */
int SHT_SYMTAB = 2; /* Symbol table */
int SHT_STRTAB = 3; /* String table */
int SHT_RELA = 4; /* Relocation entries with addends */
int SHT_HASH = 5; /* Symbol hash table */
int SHT_DYNAMIC = 6; /* Dynamic linking information */
int SHT_NOTE = 7; /* Notes */
int SHT_NOBITS = 8; /* Program space with no data (bss) */
int SHT_REL = 9; /* Relocation entries, no addends */
int SHT_SHLIB = 10; /* Reserved */
int SHT_DYNSYM = 11; /* Dynamic linker symbol table */
int SHT_INIT_ARRAY = 14; /* Array of constructors */
int SHT_FINI_ARRAY = 15; /* Array of destructors */
int SHT_PREINIT_ARRAY = 16; /* Array of pre-constructors */
int SHT_GROUP = 17; /* Section group */
int SHT_SYMTAB_SHNDX = 18; /* Extended section indeces */
int SHT_NUM = 19; /* Number of defined types. */
int SHT_LOOS = 0x60000000; /* Start OS-specific. */
int SHT_GNU_ATTRIBUTES = 0x6ffffff5; /* Object attributes. */
int SHT_GNU_HASH = 0x6ffffff6; /* GNU-style hash table. */
int SHT_GNU_LIBLIST = 0x6ffffff7; /* Prelink library list */
int SHT_CHECKSUM = 0x6ffffff8; /* Checksum for DSO content. */
int SHT_LOSUNW = 0x6ffffffa; /* Sun-specific low bound. */
int SHT_SUNW_move = 0x6ffffffa;
int SHT_SUNW_COMDAT = 0x6ffffffb;
int SHT_SUNW_syminfo = 0x6ffffffc;
int SHT_GNU_verdef = 0x6ffffffd; /* Version definition section. */
int SHT_GNU_verneed = 0x6ffffffe; /* Version needs section. */
int SHT_GNU_versym = 0x6fffffff; /* Version symbol table. */
int SHT_HISUNW = 0x6fffffff; /* Sun-specific high bound. */
int SHT_HIOS = 0x6fffffff; /* End OS-specific type */
int SHT_LOPROC = 0x70000000; /* Start of processor-specific */
int SHT_HIPROC = 0x7fffffff; /* End of processor-specific */
int SHT_LOUSER = 0x80000000; /* Start of application-specific */
int SHT_HIUSER = 0x8fffffff; /* End of application-specific */
/* Legal values for sh_flags (section flags). */
int SHF_WRITE = (1 << 0); /* Writable */
int SHF_ALLOC = (1 << 1); /* Occupies memory during execution */
int SHF_EXECINSTR = (1 << 2); /* Executable */
int SHF_MERGE = (1 << 4); /* Might be merged */
int SHF_STRINGS = (1 << 5); /* Contains nul-terminated strings */
int SHF_INFO_LINK = (1 << 6); /* `sh_info' contains SHT index */
int SHF_LINK_ORDER = (1 << 7); /* Preserve order after combining */
int SHF_OS_NONCONFORMING = (1 << 8); /* Non-standard OS specific handling required */
int SHF_GROUP = (1 << 9); /* Section is member of a group. */
int SHF_TLS = (1 << 10); /* Section hold thread-local data. */
int SHF_MASKOS = 0x0ff00000; /* OS-specific. */
int SHF_MASKPROC = 0xf0000000; /* Processor-specific */
int SHF_ORDERED = (1 << 30); /* Special ordering requirement (Solaris). */
int SHF_EXCLUDE = (1 << 31); /*
* Section is excluded unless referenced or allocated
* (Solaris).
*/
/* Legal values for ST_BIND subfield of st_info (symbol binding). */
int STB_LOCAL = 0; /* Local symbol */
int STB_GLOBAL = 1; /* Global symbol */
int STB_WEAK = 2; /* Weak symbol */
int STB_NUM = 3; /* Number of defined types. */
int STB_LOOS = 10; /* Start of OS-specific */
int STB_GNU_UNIQUE = 10; /* Unique symbol. */
int STB_HIOS = 12; /* End of OS-specific */
int STB_LOPROC = 13; /* Start of processor-specific */
int STB_HIPROC = 15; /* End of processor-specific */
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
int STT_NOTYPE = 0; /* Symbol type is unspecified */
int STT_OBJECT = 1; /* Symbol is a data object */
int STT_FUNC = 2; /* Symbol is a code object */
int STT_SECTION = 3; /* Symbol associated with a section */
int STT_FILE = 4; /* Symbol's name is file name */
int STT_COMMON = 5; /* Symbol is a common data object */
int STT_TLS = 6; /* Symbol is thread-local data object */
int STT_NUM = 7; /* Number of defined types. */
int STT_LOOS = 10; /* Start of OS-specific */
int STT_GNU_IFUNC = 10; /* Symbol is indirect code object */
int STT_HIOS = 12; /* End of OS-specific */
int STT_LOPROC = 13; /* Start of processor-specific */
int STT_HIPROC = 15; /* End of processor-specific */
}
/**
* Definitions reflecting those in libelf.h.
*
*/
public interface LibELF {
public static enum Elf_Cmd {
ELF_C_NULL("NULL"), /* Nothing, terminate, or compute only. */
ELF_C_READ("READ"), /* Read .. */
ELF_C_RDWR("RDWR"), /* Read and write .. */
ELF_C_WRITE("WRITE"), /* Write .. */
ELF_C_CLR("CLR"), /* Clear flag. */
ELF_C_SET("SET"), /* Set flag. */
ELF_C_FDDONE("FDDONE"), /*
* Signal that file descriptor will not be used anymore.
*/
ELF_C_FDREAD("FDREAD"), /*
* Read rest of data so that file descriptor is not used
* anymore.
*/
/* The following are Linux-only extensions. */
ELF_C_READ_MMAP("READ_MMAP"), /* Read, but mmap the file if possible. */
ELF_C_RDWR_MMAP("RDWR_MMAP"), /* Read and write, with mmap. */
ELF_C_WRITE_MMAP("WRITE_MMAP"), /* Write, with mmap. */
ELF_C_READ_MMAP_PRIVATE("READ_MMAP_PRIVATE"), /*
* Read, but memory is writable, results
* are not written to the file.
*/
ELF_C_EMPTY("EMPTY"), /* Copy basic file data but not the content. */
/* The following are SunOS-only enums */
ELF_C_WRIMAGE("WRIMAGE"),
ELF_C_IMAGE("IMAGE"),
/* Common last entry. */
ELF_C_NUM("NUM");
private final int intVal;
private final String name;
private Elf_Cmd(String cmd) {
name = "ELF_C_" + cmd;
switch (cmd) {
case "NULL":
// ELF_C_NULL has the same enum ordinal on both Linux and SunOS
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NULL.ordinal();
break;
case "READ":
// ELF_C_READ has the same enum ordinal on both Linux and SunOS
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ.ordinal();
break;
// Enums defined in libelf.h of both Linux and SunOS
// but with different ordinals
case "RDWR":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR.ordinal();
} else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_RDWR.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "WRITE":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE.ordinal();
} else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRITE.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "CLR":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_CLR.ordinal();
} else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_CLR.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "SET":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_SET.ordinal();
} else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_SET.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "FDDONE":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDDONE.ordinal();
} else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDDONE.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "FDREAD":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDREAD.ordinal();
} else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDREAD.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "NUM":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NUM.ordinal();
} else if (JNIELFTargetInfo.getOsName().equals("sunos")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_NUM.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
// Linux-only Elf_Cmd enums
case "READ_MMAP":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "RDWR_MMAP":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR_MMAP.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "WRITE_MMAP":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE_MMAP.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "READ_MMAP_PRIVATE":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP_PRIVATE.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "EMPTY":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_EMPTY.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
// SunOS-only Elf_Cmd enums
case "WRIMAGE":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRIMAGE.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
case "IMAGE":
if (JNIELFTargetInfo.getOsName().equals("linux")) {
intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_IMAGE.ordinal();
} else {
// Unsupported platform
intVal = -1;
}
break;
default:
intVal = -1;
}
}
public int intValue() {
assert intVal != -1 : "enum " + name + "not supported on " + JNIELFTargetInfo.getOsName();
return intVal;
}
public String getName() {
return name;
}
}
public static enum Elf_Type {
ELF_T_BYTE(0), /* unsigned char */
ELF_T_ADDR(1), /* Elf32_Addr, Elf64_Addr, ... */
ELF_T_DYN(2), /* Dynamic section record. */
ELF_T_EHDR(3), /* ELF header. */
ELF_T_HALF(4), /* Elf32_Half, Elf64_Half, ... */
ELF_T_OFF(5), /* Elf32_Off, Elf64_Off, ... */
ELF_T_PHDR(6), /* Program header. */
ELF_T_RELA(7), /* Relocation entry with addend. */
ELF_T_REL(8), /* Relocation entry. */
ELF_T_SHDR(9), /* Section header. */
ELF_T_SWORD(10), /* Elf32_Sword, Elf64_Sword, ... */
ELF_T_SYM(11), /* Symbol record. */
ELF_T_WORD(12), /* Elf32_Word, Elf64_Word, ... */
ELF_T_XWORD(13), /* Elf32_Xword, Elf64_Xword, ... */
ELF_T_SXWORD(14), /* Elf32_Sxword, Elf64_Sxword, ... */
ELF_T_VDEF(15), /* Elf32_Verdef, Elf64_Verdef, ... */
ELF_T_VDAUX(16), /* Elf32_Verdaux, Elf64_Verdaux, ... */
ELF_T_VNEED(17), /* Elf32_Verneed, Elf64_Verneed, ... */
ELF_T_VNAUX(18), /* Elf32_Vernaux, Elf64_Vernaux, ... */
ELF_T_NHDR(19), /* Elf32_Nhdr, Elf64_Nhdr, ... */
ELF_T_SYMINFO(20), /* Elf32_Syminfo, Elf64_Syminfo, ... */
ELF_T_MOVE(21), /* Elf32_Move, Elf64_Move, ... */
ELF_T_LIB(22), /* Elf32_Lib, Elf64_Lib, ... */
ELF_T_GNUHASH(23), /* GNU-style hash section. */
ELF_T_AUXV(24), /* Elf32_auxv_t, Elf64_auxv_t, ... */
/* Keep this the last entry. */
ELF_T_NUM(25);
private final int intVal;
private Elf_Type(int v) {
intVal = v;
}
public int intValue() {
return intVal;
}
}
/* Flags for the ELF structures. */
int ELF_F_DIRTY = 0x1;
int ELF_F_LAYOUT = 0x4;
int ELF_F_PERMISSIVE = 0x8;
public static enum Elf_Kind {
ELF_K_NONE(0), /* Unknown. */
ELF_K_AR(1), /* Archive. */
ELF_K_COFF(2), /* Stupid old COFF. */
ELF_K_ELF(3), /* ELF file. */
/* Keep this the last entry. */
ELF_K_NUM(4);
private final int intVal;
private Elf_Kind(int v) {
intVal = v;
}
public int intValue() {
return intVal;
}
}
}
/**
* Invoke native libelf function unsigned int elf_version (unsigned int v).
*
* @param v version
* @return return value of native call
*/
// Checkstyle: stop method name check
static native int elf_version(int v);
/**
* Return version recorded in libelfshim.
*
* @return return version string
*/
// Checkstyle: stop method name check
static native String elfshim_version();
/**
* Invoke native libelf function Elf *elf_begin (int fildes, Elf_Cmd cmd, Elf *elfPtr).
*
* @param fildes open file descriptor
* @param elfCRead command
* @param elfHdrPtr pointer to ELF header
* @return return value of native call
*/
static native Pointer elf_begin(int fildes, int elfCRead, Pointer elfHdrPtr);
/**
* Invoke native libelf function elf_end (Elf *elfPtr).
*
* @param elfPtr pointer to ELF header
* @return return value of native call
*/
static native int elf_end(Pointer elfPtr);
/**
* Invoke native libelf function elf_end (Elf *elfPtr).
*
* @param elfPtr pointer to ELF header
* @return return value of native call
*/
static native int elf_kind(Pointer elfPtr);
/**
* Invoke native libelf function unsigned int elf_flagphdr (Elf *elf, Elf_Cmd cmd, unsigned int
* flags).
*
* @param elfPtr Pointer to ELF descriptor
* @param cmd command
* @param flags flags
* @return return value of native call
*/
static native int elf_flagphdr(Pointer elfPtr, int cmd, int flags);
/**
* Invoke native libelf function Elf_Scn *elf_newscn (Elf *elfPtr).
*
* @param elfPtr Elf header pointer
* @return return value of native call
*/
static native Pointer elf_newscn(Pointer elfPtr);
/**
* Invoke native libelf function Elf_Data *elf_newdata (Elf_Scn *scn).
*
* @param scnPtr pointer to section for which the new data descriptor is to be created
* @return return value of native call
*/
static native Pointer elf_newdata(Pointer scnPtr);
/**
* Invoke native libelf function Elf64_Shdr *elf64_getshdr (Elf_Scn *scnPtr).
*
* @param scnPtr pointer to section whose header information is to be retrieved
* @return return value of native call
*/
static native Pointer elf64_getshdr(Pointer scnPtr);
/**
* Invoke native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd).
*
* @param elfPtr Pointer to ELF descriptor
* @param cmd command
* @return return value of native call
*/
static native long elf_update(Pointer elfPtr, int cmd);
/**
* Invoke native libelf function char *elf_errmsg (int error).
*
* @param error error
* @return return value of native call
*/
static native String elf_errmsg(int error);
/**
* Invoke native libelf function size_t elf_ndxscn (Elf_Scn *scn).
*
* @param scn section pointer
* @return return value of native call
*/
static native int elf_ndxscn(Pointer scn);
/**
* GELF interfaces
*/
/**
* Invoke native libelf function unsigned long int gelf_newehdr (Elf *elf, int elfClass).
*
* @param elf ELF Header pointer
* @param elfclass ELF class
* @return return value of native call boxed as a pointer
*/
static native Pointer gelf_newehdr(Pointer elf, int elfclass);
/**
* Invoke native libelf function unsigned long int gelf_newphdr (Elf *elf, size_t phnum).
*
* @param elf ELF header pointer
* @param phnum number of program headers
* @return return value of native call boxed as a pointer
*/
static native Pointer gelf_newphdr(Pointer elf, int phnum);
/**
* Miscellaneous convenience native methods that help peek and poke ELF data structures.
*/
static native int size_of_Sym(int elfClass);
static native int size_of_Rela(int elfClass);
static native int size_of_Rel(int elfClass);
static native void ehdr_set_data_encoding(Pointer ehdr, int val);
static native void set_Ehdr_e_machine(int elfclass, Pointer structPtr, int val);
static native void set_Ehdr_e_type(int elfclass, Pointer structPtr, int val);
static native void set_Ehdr_e_version(int elfclass, Pointer structPtr, int val);
static native void set_Ehdr_e_shstrndx(int elfclass, Pointer structPtr, int val);
static native void phdr_set_type_self(int elfclass, Pointer ehdr, Pointer phdr);
static native void set_Shdr_sh_name(int elfclass, Pointer structPtr, int val);
static native void set_Shdr_sh_type(int elfclass, Pointer structPtr, int val);
static native void set_Shdr_sh_flags(int elfclass, Pointer structPtr, int val);
static native void set_Shdr_sh_entsize(int elfclass, Pointer structPtr, int val);
static native void set_Shdr_sh_link(int elfclass, Pointer structPtr, int val);
static native void set_Shdr_sh_info(int elfclass, Pointer structPtr, int val);
static native void set_Data_d_align(Pointer structPtr, int val);
static native void set_Data_d_off(Pointer structPtr, int val);
static native void set_Data_d_buf(Pointer structPtr, Pointer val);
static native void set_Data_d_type(Pointer structPtr, int val);
static native void set_Data_d_size(Pointer structPtr, int val);
static native void set_Data_d_version(Pointer structPtr, int val);
static native long create_sym_entry(int elfclass, int index, int type, int bind, int shndx, int size, int value);
static native long create_reloc_entry(int elfclass, int roffset, int symtabIdx, int relocType, int raddend, int reloca);
/**
* File Operations.
*/
static native int open_rw(String fileName);
static native int open(String fileName, int flags);
static native int open(String fileName, int flags, int mode);
static native int close(int fd);
// Checkstyle: resume method name check
}

View file

@ -1,72 +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.
*
* 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.jnilibelf;
import jdk.internal.misc.Unsafe;
import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE;
public class Pointer {
private final long address;
public Pointer(long val) {
address = val;
}
/**
* Put (i.e., copy) content of byte array at consecutive addresses beginning at this Pointer.
*
* @param src source byte array
*/
public void put(byte[] src) {
UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length);
}
/**
* Get (i.e., copy) content at this Pointer to the given byte array.
*
* @param dst destination byte array
*/
public void get(byte[] dst) {
UNSAFE.copyMemory(null, address, dst, Unsafe.ARRAY_BYTE_BASE_OFFSET, dst.length);
}
/**
* Read {@code readSize} number of bytes to copy them starting at {@code startIndex} of
* {@code byteArray}
*
* @param byteArray target array to copy bytes
* @param readSize number of bytes to copy
* @param startIndex index of the array to start copy at
*/
public void copyBytesTo(byte[] byteArray, int readSize, int startIndex) {
long end = (long)startIndex + (long)readSize;
if (end > byteArray.length) {
throw new IllegalArgumentException("writing beyond array bounds");
}
UNSAFE.copyMemory(null, address, byteArray, Unsafe.ARRAY_BYTE_BASE_OFFSET+startIndex, readSize);
}
}

View file

@ -1,80 +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.
*
* 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.jnilibelf.linux;
/**
* Represent Elf_Cmd enums defined in libelf.h on Linux as they slightly different from libelf.h on
* SunOS.
*/
public enum Elf_Cmd {
/** Nothing, terminate, or compute only. */
ELF_C_NULL,
/** Read. */
ELF_C_READ,
/** Read and write. */
ELF_C_RDWR,
/** Write. */
ELF_C_WRITE,
/** Clear flag. */
ELF_C_CLR,
/** Set flag. */
ELF_C_SET,
/**
* Signal that file descriptor will not be used anymore.
*/
ELF_C_FDDONE,
/**
* Read rest of data so that file descriptor is not used anymore.
*/
ELF_C_FDREAD,
/* The following are extensions. */
/** Read, but mmap the file if possible. */
ELF_C_READ_MMAP,
/** Read and write, with mmap. */
ELF_C_RDWR_MMAP,
/** Write, with mmap. */
ELF_C_WRITE_MMAP,
/**
* Read, but memory is writable, results are not written to the file.
*/
ELF_C_READ_MMAP_PRIVATE,
/** Copy basic file data but not the content. */
ELF_C_EMPTY,
/** Keep this the last entry. */
ELF_C_NUM;
}

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