mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-28 16:50:10 +00:00
Merge
This commit is contained in:
commit
929fc23c45
@ -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
|
||||
|
||||
##############################################################################
|
||||
@ -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.
|
||||
*
|
||||
* 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
|
||||
Handle obj = HotSpotObjectConstantImpl::object(constant);
|
||||
Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
|
||||
jobject value = JNIHandles::make_local(obj());
|
||||
MacroAssembler::patch_oop(pc, (address)obj());
|
||||
int oop_index = _oop_recorder->find_index(value);
|
||||
|
||||
@ -402,14 +402,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(
|
||||
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 entry = __ pc();
|
||||
|
||||
|
||||
@ -270,12 +270,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch
|
||||
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 entry = __ pc();
|
||||
|
||||
|
||||
@ -646,12 +646,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch
|
||||
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.
|
||||
// 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) {
|
||||
|
||||
@ -28,8 +28,6 @@
|
||||
|
||||
#undef LUCY_DBG
|
||||
|
||||
#define NearLabel Label
|
||||
|
||||
// Immediate is an abstraction to represent the various immediate
|
||||
// operands which exist on z/Architecture. Neither this class nor
|
||||
// instances hereof have an own state. It consists of methods only.
|
||||
|
||||
@ -1616,6 +1616,8 @@ void MacroAssembler::branch_optimized(Assembler::branch_condition cond, Label& b
|
||||
if (branch_target.is_bound()) {
|
||||
address branch_addr = target(branch_target);
|
||||
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 {
|
||||
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) {
|
||||
address branch_origin = pc();
|
||||
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));
|
||||
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,
|
||||
bool len64,
|
||||
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()) {
|
||||
address branch_addr = target(branch_target);
|
||||
compare_and_branch_optimized(r1, r2, cond, branch_addr, len64, has_sign);
|
||||
} 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) {
|
||||
case 0: z_cr( 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 {");
|
||||
|
||||
// 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()));
|
||||
|
||||
// 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,
|
||||
vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(),
|
||||
|
||||
@ -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" %}
|
||||
ins_encode %{
|
||||
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);
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
@ -6841,6 +6842,7 @@ instruct sraI_reg_imm(iRegI dst, immI src, flagsReg cr) %{
|
||||
format %{ "SRA $dst,$src" %}
|
||||
ins_encode %{
|
||||
int Nbit = $src$$constant;
|
||||
assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph");
|
||||
__ z_sra($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0);
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
@ -6893,6 +6895,7 @@ instruct srlI_reg_imm(iRegI dst, immI src) %{
|
||||
format %{ "SRL $dst,$src" %}
|
||||
ins_encode %{
|
||||
int Nbit = $src$$constant;
|
||||
assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph");
|
||||
__ z_srl($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0);
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
|
||||
@ -623,26 +623,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#define __ (Verbose ? (_masm->block_comment(FILE_AND_LINE),_masm):_masm)->
|
||||
#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
|
||||
// sub, Klass super);
|
||||
//
|
||||
@ -2461,8 +2441,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_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).
|
||||
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();
|
||||
|
||||
|
||||
@ -33,8 +33,6 @@
|
||||
// Implementation of the platform-specific part of StubRoutines - for
|
||||
// a description of how to extend it, see the stubRoutines.hpp file.
|
||||
|
||||
address StubRoutines::zarch::_handler_for_unsafe_access_entry = NULL;
|
||||
|
||||
address StubRoutines::zarch::_partial_subtype_check = NULL;
|
||||
|
||||
// Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction.
|
||||
|
||||
@ -68,8 +68,6 @@ class zarch {
|
||||
};
|
||||
|
||||
private:
|
||||
static address _handler_for_unsafe_access_entry;
|
||||
|
||||
static int _atomic_memory_operation_lock;
|
||||
|
||||
static address _partial_subtype_check;
|
||||
@ -91,8 +89,6 @@ class zarch {
|
||||
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 address handler_for_unsafe_access_entry() { return _handler_for_unsafe_access_entry; }
|
||||
|
||||
static address partial_subtype_check() { return _partial_subtype_check; }
|
||||
|
||||
static void generate_load_crc_table_addr(MacroAssembler* masm, Register table);
|
||||
|
||||
@ -642,13 +642,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch
|
||||
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 entry = __ pc();
|
||||
|
||||
|
||||
@ -3466,7 +3466,7 @@ void TemplateTable::invokevirtual_helper(Register index,
|
||||
__ z_sllg(index, index, exact_log2(vtableEntry::size_in_bytes()));
|
||||
__ mem2reg_opt(method,
|
||||
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);
|
||||
__ jump_from_interpreted(method, Z_ARG4);
|
||||
BLOCK_COMMENT("} invokevirtual_helper");
|
||||
|
||||
@ -83,7 +83,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
__ load_klass(rcvr_klass, Z_ARG1);
|
||||
|
||||
// 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();
|
||||
|
||||
#ifndef PRODUCT
|
||||
@ -96,8 +96,8 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
// worst case actual size
|
||||
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");
|
||||
__ z_cl(vtable_idx, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass);
|
||||
assert(Immediate::is_uimm12(in_bytes(Klass::vtable_length_offset())), "disp to large");
|
||||
__ z_cl(vtable_idx, in_bytes(Klass::vtable_length_offset()), rcvr_klass);
|
||||
__ z_brl(L);
|
||||
__ 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);
|
||||
@ -187,11 +187,11 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||
__ load_klass(rcvr_klass, Z_ARG1);
|
||||
|
||||
// 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()));
|
||||
|
||||
// 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.
|
||||
start_pc = __ pc();
|
||||
__ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len);
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* 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) {
|
||||
address pc = _instructions->start() + pc_offset;
|
||||
Handle obj = HotSpotObjectConstantImpl::object(constant);
|
||||
Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
|
||||
jobject value = JNIHandles::make_local(obj());
|
||||
if (HotSpotObjectConstantImpl::compressed(constant)) {
|
||||
#ifdef _LP64
|
||||
|
||||
@ -466,12 +466,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.
|
||||
//
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,6 +21,8 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "aot/compiledIC_aot.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* 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) {
|
||||
address pc = _instructions->start() + pc_offset;
|
||||
Handle obj = HotSpotObjectConstantImpl::object(constant);
|
||||
Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
|
||||
jobject value = JNIHandles::make_local(obj());
|
||||
if (HotSpotObjectConstantImpl::compressed(constant)) {
|
||||
#ifdef _LP64
|
||||
|
||||
@ -171,16 +171,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(
|
||||
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 entry = __ pc();
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,6 +36,8 @@ import java.util.Map;
|
||||
import jdk.tools.jaotc.binformat.Symbol.Binding;
|
||||
import jdk.tools.jaotc.binformat.Symbol.Kind;
|
||||
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.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
|
||||
@ -44,7 +46,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
@ -264,29 +266,29 @@ public class BinaryContainer implements SymbolTable {
|
||||
|
||||
// read only, code
|
||||
codeContainer = new CodeContainer(".text", this);
|
||||
extLinkageContainer = new CodeContainer(".hotspot.linkage.plt", this);
|
||||
extLinkageContainer = new CodeContainer(".hs.plt.linkage", this);
|
||||
|
||||
// read only, info
|
||||
configContainer = new ReadOnlyDataContainer(".config", this);
|
||||
metaspaceNamesContainer = new ReadOnlyDataContainer(".metaspace.names", this);
|
||||
metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this);
|
||||
methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this);
|
||||
klassesOffsetsContainer = new ReadOnlyDataContainer(".klasses.offsets", this);
|
||||
klassesDependenciesContainer = new ReadOnlyDataContainer(".klasses.dependencies", this);
|
||||
klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this);
|
||||
klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this);
|
||||
|
||||
headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
|
||||
stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this);
|
||||
codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this);
|
||||
constantDataContainer = new ReadOnlyDataContainer(".method.constdata", this);
|
||||
constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this);
|
||||
|
||||
// needs relocation patching at load time by the loader
|
||||
methodMetadataContainer = new ReadOnlyDataContainer(".method.metadata", this);
|
||||
methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this);
|
||||
|
||||
// writable sections
|
||||
metaspaceGotContainer = new ByteContainer(".metaspace.got", this);
|
||||
metaspaceGotContainer = new ByteContainer(".meta.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);
|
||||
extLinkageGOTContainer = new ByteContainer(".hotspot.linkage.got", this);
|
||||
extLinkageGOTContainer = new ByteContainer(".hs.got.linkage", this);
|
||||
|
||||
addGlobalSymbols();
|
||||
|
||||
@ -497,11 +499,21 @@ public class BinaryContainer implements SymbolTable {
|
||||
switch (osName) {
|
||||
case "Linux":
|
||||
case "SunOS":
|
||||
JELFRelocObject elfso = new JELFRelocObject(this, outputFileName, aotVersion);
|
||||
elfso.createELFRelocObject(relocationTable, symbolTable.values());
|
||||
JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName, aotVersion);
|
||||
elfobj.createELFRelocObject(relocationTable, symbolTable.values());
|
||||
break;
|
||||
case "Mac OS X":
|
||||
JMachORelocObject machobj = new JMachORelocObject(this, outputFileName);
|
||||
machobj.createMachORelocObject(relocationTable, symbolTable.values());
|
||||
break;
|
||||
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 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) {
|
||||
// Get the current length of the metaspaceNameContainer
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat;
|
||||
|
||||
import jdk.tools.jaotc.binformat.Symbol.Binding;
|
||||
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.nio.ByteBuffer;
|
||||
@ -41,7 +41,7 @@ import java.util.Arrays;
|
||||
* The method {@code putIntAt} updates the content of {@code contentBytes}. Changes are not
|
||||
* reflected in {@code contentStream}.
|
||||
*/
|
||||
public class ByteContainer implements ELFContainer {
|
||||
public class ByteContainer implements Container {
|
||||
/**
|
||||
* {@code ByteBuffer} representation of {@code BinaryContainer}.
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,9 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.tools.jaotc.jnilibelf;
|
||||
package jdk.tools.jaotc.binformat;
|
||||
|
||||
public interface ELFContainer {
|
||||
public interface Container {
|
||||
|
||||
String getContainerName();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,27 +21,31 @@
|
||||
* 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
|
||||
* Linux.
|
||||
* This class represents ia native OS specific Symbol
|
||||
*/
|
||||
public enum Elf_Cmd {
|
||||
/** Must be first, 0. */
|
||||
ELF_C_NULL,
|
||||
public abstract class NativeSymbol {
|
||||
|
||||
ELF_C_READ,
|
||||
ELF_C_WRITE,
|
||||
ELF_C_CLR,
|
||||
ELF_C_SET,
|
||||
ELF_C_FDDONE,
|
||||
ELF_C_FDREAD,
|
||||
ELF_C_RDWR,
|
||||
ELF_C_WRIMAGE,
|
||||
ELF_C_IMAGE,
|
||||
/** String table index. */
|
||||
private int index;
|
||||
|
||||
/** Must be last. */
|
||||
ELF_C_NUM
|
||||
public NativeSymbol(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @index
|
||||
*/
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.tools.jaotc.jnilibelf.ELFSymbol;
|
||||
import jdk.tools.jaotc.binformat.NativeSymbol;
|
||||
|
||||
public class Symbol {
|
||||
|
||||
@ -51,7 +51,7 @@ public class Symbol {
|
||||
private final Kind kind;
|
||||
|
||||
private ByteContainer section;
|
||||
private ELFSymbol elfSymbol;
|
||||
private NativeSymbol nativeSymbol;
|
||||
|
||||
/**
|
||||
* Create symbol info.
|
||||
@ -77,12 +77,12 @@ public class Symbol {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ELFSymbol getElfSymbol() {
|
||||
return elfSymbol;
|
||||
public NativeSymbol getNativeSymbol() {
|
||||
return nativeSymbol;
|
||||
}
|
||||
|
||||
public void setElfSymbol(ELFSymbol elfSymbol) {
|
||||
this.elfSymbol = elfSymbol;
|
||||
public void setNativeSymbol(NativeSymbol nativeSym) {
|
||||
this.nativeSymbol = nativeSym;
|
||||
}
|
||||
|
||||
public Binding getBinding() {
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,6 +30,7 @@ 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;
|
||||
@ -37,36 +38,60 @@ 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.jnilibelf.ELFContainer;
|
||||
import jdk.tools.jaotc.jnilibelf.ELFSymbol;
|
||||
import jdk.tools.jaotc.jnilibelf.JNIELFContainer;
|
||||
import jdk.tools.jaotc.jnilibelf.JNIELFRelocation;
|
||||
import jdk.tools.jaotc.jnilibelf.JNIELFTargetInfo;
|
||||
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
|
||||
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd;
|
||||
import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type;
|
||||
import jdk.tools.jaotc.jnilibelf.Pointer;
|
||||
|
||||
import jdk.tools.jaotc.binformat.elf.Elf;
|
||||
import jdk.tools.jaotc.binformat.elf.ElfSymbol;
|
||||
import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
|
||||
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
|
||||
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
|
||||
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
|
||||
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel;
|
||||
import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
|
||||
|
||||
public class JELFRelocObject {
|
||||
|
||||
private final BinaryContainer binContainer;
|
||||
|
||||
private final JNIELFContainer elfContainer;
|
||||
private final ElfContainer elfContainer;
|
||||
|
||||
private final int segmentSize;
|
||||
|
||||
public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
|
||||
this.binContainer = binContainer;
|
||||
this.elfContainer = new JNIELFContainer(outputFileName, aotVersion);
|
||||
this.elfContainer = new ElfContainer(outputFileName, aotVersion);
|
||||
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();
|
||||
int scnType = ELF.SHT_PROGBITS;
|
||||
boolean zeros = !c.hasRelocations();
|
||||
|
||||
int scnType = Elf64_Shdr.SHT_PROGBITS;
|
||||
boolean zeros = hasRelocs;
|
||||
if (zeros) {
|
||||
for (byte b : scnData) {
|
||||
if (b != 0) {
|
||||
@ -75,30 +100,30 @@ public class JELFRelocObject {
|
||||
}
|
||||
}
|
||||
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);
|
||||
c.setSectionId(sectionId);
|
||||
// Clear out code section data to allow for GC
|
||||
c.clear();
|
||||
sect = createByteSection(sections, c.getContainerName(),
|
||||
scnData, hasRelocs,
|
||||
scnFlags, scnType);
|
||||
c.setSectionId(sect.getSectionId());
|
||||
}
|
||||
|
||||
private void createCodeSection(CodeContainer c) {
|
||||
createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_EXECINSTR);
|
||||
private void createCodeSection(ArrayList<ElfSection>sections, CodeContainer c) {
|
||||
createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR);
|
||||
}
|
||||
|
||||
private void createReadOnlySection(ReadOnlyDataContainer c) {
|
||||
createByteSection(c, ELF.SHF_ALLOC);
|
||||
private void createReadOnlySection(ArrayList<ElfSection>sections, ReadOnlyDataContainer c) {
|
||||
createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC);
|
||||
}
|
||||
|
||||
private void createReadWriteSection(ByteContainer c) {
|
||||
createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_WRITE);
|
||||
private void createReadWriteSection(ArrayList<ElfSection>sections, ByteContainer c) {
|
||||
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 symbols
|
||||
@ -106,145 +131,171 @@ public class JELFRelocObject {
|
||||
*/
|
||||
public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
|
||||
// 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
|
||||
createCodeSection(binContainer.getCodeContainer());
|
||||
createReadOnlySection(binContainer.getMetaspaceNamesContainer());
|
||||
createReadOnlySection(binContainer.getKlassesOffsetsContainer());
|
||||
createReadOnlySection(binContainer.getMethodsOffsetsContainer());
|
||||
createReadOnlySection(binContainer.getKlassesDependenciesContainer());
|
||||
createReadWriteSection(binContainer.getMetaspaceGotContainer());
|
||||
createReadWriteSection(binContainer.getMetadataGotContainer());
|
||||
createReadWriteSection(binContainer.getMethodStateContainer());
|
||||
createReadWriteSection(binContainer.getOopGotContainer());
|
||||
createReadWriteSection(binContainer.getMethodMetadataContainer());
|
||||
createReadOnlySection(binContainer.getStubsOffsetsContainer());
|
||||
createReadOnlySection(binContainer.getHeaderContainer().getContainer());
|
||||
createReadOnlySection(binContainer.getCodeSegmentsContainer());
|
||||
createReadOnlySection(binContainer.getConstantDataContainer());
|
||||
createReadOnlySection(binContainer.getConfigContainer());
|
||||
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(binContainer.getExtLinkageContainer());
|
||||
createReadWriteSection(binContainer.getExtLinkageGOTContainer());
|
||||
createCodeSection(sections, binContainer.getExtLinkageContainer());
|
||||
createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
|
||||
|
||||
// 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
|
||||
// that order since symtab section needs to set the index of strtab in sh_link field
|
||||
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);
|
||||
// that order since symtab section needs to set the index of
|
||||
// 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
|
||||
// contains the index of string table its symbols reference and
|
||||
// sh_info contains the index of first non-local symbol
|
||||
int scnInfo = elfContainer.getFirstNonLocalSymbolIndex();
|
||||
int symTabSectionIndex = elfContainer.createSection(".symtab", getELFSymbolTableData(), Elf_Type.ELF_T_SYM, 8, ELF.SHT_SYMTAB, ELF.SHF_ALLOC, strTabSectionIndex, scnInfo);
|
||||
// Now create .symtab section with the symtab data constructed.
|
||||
// On Linux, sh_link of symtab contains the index of string table
|
||||
// its symbols reference and sh_info contains the index of first
|
||||
// non-local symbol
|
||||
ElfSection symTabSection = createByteSection(sections,
|
||||
".symtab",
|
||||
symtab.getSymtabArray(),
|
||||
false,
|
||||
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
|
||||
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
|
||||
elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL);
|
||||
// Update all section offsets and the Elf header section offset
|
||||
// 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.
|
||||
elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE);
|
||||
// Finish ELF processing
|
||||
elfContainer.elfEnd();
|
||||
// and round it up
|
||||
file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) &
|
||||
~((sections.get(1).getDataAlign()-1));
|
||||
|
||||
// Calc file offsets for section data skipping null section
|
||||
for (int i = 1; i < sections.size(); i++) {
|
||||
ElfSection sect = sections.get(i);
|
||||
file_offset = (file_offset + (sect.getDataAlign()-1)) &
|
||||
~((sect.getDataAlign()-1));
|
||||
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
|
||||
* symbol table and ELF symbol table are created from BinaryContainer's symbol info.
|
||||
*
|
||||
* @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.
|
||||
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.
|
||||
for (Symbol symbol : symbols) {
|
||||
// Get the index of section this symbol is defined in.
|
||||
int secHdrIndex = symbol.getSection().getSectionId();
|
||||
boolean isLocal = (symbol.getBinding() == Binding.LOCAL);
|
||||
ELFSymbol elfSymbol = elfContainer.createELFSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), secHdrIndex, symbol.getSize(), symbol.getOffset(), isLocal);
|
||||
symbol.setElfSymbol(elfSymbol);
|
||||
ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize());
|
||||
symbol.setNativeSymbol((NativeSymbol)elfSymbol);
|
||||
}
|
||||
return (symtab);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
private static byte getELFTypeOf(Symbol sym) {
|
||||
Kind kind = sym.getKind();
|
||||
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) {
|
||||
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();
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
|
||||
@ -252,18 +303,26 @@ public class JELFRelocObject {
|
||||
Symbol symbol = entry.getKey();
|
||||
|
||||
for (Relocation reloc : relocs) {
|
||||
createRelocation(symbol, reloc);
|
||||
createRelocation(symbol, reloc, elfRelocTable);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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) {
|
||||
case FOREIGN_CALL_DIRECT:
|
||||
@ -271,85 +330,89 @@ public class JELFRelocObject {
|
||||
case STUB_CALL_DIRECT:
|
||||
case FOREIGN_CALL_INDIRECT_GOT: {
|
||||
// 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
|
||||
int offset = reloc.getOffset() + reloc.getSize() + addend;
|
||||
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
|
||||
offset = offset + reloc.getSize() + addend;
|
||||
break;
|
||||
}
|
||||
case FOREIGN_CALL_DIRECT_FAR: {
|
||||
// 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
|
||||
// 10 = 2 (jmp [r]) + 8 (imm64)
|
||||
int offset = reloc.getOffset() + reloc.getSize() + addend - 2;
|
||||
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
|
||||
offset = offset + reloc.getSize() + addend - 2;
|
||||
break;
|
||||
}
|
||||
case FOREIGN_CALL_INDIRECT:
|
||||
case JAVA_CALL_INDIRECT:
|
||||
case STUB_CALL_INDIRECT: {
|
||||
// Do nothing.
|
||||
break;
|
||||
return;
|
||||
}
|
||||
case EXTERNAL_DATA_REFERENCE_FAR: {
|
||||
// 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.
|
||||
* 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.
|
||||
*/
|
||||
int offset = reloc.getOffset() + addend;
|
||||
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
|
||||
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: {
|
||||
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.
|
||||
* reloc.getOffset() points to the test instruction after the instruction that loads
|
||||
* the address of polling page. So set the offset appropriately.
|
||||
* 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.
|
||||
*/
|
||||
int offset = reloc.getOffset() + addend;
|
||||
elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
|
||||
offset = offset + addend;
|
||||
break;
|
||||
}
|
||||
case EXTERNAL_GOT_TO_PLT:
|
||||
case LOADTIME_ADDRESS: {
|
||||
// this is load time relocations
|
||||
elfContainer.createELFRelocationEntry(reloc.getSection(), reloc.getOffset(), elfRelocType, 0, symbol.getElfSymbol());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
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) {
|
||||
int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
|
||||
switch (JNIELFTargetInfo.getELFArch()) {
|
||||
case ELF.EM_X64_64:
|
||||
switch (ElfTargetInfo.getElfArch()) {
|
||||
case Elf64_Ehdr.EM_X86_64:
|
||||
// Return R_X86_64_* entries based on relocType
|
||||
if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
|
||||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PLT32;
|
||||
if (relocType == RelocType.FOREIGN_CALL_DIRECT ||
|
||||
relocType == RelocType.JAVA_CALL_DIRECT ||
|
||||
relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
|
||||
elfRelocType = Elf64_Rela.R_X86_64_PLT32;
|
||||
} else if (relocType == RelocType.STUB_CALL_DIRECT) {
|
||||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32;
|
||||
elfRelocType = Elf64_Rela.R_X86_64_PC32;
|
||||
} else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
|
||||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64;
|
||||
} else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) {
|
||||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_NONE;
|
||||
elfRelocType = Elf64_Rela.R_X86_64_64;
|
||||
} else if (relocType == RelocType.FOREIGN_CALL_INDIRECT ||
|
||||
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)) {
|
||||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_GOTPCREL;
|
||||
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
|
||||
relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
|
||||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32;
|
||||
} else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) {
|
||||
elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64;
|
||||
elfRelocType = Elf64_Rela.R_X86_64_GOTPCREL;
|
||||
} else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
|
||||
relocType == RelocType.EXTERNAL_PLT_TO_GOT ||
|
||||
relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
|
||||
relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
|
||||
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 {
|
||||
assert false : "Unhandled relocation type: " + relocType;
|
||||
}
|
||||
@ -360,61 +423,26 @@ public class JELFRelocObject {
|
||||
return elfRelocType;
|
||||
}
|
||||
|
||||
private void createAllRelocationSections(ELFContainer symtab) {
|
||||
for (Map.Entry<ELFContainer, ArrayList<Pointer>> entry : elfContainer.getRelocTables().entrySet()) {
|
||||
createRelocationSection(entry.getKey(), entry.getValue(), symtab);
|
||||
}
|
||||
}
|
||||
private void createElfRelocSections(ArrayList<ElfSection> sections,
|
||||
ElfRelocTable elfRelocTable,
|
||||
int symtabsectidx) {
|
||||
|
||||
private void createRelocationSection(ELFContainer container, ArrayList<Pointer> relocations, ELFContainer symtab) {
|
||||
String secName = container.getContainerName();
|
||||
int entrySize = JNIELFTargetInfo.sizeOfRelocEntry();
|
||||
int numEntries = relocations.size();
|
||||
byte[] sectionDataBytes = new byte[numEntries * entrySize];
|
||||
// Grab count before we create new sections
|
||||
int count = sections.size();
|
||||
|
||||
for (int index = 0; index < relocations.size(); index++) {
|
||||
Pointer entry = relocations.get(index);
|
||||
entry.copyBytesTo(sectionDataBytes, entrySize, index * entrySize);
|
||||
}
|
||||
String fullSecName;
|
||||
// If relocDat is non-null create section
|
||||
if (sectionDataBytes.length > 0) {
|
||||
int scnType;
|
||||
Elf_Type dataType;
|
||||
if (JNIELFTargetInfo.createReloca() == 0) {
|
||||
scnType = ELF.SHT_REL;
|
||||
dataType = Elf_Type.ELF_T_REL;
|
||||
fullSecName = ".rel" + secName;
|
||||
} else {
|
||||
scnType = ELF.SHT_RELA;
|
||||
dataType = Elf_Type.ELF_T_RELA;
|
||||
fullSecName = ".rela" + secName;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (elfRelocTable.getNumRelocs(i) > 0) {
|
||||
ElfSection sect = sections.get(i);
|
||||
String relname = ".rela" + sect.getName();
|
||||
ElfSection relocSection = createByteSection(sections,
|
||||
relname,
|
||||
elfRelocTable.getRelocData(i),
|
||||
false,
|
||||
0,
|
||||
Elf64_Shdr.SHT_RELA);
|
||||
relocSection.setLink(symtabsectidx);
|
||||
relocSection.setInfo(sect.getSectionId());
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,15 +21,18 @@
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Package private access to the {@link Unsafe} capability.
|
||||
*/
|
||||
class UnsafeAccess {
|
||||
public class PECoffByteBuffer {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -136,9 +136,6 @@ public class Main implements LogPrinter {
|
||||
@Override
|
||||
void process(Main task, String opt, String arg) {
|
||||
String name = arg;
|
||||
if (name.endsWith(".so")) {
|
||||
name = name.substring(0, name.length() - ".so".length());
|
||||
}
|
||||
task.options.outputName = name;
|
||||
}
|
||||
}, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
|
||||
@ -234,6 +231,11 @@ public class Main implements LogPrinter {
|
||||
void process(Main task, String opt, String arg) {
|
||||
task.options.version = true;
|
||||
}
|
||||
}, new Option(" --linker-path Full path to linker executable", true, "--linker-path") {
|
||||
@Override
|
||||
void process(Main task, String opt, String arg) {
|
||||
task.options.linkerpath = arg;
|
||||
}
|
||||
}, new Option(" -J<flag> Pass <flag> directly to the runtime system", false, "-J") {
|
||||
@Override
|
||||
void process(Main task, String opt, String arg) {
|
||||
@ -242,9 +244,10 @@ public class Main implements LogPrinter {
|
||||
|
||||
public static class Options {
|
||||
public List<SearchFor> files = new LinkedList<>();
|
||||
public String outputName = "unnamed";
|
||||
public String outputName = "unnamed.so";
|
||||
public String methodList;
|
||||
public List<ClassSource> sources = new ArrayList<>();
|
||||
public String linkerpath = null;
|
||||
public SearchPath searchPath = new SearchPath();
|
||||
|
||||
/**
|
||||
@ -347,6 +350,62 @@ public class Main implements LogPrinter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visual Studio supported versions
|
||||
* Search Order is: VS2013, VS2015, VS2012
|
||||
*/
|
||||
public enum VSVERSIONS {
|
||||
VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
|
||||
VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
|
||||
VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe");
|
||||
|
||||
private final String envvariable;
|
||||
private final String wkp;
|
||||
|
||||
VSVERSIONS(String envvariable, String wellknownpath) {
|
||||
this.envvariable = envvariable;
|
||||
this.wkp = wellknownpath;
|
||||
}
|
||||
|
||||
String EnvVariable() { return envvariable; }
|
||||
String WellKnownPath() { return wkp; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for Visual Studio link.exe
|
||||
* Search Order is: VS2013, VS2015, VS2012
|
||||
*/
|
||||
private static String getWindowsLinkPath() {
|
||||
String link = "\\VC\\bin\\amd64\\link.exe";
|
||||
|
||||
/**
|
||||
* First try searching the paths pointed to by
|
||||
* the VS environment variables.
|
||||
*/
|
||||
for (VSVERSIONS vs : VSVERSIONS.values()) {
|
||||
String vspath = System.getenv(vs.EnvVariable());
|
||||
if (vspath != null) {
|
||||
File commonTools = new File(vspath);
|
||||
File vsRoot = commonTools.getParentFile().getParentFile();
|
||||
File linkPath = new File(vsRoot, link);
|
||||
if (linkPath.exists()) return linkPath.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we didn't find via the VS environment variables,
|
||||
* try the well known paths
|
||||
*/
|
||||
for (VSVERSIONS vs : VSVERSIONS.values()) {
|
||||
String wkp = vs.WellKnownPath();
|
||||
if (new File(wkp).exists()) {
|
||||
return wkp;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
private boolean run() throws Exception {
|
||||
openLog();
|
||||
@ -451,8 +510,62 @@ public class Main implements LogPrinter {
|
||||
System.gc();
|
||||
}
|
||||
|
||||
String objectFileName = options.outputName + ".o";
|
||||
String libraryFileName = options.outputName + ".so";
|
||||
String name = options.outputName;
|
||||
String objectFileName = name;
|
||||
|
||||
// [TODO] The jtregs tests expect .so extension so don't
|
||||
// override with platform specific file extension until the
|
||||
// tests are fixed.
|
||||
String libraryFileName = name;
|
||||
|
||||
String linkerCmd;
|
||||
String linkerPath;
|
||||
String osName = System.getProperty("os.name");
|
||||
|
||||
if (name.endsWith(".so")) {
|
||||
objectFileName = name.substring(0, name.length() - ".so".length());
|
||||
}
|
||||
else if (name.endsWith(".dylib")) {
|
||||
objectFileName = name.substring(0, name.length() - ".dylib".length());
|
||||
}
|
||||
else if (name.endsWith(".dll")) {
|
||||
objectFileName = name.substring(0, name.length() - ".dll".length());
|
||||
}
|
||||
|
||||
switch (osName) {
|
||||
case "Linux":
|
||||
// libraryFileName = options.outputName + ".so";
|
||||
objectFileName = objectFileName + ".o";
|
||||
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
|
||||
linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
|
||||
break;
|
||||
case "SunOS":
|
||||
// libraryFileName = options.outputName + ".so";
|
||||
objectFileName = objectFileName + ".o";
|
||||
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
|
||||
linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName;
|
||||
break;
|
||||
case "Mac OS X":
|
||||
// libraryFileName = options.outputName + ".dylib";
|
||||
objectFileName = objectFileName + ".o";
|
||||
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
|
||||
linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName;
|
||||
break;
|
||||
default:
|
||||
if (osName.startsWith("Windows")) {
|
||||
// libraryFileName = options.outputName + ".dll";
|
||||
objectFileName = objectFileName + ".obj";
|
||||
linkerPath = (options.linkerpath != null) ?
|
||||
options.linkerpath : getWindowsLinkPath();
|
||||
if (linkerPath == null) {
|
||||
throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe");
|
||||
}
|
||||
linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName;
|
||||
break;
|
||||
}
|
||||
else
|
||||
throw new InternalError("Unsupported platform: " + osName);
|
||||
}
|
||||
|
||||
try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
|
||||
binaryContainer.createBinary(objectFileName, JVM_VERSION);
|
||||
@ -466,7 +579,7 @@ public class Main implements LogPrinter {
|
||||
}
|
||||
|
||||
try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) {
|
||||
Process p = Runtime.getRuntime().exec("ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName);
|
||||
Process p = Runtime.getRuntime().exec(linkerCmd);
|
||||
final int exitCode = p.waitFor();
|
||||
if (exitCode != 0) {
|
||||
InputStream stderr = p.getErrorStream();
|
||||
@ -484,7 +597,7 @@ public class Main implements LogPrinter {
|
||||
}
|
||||
// Make non-executable for all.
|
||||
File libFile = new File(libraryFileName);
|
||||
if (libFile.exists()) {
|
||||
if (libFile.exists() && !osName.startsWith("Windows")) {
|
||||
if (!libFile.setExecutable(false, false)) {
|
||||
throw new InternalError("Failed to change attribute for " + libraryFileName + " file");
|
||||
}
|
||||
|
||||
@ -1,522 +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.
|
||||
*/
|
||||
|
||||
#include "jdk_tools_jaotc_jnilibelf_JNILibELFAPI.h"
|
||||
|
||||
// For file open and close
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <sysexits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
// For libelf interfaces
|
||||
#include <libelf.h>
|
||||
#include <gelf.h>
|
||||
|
||||
// Convenience macro to shut the compiler warnings
|
||||
#ifdef UNUSED
|
||||
#elif defined(__GNUC__)
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
|
||||
#elif defined(__LCLINT__)
|
||||
# define UNUSED(x) /*@unused@*/ x
|
||||
#else
|
||||
# define UNUSED(x) x
|
||||
#endif
|
||||
|
||||
/**
|
||||
* libelfshim version
|
||||
*/
|
||||
#ifndef AOT_VERSION_STRING
|
||||
#error AOT_VERSION_STRING must be defined
|
||||
#endif
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elfshim_1version
|
||||
(JNIEnv* env, jclass UNUSED(c)) {
|
||||
const char* ver = AOT_VERSION_STRING;
|
||||
return (*env)->NewStringUTF(env, ver);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1version
|
||||
(JNIEnv* UNUSED(env), jclass UNUSED(c), jint v) {
|
||||
return elf_version(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbox the Pointer object the encapsulated native address.
|
||||
*/
|
||||
|
||||
static jlong getNativeAddress(JNIEnv* env, jobject ptrObj) {
|
||||
jclass ptrClass;
|
||||
jfieldID fidNumber;
|
||||
jlong nativeAddress = -1;
|
||||
assert (ptrObj != NULL);
|
||||
// Get a reference to ptr object's class
|
||||
ptrClass = (*env)->GetObjectClass(env, ptrObj);
|
||||
|
||||
// Get the Field ID of the instance variables "address"
|
||||
fidNumber = (*env)->GetFieldID(env, ptrClass, "address", "J");
|
||||
if (fidNumber != NULL) {
|
||||
// Get the long given the Field ID
|
||||
nativeAddress = (*env)->GetLongField(env, ptrObj, fidNumber);
|
||||
}
|
||||
// fprintf(stderr, "Native address : %lx\n", nativeAddress);
|
||||
return nativeAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Box the nativeAddress as a Pointer object.
|
||||
*/
|
||||
static jobject makePointerObject(JNIEnv* env, jlong nativeAddr) {
|
||||
jclass ptrClass = (*env)->FindClass(env, "jdk/tools/jaotc/jnilibelf/Pointer");
|
||||
// Call back constructor to allocate a Pointer object, with an int argument
|
||||
jmethodID constructorId = (*env)->GetMethodID(env, ptrClass, "<init>", "(J)V");
|
||||
jobject retObj = (*env)->NewObject(env, ptrClass, constructorId, nativeAddr);
|
||||
return retObj;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1begin
|
||||
(JNIEnv* env, jclass UNUSED(class), jint filedes, jint cmd, jobject ptrObj) {
|
||||
|
||||
Elf* elfPtr = NULL;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((elfPtr = elf_begin(filedes, cmd, (Elf *) addr)) == NULL) {
|
||||
errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_begin()\n");
|
||||
}
|
||||
|
||||
return makePointerObject(env, (jlong) elfPtr);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1end
|
||||
(JNIEnv* env, jclass UNUSED(class), jobject ptrObj) {
|
||||
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
return elf_end((Elf *) addr);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_end()\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1kind
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
return elf_kind((Elf *) addr);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_kind()\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1flagphdr
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd, jint flags) {
|
||||
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
unsigned int retVal = 0;
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((retVal = elf_flagphdr((Elf *) addr, cmd, flags)) == 0) {
|
||||
errx(EX_SOFTWARE, "elf_flagphdr() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_flagphdr()\n");
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newscn
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
|
||||
|
||||
Elf_Scn* elfSecPtr = NULL;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((elfSecPtr = elf_newscn((Elf *) addr)) == NULL) {
|
||||
errx(EX_SOFTWARE, "elf_newscn() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_newscn()\n");
|
||||
}
|
||||
|
||||
return makePointerObject(env, (jlong) elfSecPtr);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newdata
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
|
||||
|
||||
Elf_Data* elfDataPtr = NULL;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((elfDataPtr = elf_newdata((Elf_Scn *) addr)) == NULL) {
|
||||
errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_newdata()\n");
|
||||
}
|
||||
return makePointerObject(env, (jlong) elfDataPtr);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf64_1getshdr
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
|
||||
|
||||
Elf64_Shdr* elf64ShdrPtr = NULL;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((elf64ShdrPtr = elf64_getshdr((Elf_Scn *) addr)) == NULL) {
|
||||
errx(EX_SOFTWARE, "elf64_getshdr() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_getshdr()\n");
|
||||
}
|
||||
return makePointerObject(env, (jlong) elf64ShdrPtr);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1update
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd) {
|
||||
|
||||
off_t size = -1;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((size = elf_update((Elf*) addr, cmd)) == -1) {
|
||||
errx(EX_SOFTWARE, "elf_update() failed: %s size (%d) cmd (%d).", elf_errmsg(-1), (int)size, cmd);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_update()\n");
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1errmsg
|
||||
(JNIEnv* env, jclass UNUSED(c), jint errno) {
|
||||
|
||||
const char * retPtr = NULL;
|
||||
// Call libelf function
|
||||
if ((retPtr = elf_errmsg(errno)) == NULL) {
|
||||
errx(EX_SOFTWARE, "elf_errmsg() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
return (*env)->NewStringUTF(env, retPtr);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1ndxscn
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) {
|
||||
jint secnum = SHN_UNDEF;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
secnum = elf_ndxscn((Elf_Scn*) addr);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_ndxscn()\n");
|
||||
}
|
||||
return secnum;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newehdr
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint elfClass) {
|
||||
unsigned long int retPtr = 0;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((retPtr = gelf_newehdr((Elf*) addr, elfClass)) == 0) {
|
||||
errx(EX_SOFTWARE, "gelf_newehdr() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_newehdr()\n");
|
||||
}
|
||||
return makePointerObject(env, (jlong) retPtr);
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newphdr
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint phnum) {
|
||||
unsigned long int retPtr = 0;
|
||||
jlong addr = getNativeAddress(env, ptrObj);
|
||||
if (addr != -1) {
|
||||
// Call libelf function
|
||||
if ((retPtr = gelf_newphdr((Elf*) addr, phnum)) == 0) {
|
||||
errx(EX_SOFTWARE, "gelf_newphdr() failed: %s.", elf_errmsg(-1));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed to get native address to call elf_newphdr()\n");
|
||||
}
|
||||
return makePointerObject(env, (jlong) retPtr);
|
||||
}
|
||||
|
||||
|
||||
/* File operations */
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open_1rw
|
||||
(JNIEnv * env, jclass UNUSED(class), jstring jfileName) {
|
||||
int flags = O_RDWR | O_CREAT | O_TRUNC;
|
||||
int mode = 0666;
|
||||
int retVal;
|
||||
const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL);
|
||||
if (cfileName == NULL) {
|
||||
return -1;
|
||||
}
|
||||
retVal = open(cfileName, flags, mode);
|
||||
if (retVal < 0) {
|
||||
err(EX_NOINPUT, "open %s failed", cfileName);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jfileName, cfileName);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2I
|
||||
(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags) {
|
||||
int retVal;
|
||||
const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL);
|
||||
if (cfileName == NULL) {
|
||||
return -1;
|
||||
}
|
||||
retVal = open(cfileName, flags);
|
||||
if (retVal < 0) {
|
||||
err(EX_NOINPUT, "open %s failed", cfileName);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jfileName, cfileName);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2II
|
||||
(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags, jint mode) {
|
||||
int retVal;
|
||||
const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL);
|
||||
if (cfileName == NULL) {
|
||||
return -1;
|
||||
}
|
||||
retVal = open(cfileName, flags, mode);
|
||||
if (retVal < 0) {
|
||||
err(EX_NOINPUT, "open %s failed", cfileName);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jfileName, cfileName);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_close
|
||||
(JNIEnv* UNUSED(env), jclass UNUSED(class), jint fd) {
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Miscellaneous ELF data structure peek-poke functions in
|
||||
* shim_functions.c. No corresponding .h file exists yet.
|
||||
* So each function needs to be declared as extern
|
||||
*/
|
||||
|
||||
extern int size_of_Sym(int elfclass);
|
||||
extern int size_of_Rel(int elfclass);
|
||||
extern int size_of_Rela(int elfclass);
|
||||
|
||||
extern void ehdr_set_data_encoding(void * ehdr, int val);
|
||||
extern void set_Ehdr_e_machine(int elfclass, void * structPtr, int val);
|
||||
extern void set_Ehdr_e_type(int elfclass, void * structPtr, int val);
|
||||
extern void set_Ehdr_e_version(int elfclass, void * structPtr, int val);
|
||||
extern void set_Ehdr_e_shstrndx(int elfclass, void * structPtr, int val);
|
||||
|
||||
extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr);
|
||||
extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr);
|
||||
|
||||
extern void set_Shdr_sh_name(int elfclass, void* structPtr, int val);
|
||||
extern void set_Shdr_sh_type(int elfclass, void* structPtr, int val);
|
||||
extern void set_Shdr_sh_flags(int elfclass, void* structPtr, int val);
|
||||
extern void set_Shdr_sh_entsize(int elfclass, void* structPtr, int val);
|
||||
extern void set_Shdr_sh_link(int elfclass, void* structPtr, int val);
|
||||
extern void set_Shdr_sh_info(int elfclass, void* structPtr, int val);
|
||||
|
||||
extern void set_Data_d_align(void* structPtr, int val);
|
||||
extern void set_Data_d_off(void* structPtr, int val);
|
||||
extern void set_Data_d_buf(void* structPtr, void* val);
|
||||
extern void set_Data_d_type(void* structPtr, int val);
|
||||
extern void set_Data_d_size(void* structPtr, int val);
|
||||
extern void set_Data_d_version(void* structPtr, int val);
|
||||
|
||||
extern void* create_sym_entry(int elfclass, int index, int type, int bind,
|
||||
int shndx, int size, int value);
|
||||
extern void * create_reloc_entry(int elfclass, int roffset, int symtabIdx,
|
||||
int relocType, int raddend, int reloca);
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Sym
|
||||
(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) {
|
||||
return size_of_Sym(elfClass);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rela
|
||||
(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) {
|
||||
return size_of_Rela(elfClass);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rel
|
||||
(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) {
|
||||
return size_of_Rel(elfClass);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_ehdr_1set_1data_1encoding
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
|
||||
void* ehdr = (void*) getNativeAddress(env, ptrObj);
|
||||
ehdr_set_data_encoding(ehdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1machine
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* ehdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Ehdr_e_machine(elfClass, ehdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1type
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* ehdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Ehdr_e_type(elfClass, ehdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1version
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* ehdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Ehdr_e_version(elfClass, ehdr, val);
|
||||
}
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1shstrndx
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* shdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Ehdr_e_shstrndx(elfClass, shdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_phdr_1set_1type_1self
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ehdrPtr, jobject phdrPtr) {
|
||||
void* ehdr = (void*) getNativeAddress(env, ehdrPtr);
|
||||
void* phdr = (void*) getNativeAddress(env, phdrPtr);
|
||||
phdr_set_type_self(elfClass, ehdr, phdr);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1name
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* shdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Shdr_sh_name(elfClass, shdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1type
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* shdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Shdr_sh_type(elfClass, shdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1flags
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* shdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Shdr_sh_flags(elfClass, shdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1entsize
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* shdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Shdr_sh_entsize(elfClass, shdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1info
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* shdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Shdr_sh_info(elfClass, shdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1link
|
||||
(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) {
|
||||
void* shdr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Shdr_sh_link(elfClass, shdr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1align
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
|
||||
void* dptr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Data_d_align(dptr, val);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1off
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
|
||||
void* dptr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Data_d_off(dptr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1buf
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jobject bufPtr) {
|
||||
void* dptr = (void*) getNativeAddress(env, ptrObj);
|
||||
void* bptr = (void*) getNativeAddress(env, bufPtr);
|
||||
set_Data_d_buf(dptr, bptr);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1type
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
|
||||
void* dptr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Data_d_type(dptr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1size
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
|
||||
void* dptr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Data_d_size(dptr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1version
|
||||
(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) {
|
||||
void* dptr = (void*) getNativeAddress(env, ptrObj);
|
||||
set_Data_d_version(dptr, val);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1sym_1entry
|
||||
(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint index, jint type,
|
||||
jint bind, jint shndx, jint size, jint value) {
|
||||
void * retVal = create_sym_entry(elfClass, index, type, bind,
|
||||
shndx, size, value);
|
||||
return (jlong)retVal;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1reloc_1entry
|
||||
(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint roffset,
|
||||
jint symTabIdx, jint relocType, jint raddend, jint reloca) {
|
||||
void * retVal = create_reloc_entry(elfClass, roffset, symTabIdx,
|
||||
relocType, raddend, reloca);
|
||||
return (jlong)retVal;
|
||||
}
|
||||
|
||||
@ -1,226 +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.
|
||||
*/
|
||||
|
||||
#include <libelf.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* TODO: This is an intial and crude attempt to access structure
|
||||
* fields of some ELF structrures. Need to figure out a way to access the
|
||||
* given field of a given structure instead of writing one shim function
|
||||
* per access of each of the structure field.
|
||||
**/
|
||||
|
||||
#define STRINGIFYHELPER(x) #x
|
||||
#define STRINGIFY(x) STRINGIFYHELPER(x)
|
||||
#define FUNC_NAME(S, F) set_ ## S ## _ ## F
|
||||
#define CAST_STRUCT(S, F) ((Elf_ ## S *) structPtr)
|
||||
#define CAST_STRUCT32(S, F) ((Elf32_ ## S *) structPtr)
|
||||
#define CAST_STRUCT64(S, F) ((Elf64_ ## S *) structPtr)
|
||||
#define ACCESS_FIELD(S, F) CAST_STRUCT(S, F)-> F
|
||||
#define ACCESS_FIELD32(S, F) CAST_STRUCT32(S, F)-> F
|
||||
#define ACCESS_FIELD64(S, F) CAST_STRUCT64(S, F)-> F
|
||||
|
||||
/*
|
||||
Example:
|
||||
SET_TYPE_BASED_FIELD(Ehdr, e_machine, int)
|
||||
expands to
|
||||
set_Ehdr_e_machine(int elfclass, void * strPtr, int val) {
|
||||
}
|
||||
*/
|
||||
|
||||
#define SET_TYPE_BASED_FIELD(S, F, T) \
|
||||
void FUNC_NAME(S, F)(int elfclass, void * structPtr, T val) { \
|
||||
if (elfclass == ELFCLASS32) { \
|
||||
ACCESS_FIELD32(S, F) = val; \
|
||||
} else if (elfclass == ELFCLASS64) { \
|
||||
ACCESS_FIELD64(S, F) = val; \
|
||||
} else { \
|
||||
printf("%s: Unknown ELF Class %d provided\n", STRINGIFY(FUNC_NAME(S, F)), elfclass); \
|
||||
} \
|
||||
return; \
|
||||
}
|
||||
|
||||
/*
|
||||
Example:
|
||||
SET_FIELD(Ehdr, e_machine, int)
|
||||
expands to
|
||||
set_Ehdr_e_machine(void * strPtr, int val) {
|
||||
}
|
||||
*/
|
||||
|
||||
#define SET_FIELD(S, F, T) \
|
||||
void FUNC_NAME(S, F)(void * structPtr, T val) { \
|
||||
ACCESS_FIELD(S, F) = val; \
|
||||
return; \
|
||||
}
|
||||
|
||||
int size_of_Sym(int elfclass) {
|
||||
if (elfclass == ELFCLASS32) {
|
||||
return sizeof(Elf32_Sym);
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
return sizeof(Elf64_Sym);
|
||||
} else {
|
||||
printf("Unknown ELF Class %d provided\n", elfclass);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int size_of_Rela(int elfclass) {
|
||||
if (elfclass == ELFCLASS32) {
|
||||
return sizeof(Elf32_Rela);
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
return sizeof(Elf64_Rela);
|
||||
} else {
|
||||
printf("Unknown ELF Class %d provided\n", elfclass);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int size_of_Rel(int elfclass) {
|
||||
if (elfclass == ELFCLASS32) {
|
||||
return sizeof(Elf32_Rel);
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
return sizeof(Elf64_Rel);
|
||||
} else {
|
||||
printf("Unknown ELF Class %d provided\n", elfclass);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ELF Header field access */
|
||||
|
||||
void ehdr_set_data_encoding(void * ehdr, int val) {
|
||||
((Elf32_Ehdr *) ehdr)->e_ident[EI_DATA] = val;
|
||||
return;
|
||||
}
|
||||
|
||||
SET_TYPE_BASED_FIELD(Ehdr, e_machine, int)
|
||||
SET_TYPE_BASED_FIELD(Ehdr, e_type, int)
|
||||
SET_TYPE_BASED_FIELD(Ehdr, e_version, int)
|
||||
SET_TYPE_BASED_FIELD(Ehdr, e_shstrndx, int)
|
||||
|
||||
/* Data descriptor field access */
|
||||
SET_FIELD(Data, d_align, int)
|
||||
SET_FIELD(Data, d_off, int)
|
||||
SET_FIELD(Data, d_buf, void*)
|
||||
SET_FIELD(Data, d_type, int)
|
||||
SET_FIELD(Data, d_size, int)
|
||||
SET_FIELD(Data, d_version, int)
|
||||
|
||||
/* Section Header Access functions */
|
||||
SET_TYPE_BASED_FIELD(Shdr, sh_name, int)
|
||||
SET_TYPE_BASED_FIELD(Shdr, sh_type, int)
|
||||
SET_TYPE_BASED_FIELD(Shdr, sh_flags, int)
|
||||
SET_TYPE_BASED_FIELD(Shdr, sh_entsize, int)
|
||||
SET_TYPE_BASED_FIELD(Shdr, sh_link, int)
|
||||
SET_TYPE_BASED_FIELD(Shdr, sh_info, int)
|
||||
|
||||
/* Set the Program Header to be of PH_PHDR type and initialize other
|
||||
related fields of the program header.
|
||||
*/
|
||||
void phdr_set_type_self(int elfclass, void * ehdr, void * phdr) {
|
||||
if (elfclass == ELFCLASS32) {
|
||||
Elf32_Ehdr * ehdr32 = (Elf32_Ehdr *) ehdr;
|
||||
Elf32_Phdr * phdr32 = (Elf32_Phdr *) phdr;
|
||||
phdr32->p_type = PT_PHDR;
|
||||
phdr32->p_offset = ehdr32->e_phoff;
|
||||
phdr32->p_filesz = elf32_fsize(ELF_T_PHDR, 1, EV_CURRENT);
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
Elf64_Ehdr * ehdr64 = (Elf64_Ehdr *) ehdr;
|
||||
Elf64_Phdr * phdr64 = (Elf64_Phdr *) phdr;
|
||||
phdr64->p_type = PT_PHDR;
|
||||
phdr64->p_offset = ehdr64->e_phoff;
|
||||
phdr64->p_filesz = elf64_fsize(ELF_T_PHDR, 1, EV_CURRENT);
|
||||
} else {
|
||||
printf("phdr_set_type_self: Unknown ELF Class %d provided\n", elfclass);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Create symbol table entry with given type and binding
|
||||
*/
|
||||
void * create_sym_entry(int elfclass, int index, int type, int bind,
|
||||
int shndx, int size, int value) {
|
||||
void * symentry = NULL;
|
||||
if (elfclass == ELFCLASS32) {
|
||||
Elf32_Sym * sym32 = (Elf32_Sym *) malloc(sizeof(Elf32_Sym));
|
||||
sym32->st_name = index;
|
||||
sym32->st_value = value;
|
||||
sym32->st_size = size;
|
||||
sym32->st_info = ELF32_ST_INFO(bind, type);
|
||||
sym32->st_other = 0; // TODO: Add an argument to get this value ??
|
||||
sym32->st_shndx = shndx;
|
||||
symentry = sym32;
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
Elf64_Sym * sym64 = (Elf64_Sym *) malloc(sizeof(Elf64_Sym));
|
||||
sym64->st_name = index;
|
||||
sym64->st_value = value;
|
||||
sym64->st_size = size;
|
||||
sym64->st_info = ELF64_ST_INFO(bind, type);
|
||||
sym64->st_other = 0; // TODO: Add an argument to get this value ??
|
||||
sym64->st_shndx = shndx;
|
||||
symentry = sym64;
|
||||
} else {
|
||||
printf("create_sym_entry: Unknown ELF Class %d provided\n", elfclass);
|
||||
}
|
||||
return (void *) symentry;
|
||||
}
|
||||
|
||||
// Create a reloc (or reloca entry if argument reloca is non-zero)
|
||||
void * create_reloc_entry(int elfclass, int roffset, int symtabIdx,
|
||||
int relocType, int raddend, int reloca) {
|
||||
void * relocentry = NULL;
|
||||
if (elfclass == ELFCLASS32) {
|
||||
if (reloca) {
|
||||
Elf32_Rela * rela32 = (Elf32_Rela *) malloc(sizeof(Elf32_Rela));
|
||||
rela32->r_offset = roffset;
|
||||
rela32->r_info = ELF32_R_INFO(symtabIdx, relocType);
|
||||
rela32->r_addend = raddend;
|
||||
relocentry = rela32;
|
||||
} else {
|
||||
Elf32_Rel * rel32 = (Elf32_Rel *) malloc(sizeof(Elf32_Rel));
|
||||
rel32->r_offset = roffset;
|
||||
rel32->r_info = ELF32_R_INFO(symtabIdx, relocType);
|
||||
relocentry = rel32;
|
||||
}
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
if (reloca) {
|
||||
Elf64_Rela * rela64 = (Elf64_Rela *) malloc(sizeof(Elf64_Rela));
|
||||
rela64->r_offset = roffset;
|
||||
rela64->r_info = ELF64_R_INFO(symtabIdx, relocType);
|
||||
rela64->r_addend = raddend;
|
||||
relocentry = rela64;
|
||||
} else {
|
||||
Elf64_Rel * rel64 = (Elf64_Rel *) malloc(sizeof(Elf64_Rel));
|
||||
rel64->r_offset = roffset;
|
||||
rel64->r_info = ELF64_R_INFO(symtabIdx, relocType);
|
||||
relocentry = rel64;
|
||||
}
|
||||
} else {
|
||||
printf("create_reloc_entry: Unknown ELF Class %d provided\n", elfclass);
|
||||
}
|
||||
return (void *) relocentry;
|
||||
}
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -59,6 +59,21 @@ static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
|
||||
static int resettedSigflags[NUM_SIGNALS];
|
||||
static address resettedSighandler[NUM_SIGNALS];
|
||||
|
||||
// Needed for cancelable steps.
|
||||
static volatile pthread_t reporter_thread_id;
|
||||
|
||||
void VMError::reporting_started() {
|
||||
// record pthread id of reporter thread.
|
||||
reporter_thread_id = ::pthread_self();
|
||||
}
|
||||
|
||||
void VMError::interrupt_reporting_thread() {
|
||||
// We misuse SIGILL here, but it does not really matter. We need
|
||||
// a signal which is handled by crash_handler and not likely to
|
||||
// occurr during error reporting itself.
|
||||
::pthread_kill(reporter_thread_id, SIGILL);
|
||||
}
|
||||
|
||||
static void save_signal(int idx, int sig)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -66,3 +66,10 @@ void VMError::check_failing_cds_access(outputStream* st, const void* siginfo) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error reporting cancellation: there is no easy way to implement this on Windows, because we do
|
||||
// not have an easy way to send signals to threads (aka to cause a win32 Exception in another
|
||||
// thread). We would need something like "RaiseException(HANDLE thread)"...
|
||||
void VMError::reporting_started() {}
|
||||
void VMError::interrupt_reporting_thread() {}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,7 +41,7 @@ int AOTLib::_narrow_oop_shift = 0;
|
||||
int AOTLib::_narrow_klass_shift = 0;
|
||||
|
||||
address AOTLib::load_symbol(const char *name) {
|
||||
address symbol = (address) dlsym(_dl_handle, name);
|
||||
address symbol = (address) os::dll_lookup(_dl_handle, name);
|
||||
if (symbol == NULL) {
|
||||
tty->print_cr("Shared file %s error: missing %s", _name, name);
|
||||
vm_exit(1);
|
||||
@ -225,16 +225,15 @@ AOTCodeHeap::AOTCodeHeap(AOTLib* lib) :
|
||||
_method_count = _lib->header()->_method_count;
|
||||
|
||||
// Collect metaspace info: names -> address in .got section
|
||||
_metaspace_names = (const char*) _lib->load_symbol("JVM.metaspace.names");
|
||||
_method_metadata = (address) _lib->load_symbol("JVM.method.metadata");
|
||||
_metaspace_names = (const char*) _lib->load_symbol("JVM.meta.names");
|
||||
_method_metadata = (address) _lib->load_symbol("JVM.meth.metadata");
|
||||
_methods_offsets = (address) _lib->load_symbol("JVM.methods.offsets");
|
||||
_klasses_offsets = (address) _lib->load_symbol("JVM.klasses.offsets");
|
||||
_dependencies = (address) _lib->load_symbol("JVM.klasses.dependencies");
|
||||
_klasses_offsets = (address) _lib->load_symbol("JVM.kls.offsets");
|
||||
_dependencies = (address) _lib->load_symbol("JVM.kls.dependencies");
|
||||
_code_space = (address) _lib->load_symbol("JVM.text");
|
||||
|
||||
// First cell is number of elements.
|
||||
jlong* got_sect;
|
||||
_metaspace_got = (Metadata**) _lib->load_symbol("JVM.metaspace.got");
|
||||
_metaspace_got = (Metadata**) _lib->load_symbol("JVM.meta.got");
|
||||
_metaspace_got_size = _lib->header()->_metaspace_got_size;
|
||||
|
||||
_metadata_got = (Metadata**) _lib->load_symbol("JVM.metadata.got");
|
||||
@ -250,7 +249,7 @@ AOTCodeHeap::AOTCodeHeap(AOTLib* lib) :
|
||||
_code_segments = (address) _lib->load_symbol("JVM.code.segments");
|
||||
|
||||
// method state
|
||||
_method_state = (jlong*) _lib->load_symbol("JVM.method.state");
|
||||
_method_state = (jlong*) _lib->load_symbol("JVM.meth.state");
|
||||
|
||||
// Create a table for mapping classes
|
||||
_classes = NEW_C_HEAP_ARRAY(AOTClass, _class_count, mtCode);
|
||||
@ -341,7 +340,7 @@ void AOTCodeHeap::link_primitive_array_klasses() {
|
||||
BasicType t = (BasicType)i;
|
||||
if (is_java_primitive(t)) {
|
||||
const Klass* arr_klass = Universe::typeArrayKlassObj(t);
|
||||
AOTKlassData* klass_data = (AOTKlassData*) dlsym(_lib->dl_handle(), arr_klass->signature_name());
|
||||
AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), arr_klass->signature_name());
|
||||
if (klass_data != NULL) {
|
||||
// Set both GOT cells, resolved and initialized klass pointers.
|
||||
// _got_index points to second cell - resolved klass pointer.
|
||||
@ -394,13 +393,9 @@ void AOTCodeHeap::register_stubs() {
|
||||
|
||||
#define SET_AOT_GLOBAL_SYMBOL_VALUE(AOTSYMNAME, AOTSYMTYPE, VMSYMVAL) \
|
||||
{ \
|
||||
char* error; \
|
||||
/* Clear any existing error */ \
|
||||
dlerror(); \
|
||||
AOTSYMTYPE * adr = (AOTSYMTYPE *) dlsym(_lib->dl_handle(), AOTSYMNAME); \
|
||||
/* Check for any dlsym lookup error */ \
|
||||
error = dlerror(); \
|
||||
guarantee(error == NULL, "%s", error); \
|
||||
AOTSYMTYPE * adr = (AOTSYMTYPE *) os::dll_lookup(_lib->dl_handle(), AOTSYMNAME); \
|
||||
/* Check for a lookup error */ \
|
||||
guarantee(adr != NULL, "AOT Symbol not found %s", AOTSYMNAME); \
|
||||
*adr = (AOTSYMTYPE) VMSYMVAL; \
|
||||
}
|
||||
|
||||
@ -604,9 +599,9 @@ Method* AOTCodeHeap::find_method(KlassHandle klass, Thread* thread, const char*
|
||||
memcpy(&meta_name[klass_len + 1 + method_name_len], signature_name, signature_name_len);
|
||||
meta_name[klass_len + 1 + method_name_len + signature_name_len] = '\0';
|
||||
Handle exception = Exceptions::new_exception(thread, vmSymbols::java_lang_NoSuchMethodError(), meta_name);
|
||||
java_lang_Throwable::print(exception, tty);
|
||||
java_lang_Throwable::print(exception(), tty);
|
||||
tty->cr();
|
||||
java_lang_Throwable::print_stack_trace(exception(), tty);
|
||||
java_lang_Throwable::print_stack_trace(exception, tty);
|
||||
tty->cr();
|
||||
fatal("Failed to find method '%s'", meta_name);
|
||||
}
|
||||
@ -616,7 +611,7 @@ Method* AOTCodeHeap::find_method(KlassHandle klass, Thread* thread, const char*
|
||||
|
||||
AOTKlassData* AOTCodeHeap::find_klass(InstanceKlass* ik) {
|
||||
ResourceMark rm;
|
||||
AOTKlassData* klass_data = (AOTKlassData*) dlsym(_lib->dl_handle(), ik->signature_name());
|
||||
AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), ik->signature_name());
|
||||
return klass_data;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -42,7 +42,6 @@
|
||||
#include "utilities/array.hpp"
|
||||
#include "utilities/xmlstream.hpp"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if 0
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@
|
||||
#include "aot/aotLoader.inline.hpp"
|
||||
#include "jvmci/jvmciRuntime.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
|
||||
GrowableArray<AOTCodeHeap*>* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTCodeHeap*> (2, true);
|
||||
GrowableArray<AOTLib*>* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTLib*> (2, true);
|
||||
@ -146,13 +147,13 @@ void AOTLoader::initialize() {
|
||||
|
||||
for (int i = 0; i < (int) (sizeof(modules) / sizeof(const char*)); i++) {
|
||||
char library[JVM_MAXPATHLEN];
|
||||
jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s.so", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1");
|
||||
jio_snprintf(library, sizeof(library), "%s%slib%slib%s%s%s%s", home, file_separator, file_separator, modules[i], UseCompressedOops ? "-coop" : "", UseG1GC ? "" : "-nong1", os::dll_file_extension());
|
||||
load_library(library, false);
|
||||
}
|
||||
|
||||
// Scan the AOTLibrary option.
|
||||
if (AOTLibrary != NULL) {
|
||||
const int len = strlen(AOTLibrary);
|
||||
const int len = (int)strlen(AOTLibrary);
|
||||
char* cp = NEW_C_HEAP_ARRAY(char, len+1, mtCode);
|
||||
if (cp != NULL) { // No memory?
|
||||
memcpy(cp, AOTLibrary, len);
|
||||
@ -234,10 +235,11 @@ void AOTLoader::set_narrow_klass_shift() {
|
||||
}
|
||||
|
||||
void AOTLoader::load_library(const char* name, bool exit_on_error) {
|
||||
void* handle = dlopen(name, RTLD_LAZY);
|
||||
char ebuf[1024];
|
||||
void* handle = os::dll_load(name, ebuf, sizeof ebuf);
|
||||
if (handle == NULL) {
|
||||
if (exit_on_error) {
|
||||
tty->print_cr("error opening file: %s", dlerror());
|
||||
tty->print_cr("error opening file: %s", ebuf);
|
||||
vm_exit(1);
|
||||
}
|
||||
return;
|
||||
@ -246,7 +248,7 @@ void AOTLoader::load_library(const char* name, bool exit_on_error) {
|
||||
AOTLib* lib = new AOTLib(handle, name, dso_id);
|
||||
if (!lib->is_valid()) {
|
||||
delete lib;
|
||||
dlclose(handle);
|
||||
os::dll_unload(handle);
|
||||
return;
|
||||
}
|
||||
add_library(lib);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,6 +21,8 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "aot/compiledIC_aot.hpp"
|
||||
|
||||
bool CompiledPltStaticCall::is_call_to_interpreted() const {
|
||||
|
||||
@ -93,6 +93,10 @@ class Label VALUE_OBJ_CLASS_SPEC {
|
||||
GrowableArray<int>* _patch_overflow;
|
||||
|
||||
Label(const Label&) { ShouldNotReachHere(); }
|
||||
protected:
|
||||
|
||||
// The label will be bound to a location near its users.
|
||||
bool _is_near;
|
||||
|
||||
public:
|
||||
|
||||
@ -126,6 +130,10 @@ class Label VALUE_OBJ_CLASS_SPEC {
|
||||
bool is_unbound() const { return _loc == -1 && _patch_index > 0; }
|
||||
bool is_unused() const { return _loc == -1 && _patch_index == 0; }
|
||||
|
||||
// The label will be bound to a location near its users. Users can
|
||||
// optimize on this information, e.g. generate short branches.
|
||||
bool is_near() { return _is_near; }
|
||||
|
||||
/**
|
||||
* Adds a reference to an unresolved displacement instruction to
|
||||
* this unbound label
|
||||
@ -145,6 +153,7 @@ class Label VALUE_OBJ_CLASS_SPEC {
|
||||
_loc = -1;
|
||||
_patch_index = 0;
|
||||
_patch_overflow = NULL;
|
||||
_is_near = false;
|
||||
}
|
||||
|
||||
Label() {
|
||||
@ -152,6 +161,13 @@ class Label VALUE_OBJ_CLASS_SPEC {
|
||||
}
|
||||
};
|
||||
|
||||
// A NearLabel must be bound to a location near its users. Users can
|
||||
// optimize on this information, e.g. generate short branches.
|
||||
class NearLabel : public Label {
|
||||
public:
|
||||
NearLabel() : Label() { _is_near = true; }
|
||||
};
|
||||
|
||||
// A union type for code which has to assemble both constant and
|
||||
// non-constant operands, when the distinction cannot be made
|
||||
// statically.
|
||||
|
||||
@ -4291,6 +4291,8 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes
|
||||
}
|
||||
#endif // INCLUDE_TRACE
|
||||
|
||||
CompileTask::print_inlining_ul(callee, scope()->level(), bci(), msg);
|
||||
|
||||
if (!compilation()->directive()->PrintInliningOption) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -961,13 +961,13 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i
|
||||
assert(cache_index >= 0 && cache_index < pool->cache()->length(), "unexpected cache index");
|
||||
ConstantPoolCacheEntry* cpce = pool->cache()->entry_at(cache_index);
|
||||
cpce->set_method_handle(pool, info);
|
||||
appendix = cpce->appendix_if_resolved(pool); // just in case somebody already resolved the entry
|
||||
appendix = Handle(THREAD, cpce->appendix_if_resolved(pool)); // just in case somebody already resolved the entry
|
||||
break;
|
||||
}
|
||||
case Bytecodes::_invokedynamic: {
|
||||
ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index);
|
||||
cpce->set_dynamic_call(pool, info);
|
||||
appendix = cpce->appendix_if_resolved(pool); // just in case somebody already resolved the entry
|
||||
appendix = Handle(THREAD, cpce->appendix_if_resolved(pool)); // just in case somebody already resolved the entry
|
||||
break;
|
||||
}
|
||||
default: fatal("unexpected bytecode for load_appendix_patching_id");
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -278,7 +278,7 @@ ciInstance* ciEnv::get_or_create_exception(jobject& handle, Symbol* name) {
|
||||
if (!HAS_PENDING_EXCEPTION && k != NULL) {
|
||||
oop obj = InstanceKlass::cast(k)->allocate_instance(THREAD);
|
||||
if (!HAS_PENDING_EXCEPTION)
|
||||
objh = JNIHandles::make_global(obj);
|
||||
objh = JNIHandles::make_global(Handle(THREAD, obj));
|
||||
}
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
@ -376,7 +376,7 @@ bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass,
|
||||
}
|
||||
if (resolved_klass->is_instance_klass()) {
|
||||
return (Reflection::verify_class_access(accessing_klass->get_Klass(),
|
||||
resolved_klass,
|
||||
InstanceKlass::cast(resolved_klass),
|
||||
true) == Reflection::ACCESS_OK);
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -58,8 +58,8 @@ ciType* ciInstance::java_mirror_type() {
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstance::field_value_impl
|
||||
ciConstant ciInstance::field_value_impl(BasicType field_btype, int offset) {
|
||||
Handle obj = get_oop();
|
||||
assert(!obj.is_null(), "bad oop");
|
||||
oop obj = get_oop();
|
||||
assert(obj != NULL, "bad oop");
|
||||
switch(field_btype) {
|
||||
case T_BYTE: return ciConstant(field_btype, obj->byte_field(offset));
|
||||
case T_CHAR: return ciConstant(field_btype, obj->char_field(offset));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -54,7 +54,8 @@ ciObject::ciObject(oop o) {
|
||||
if (ciObjectFactory::is_initialized()) {
|
||||
_handle = JNIHandles::make_local(o);
|
||||
} else {
|
||||
_handle = JNIHandles::make_global(o);
|
||||
Handle obj(Thread::current(), o);
|
||||
_handle = JNIHandles::make_global(obj);
|
||||
}
|
||||
_klass = NULL;
|
||||
init_flags_from(o);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -249,7 +249,7 @@ ciObject* ciObjectFactory::get(oop key) {
|
||||
|
||||
// The ciObject does not yet exist. Create it and insert it
|
||||
// into the cache.
|
||||
Handle keyHandle(key);
|
||||
Handle keyHandle(Thread::current(), key);
|
||||
ciObject* new_object = create_new_object(keyHandle());
|
||||
assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
|
||||
init_ident_of(new_object);
|
||||
|
||||
@ -751,7 +751,7 @@ class CompileReplay : public StackObj {
|
||||
|
||||
assert(k->is_initialized(), "must be");
|
||||
|
||||
const char* field_name = parse_escaped_string();;
|
||||
const char* field_name = parse_escaped_string();
|
||||
const char* field_signature = parse_string();
|
||||
fieldDescriptor fd;
|
||||
Symbol* name = SymbolTable::lookup(field_name, (int)strlen(field_name), CHECK);
|
||||
@ -840,9 +840,8 @@ class CompileReplay : public StackObj {
|
||||
Handle value = java_lang_String::create_from_str(string_value, CHECK);
|
||||
java_mirror->obj_field_put(fd.offset(), value());
|
||||
} else if (field_signature[0] == 'L') {
|
||||
Symbol* klass_name = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK);
|
||||
KlassHandle kelem = resolve_klass(field_signature, CHECK);
|
||||
oop value = InstanceKlass::cast(kelem())->allocate_instance(CHECK);
|
||||
KlassHandle k = resolve_klass(string_value, CHECK);
|
||||
oop value = InstanceKlass::cast(k())->allocate_instance(CHECK);
|
||||
java_mirror->obj_field_put(fd.offset(), value);
|
||||
} else {
|
||||
report_error("unhandled staticfield");
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -834,7 +834,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
||||
const Klass* const k =
|
||||
SystemDictionary::resolve_super_or_fail(_class_name,
|
||||
unresolved_klass,
|
||||
_loader_data->class_loader(),
|
||||
Handle(THREAD, _loader_data->class_loader()),
|
||||
_protection_domain,
|
||||
false,
|
||||
CHECK);
|
||||
@ -2858,7 +2858,6 @@ void ClassFileParser::parse_methods(const ClassFileStream* const cfs,
|
||||
NULL,
|
||||
CHECK);
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
for (int index = 0; index < length; index++) {
|
||||
Method* method = parse_method(cfs,
|
||||
is_interface,
|
||||
@ -4382,10 +4381,12 @@ static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) {
|
||||
}
|
||||
|
||||
Reflection::VerifyClassAccessResults vca_result =
|
||||
Reflection::verify_class_access(this_klass, super, false);
|
||||
Reflection::verify_class_access(this_klass, InstanceKlass::cast(super), false);
|
||||
if (vca_result != Reflection::ACCESS_OK) {
|
||||
ResourceMark rm(THREAD);
|
||||
char* msg = Reflection::verify_class_access_msg(this_klass, super, vca_result);
|
||||
char* msg = Reflection::verify_class_access_msg(this_klass,
|
||||
InstanceKlass::cast(super),
|
||||
vca_result);
|
||||
if (msg == NULL) {
|
||||
Exceptions::fthrow(
|
||||
THREAD_AND_LOCATION,
|
||||
@ -4414,10 +4415,12 @@ static void check_super_interface_access(const InstanceKlass* this_klass, TRAPS)
|
||||
Klass* const k = local_interfaces->at(i);
|
||||
assert (k != NULL && k->is_interface(), "invalid interface");
|
||||
Reflection::VerifyClassAccessResults vca_result =
|
||||
Reflection::verify_class_access(this_klass, k, false);
|
||||
Reflection::verify_class_access(this_klass, InstanceKlass::cast(k), false);
|
||||
if (vca_result != Reflection::ACCESS_OK) {
|
||||
ResourceMark rm(THREAD);
|
||||
char* msg = Reflection::verify_class_access_msg(this_klass, k, vca_result);
|
||||
char* msg = Reflection::verify_class_access_msg(this_klass,
|
||||
InstanceKlass::cast(k),
|
||||
vca_result);
|
||||
if (msg == NULL) {
|
||||
Exceptions::fthrow(
|
||||
THREAD_AND_LOCATION,
|
||||
@ -5361,7 +5364,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
|
||||
// Allocate mirror and initialize static fields
|
||||
// The create_mirror() call will also call compute_modifiers()
|
||||
java_lang_Class::create_mirror(ik,
|
||||
_loader_data->class_loader(),
|
||||
Handle(THREAD, _loader_data->class_loader()),
|
||||
module_handle,
|
||||
_protection_domain,
|
||||
CHECK);
|
||||
@ -5919,10 +5922,11 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
|
||||
"Interfaces must have java.lang.Object as superclass in class file %s",
|
||||
CHECK);
|
||||
}
|
||||
Handle loader(THREAD, _loader_data->class_loader());
|
||||
_super_klass = (const InstanceKlass*)
|
||||
SystemDictionary::resolve_super_or_fail(_class_name,
|
||||
super_class_name,
|
||||
_loader_data->class_loader(),
|
||||
loader,
|
||||
_protection_domain,
|
||||
true,
|
||||
CHECK);
|
||||
@ -5964,6 +5968,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
|
||||
|
||||
_all_mirandas = new GrowableArray<Method*>(20);
|
||||
|
||||
Handle loader(THREAD, _loader_data->class_loader());
|
||||
klassVtable::compute_vtable_size_and_num_mirandas(&_vtable_size,
|
||||
&_num_miranda_methods,
|
||||
_all_mirandas,
|
||||
@ -5971,7 +5976,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
|
||||
_methods,
|
||||
_access_flags,
|
||||
_major_version,
|
||||
_loader_data->class_loader(),
|
||||
loader,
|
||||
_class_name,
|
||||
_local_interfaces,
|
||||
CHECK);
|
||||
|
||||
@ -1720,7 +1720,7 @@ void ClassLoader::create_javabase() {
|
||||
|
||||
{
|
||||
MutexLocker ml(Module_lock, THREAD);
|
||||
ModuleEntry* jb_module = null_cld_modules->locked_create_entry_or_null(Handle(NULL), vmSymbols::java_base(), NULL, NULL, null_cld);
|
||||
ModuleEntry* jb_module = null_cld_modules->locked_create_entry_or_null(Handle(), vmSymbols::java_base(), NULL, NULL, null_cld);
|
||||
if (jb_module == NULL) {
|
||||
vm_exit_during_initialization("Unable to create ModuleEntry for " JAVA_BASE_NAME);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -522,10 +522,9 @@ bool ClassLoaderData::is_platform_class_loader_data() const {
|
||||
// (boot, application/system or platform) class loaders. Note, the
|
||||
// builtin loaders are not freed by a GC.
|
||||
bool ClassLoaderData::is_builtin_class_loader_data() const {
|
||||
Handle classLoaderHandle = class_loader();
|
||||
return (is_the_null_class_loader_data() ||
|
||||
SystemDictionary::is_system_class_loader(classLoaderHandle) ||
|
||||
SystemDictionary::is_platform_class_loader(classLoaderHandle));
|
||||
SystemDictionary::is_system_class_loader(class_loader()) ||
|
||||
SystemDictionary::is_platform_class_loader(class_loader()));
|
||||
}
|
||||
|
||||
Metaspace* ClassLoaderData::metaspace_non_null() {
|
||||
@ -627,7 +626,8 @@ void ClassLoaderData::free_deallocate_list() {
|
||||
// These anonymous class loaders are to contain classes used for JSR292
|
||||
ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(oop loader, TRAPS) {
|
||||
// Add a new class loader data to the graph.
|
||||
return ClassLoaderDataGraph::add(loader, true, THREAD);
|
||||
Handle lh(THREAD, loader);
|
||||
return ClassLoaderDataGraph::add(lh, true, THREAD);
|
||||
}
|
||||
|
||||
const char* ClassLoaderData::loader_name() {
|
||||
@ -768,7 +768,7 @@ void ClassLoaderDataGraph::log_creation(Handle loader, ClassLoaderData* cld, TRA
|
||||
vmSymbols::void_string_signature(),
|
||||
CHECK);
|
||||
assert(result.get_type() == T_OBJECT, "just checking");
|
||||
string = (oop)result.get_jobject();
|
||||
string = Handle(THREAD, (oop)result.get_jobject());
|
||||
}
|
||||
|
||||
ResourceMark rm;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -260,7 +260,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice");
|
||||
|
||||
// We explicitly initialize the Dependencies object at a later phase in the initialization
|
||||
_the_null_class_loader_data = new ClassLoaderData((oop)NULL, false, Dependencies());
|
||||
_the_null_class_loader_data = new ClassLoaderData(Handle(), false, Dependencies());
|
||||
ClassLoaderDataGraph::_head = _the_null_class_loader_data;
|
||||
assert(_the_null_class_loader_data->is_the_null_class_loader_data(), "Must be");
|
||||
if (DumpSharedSpaces) {
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -61,7 +61,7 @@ Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
|
||||
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
|
||||
};
|
||||
|
||||
ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) {
|
||||
ProtectionDomainCacheEntry* Dictionary::cache_get(Handle protection_domain) {
|
||||
return _pd_cache_table->get(protection_domain);
|
||||
}
|
||||
|
||||
@ -123,9 +123,9 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
|
||||
}
|
||||
|
||||
|
||||
void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) {
|
||||
void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
if (!contains_protection_domain(protection_domain)) {
|
||||
if (!contains_protection_domain(protection_domain())) {
|
||||
ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
|
||||
ProtectionDomainEntry* new_head =
|
||||
new ProtectionDomainEntry(entry, _pd_set);
|
||||
@ -454,7 +454,7 @@ void Dictionary::add_protection_domain(int index, unsigned int hash,
|
||||
assert(protection_domain() != NULL,
|
||||
"real protection domain should be present");
|
||||
|
||||
entry->add_protection_domain(this, protection_domain());
|
||||
entry->add_protection_domain(this, protection_domain);
|
||||
|
||||
assert(entry->contains_protection_domain(protection_domain()),
|
||||
"now protection domain should be present");
|
||||
@ -505,11 +505,12 @@ void Dictionary::reorder_dictionary() {
|
||||
}
|
||||
|
||||
|
||||
unsigned int ProtectionDomainCacheTable::compute_hash(oop protection_domain) {
|
||||
unsigned int ProtectionDomainCacheTable::compute_hash(Handle protection_domain) {
|
||||
// Identity hash can safepoint, so keep protection domain in a Handle.
|
||||
return (unsigned int)(protection_domain->identity_hash());
|
||||
}
|
||||
|
||||
int ProtectionDomainCacheTable::index_for(oop protection_domain) {
|
||||
int ProtectionDomainCacheTable::index_for(Handle protection_domain) {
|
||||
return hash_to_index(compute_hash(protection_domain));
|
||||
}
|
||||
|
||||
@ -619,7 +620,7 @@ void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f) {
|
||||
}
|
||||
}
|
||||
|
||||
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domain) {
|
||||
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(Handle protection_domain) {
|
||||
unsigned int hash = compute_hash(protection_domain);
|
||||
int index = hash_to_index(hash);
|
||||
|
||||
@ -630,9 +631,9 @@ ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domai
|
||||
return entry;
|
||||
}
|
||||
|
||||
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oop protection_domain) {
|
||||
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, Handle protection_domain) {
|
||||
for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) {
|
||||
if (e->protection_domain() == protection_domain) {
|
||||
if (e->protection_domain() == protection_domain()) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@ -640,7 +641,7 @@ ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oo
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, oop protection_domain) {
|
||||
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, Handle protection_domain) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
assert(index == index_for(protection_domain), "incorrect index?");
|
||||
assert(find_entry(index, protection_domain) == NULL, "no double entry");
|
||||
@ -651,7 +652,7 @@ ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, uns
|
||||
}
|
||||
|
||||
void ProtectionDomainCacheTable::free(ProtectionDomainCacheEntry* to_delete) {
|
||||
unsigned int hash = compute_hash(to_delete->protection_domain());
|
||||
unsigned int hash = compute_hash(Handle(Thread::current(), to_delete->protection_domain()));
|
||||
int index = hash_to_index(hash);
|
||||
|
||||
ProtectionDomainCacheEntry** p = bucket_addr(index);
|
||||
@ -731,7 +732,6 @@ void SymbolPropertyTable::methods_do(void f(Method*)) {
|
||||
|
||||
void Dictionary::print(bool details) {
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
|
||||
if (details) {
|
||||
tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
|
||||
@ -777,7 +777,6 @@ void Dictionary::print(bool details) {
|
||||
void Dictionary::printPerformanceInfoDetails() {
|
||||
if (log_is_enabled(Info, hashtables)) {
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
|
||||
log_info(hashtables)(" ");
|
||||
log_info(hashtables)("Java system dictionary (table_size=%d, classes=%d)",
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -128,7 +128,7 @@ public:
|
||||
// Sharing support
|
||||
void reorder_dictionary();
|
||||
|
||||
ProtectionDomainCacheEntry* cache_get(oop protection_domain);
|
||||
ProtectionDomainCacheEntry* cache_get(Handle protection_domain);
|
||||
|
||||
void print(bool details = true);
|
||||
#ifdef ASSERT
|
||||
@ -194,23 +194,23 @@ private:
|
||||
return (ProtectionDomainCacheEntry**) Hashtable<oop, mtClass>::bucket_addr(i);
|
||||
}
|
||||
|
||||
ProtectionDomainCacheEntry* new_entry(unsigned int hash, oop protection_domain) {
|
||||
ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::new_entry(hash, protection_domain);
|
||||
ProtectionDomainCacheEntry* new_entry(unsigned int hash, Handle protection_domain) {
|
||||
ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::new_entry(hash, protection_domain());
|
||||
entry->init();
|
||||
return entry;
|
||||
}
|
||||
|
||||
static unsigned int compute_hash(oop protection_domain);
|
||||
static unsigned int compute_hash(Handle protection_domain);
|
||||
|
||||
int index_for(oop protection_domain);
|
||||
ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, oop protection_domain);
|
||||
ProtectionDomainCacheEntry* find_entry(int index, oop protection_domain);
|
||||
int index_for(Handle protection_domain);
|
||||
ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, Handle protection_domain);
|
||||
ProtectionDomainCacheEntry* find_entry(int index, Handle protection_domain);
|
||||
|
||||
public:
|
||||
|
||||
ProtectionDomainCacheTable(int table_size);
|
||||
|
||||
ProtectionDomainCacheEntry* get(oop protection_domain);
|
||||
ProtectionDomainCacheEntry* get(Handle protection_domain);
|
||||
void free(ProtectionDomainCacheEntry* entry);
|
||||
|
||||
void unlink(BoolObjectClosure* cl);
|
||||
@ -275,7 +275,7 @@ class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
|
||||
// Tells whether a protection is in the approved set.
|
||||
bool contains_protection_domain(oop protection_domain) const;
|
||||
// Adds a protection domain to the approved set.
|
||||
void add_protection_domain(Dictionary* dict, oop protection_domain);
|
||||
void add_protection_domain(Dictionary* dict, Handle protection_domain);
|
||||
|
||||
Klass* klass() const { return (Klass*)literal(); }
|
||||
Klass** klass_addr() { return (Klass**)literal_addr(); }
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -514,11 +514,10 @@ char* java_lang_String::as_quoted_ascii(oop java_string) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) {
|
||||
oop obj = java_string();
|
||||
typeArrayOop value = java_lang_String::value(obj);
|
||||
int length = java_lang_String::length(obj);
|
||||
bool is_latin1 = java_lang_String::is_latin1(obj);
|
||||
Symbol* java_lang_String::as_symbol(oop java_string, TRAPS) {
|
||||
typeArrayOop value = java_lang_String::value(java_string);
|
||||
int length = java_lang_String::length(java_string);
|
||||
bool is_latin1 = java_lang_String::is_latin1(java_string);
|
||||
if (!is_latin1) {
|
||||
jchar* base = (length == 0) ? NULL : value->char_at_addr(0);
|
||||
Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD);
|
||||
@ -753,7 +752,7 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) {
|
||||
}
|
||||
}
|
||||
}
|
||||
create_mirror(k, Handle(NULL), Handle(NULL), Handle(NULL), CHECK);
|
||||
create_mirror(k, Handle(), Handle(), Handle(), CHECK);
|
||||
}
|
||||
|
||||
void java_lang_Class::initialize_mirror_fields(KlassHandle k,
|
||||
@ -828,7 +827,8 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
|
||||
// the mirror.
|
||||
if (SystemDictionary::Class_klass_loaded()) {
|
||||
// Allocate mirror (java.lang.Class instance)
|
||||
Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK);
|
||||
oop mirror_oop = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK);
|
||||
Handle mirror(THREAD, mirror_oop);
|
||||
|
||||
// Setup indirection from mirror->klass
|
||||
if (!k.is_null()) {
|
||||
@ -842,7 +842,7 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
|
||||
|
||||
// It might also have a component mirror. This mirror must already exist.
|
||||
if (k->is_array_klass()) {
|
||||
Handle comp_mirror;
|
||||
oop comp_mirror;
|
||||
if (k->is_typeArray_klass()) {
|
||||
BasicType type = TypeArrayKlass::cast(k())->element_type();
|
||||
comp_mirror = Universe::java_mirror(type);
|
||||
@ -852,12 +852,12 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
|
||||
assert(element_klass != NULL, "Must have an element klass");
|
||||
comp_mirror = element_klass->java_mirror();
|
||||
}
|
||||
assert(comp_mirror.not_null(), "must have a mirror");
|
||||
assert(comp_mirror != NULL, "must have a mirror");
|
||||
|
||||
// Two-way link between the array klass and its component mirror:
|
||||
// (array_klass) k -> mirror -> component_mirror -> array_klass -> k
|
||||
set_component_mirror(mirror(), comp_mirror());
|
||||
set_array_klass(comp_mirror(), k());
|
||||
set_component_mirror(mirror(), comp_mirror);
|
||||
set_array_klass(comp_mirror, k());
|
||||
} else {
|
||||
assert(k->is_instance_klass(), "Must be");
|
||||
|
||||
@ -1518,7 +1518,7 @@ void java_lang_Throwable::set_depth(oop throwable, int value) {
|
||||
throwable->int_field_put(depth_offset, value);
|
||||
}
|
||||
|
||||
oop java_lang_Throwable::message(Handle throwable) {
|
||||
oop java_lang_Throwable::message(oop throwable) {
|
||||
return throwable->obj_field(detailMessage_offset);
|
||||
}
|
||||
|
||||
@ -1547,7 +1547,7 @@ void java_lang_Throwable::clear_stacktrace(oop throwable) {
|
||||
}
|
||||
|
||||
|
||||
void java_lang_Throwable::print(Handle throwable, outputStream* st) {
|
||||
void java_lang_Throwable::print(oop throwable, outputStream* st) {
|
||||
ResourceMark rm;
|
||||
Klass* k = throwable->klass();
|
||||
assert(k != NULL, "just checking");
|
||||
@ -1578,7 +1578,7 @@ class BacktraceBuilder: public StackObj {
|
||||
typeArrayOop _methods;
|
||||
typeArrayOop _bcis;
|
||||
objArrayOop _mirrors;
|
||||
typeArrayOop _cprefs; // needed to insulate method name against redefinition
|
||||
typeArrayOop _names; // needed to insulate method name against redefinition
|
||||
int _index;
|
||||
NoSafepointVerifier _nsv;
|
||||
|
||||
@ -1586,7 +1586,7 @@ class BacktraceBuilder: public StackObj {
|
||||
trace_methods_offset = java_lang_Throwable::trace_methods_offset,
|
||||
trace_bcis_offset = java_lang_Throwable::trace_bcis_offset,
|
||||
trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset,
|
||||
trace_cprefs_offset = java_lang_Throwable::trace_cprefs_offset,
|
||||
trace_names_offset = java_lang_Throwable::trace_names_offset,
|
||||
trace_next_offset = java_lang_Throwable::trace_next_offset,
|
||||
trace_size = java_lang_Throwable::trace_size,
|
||||
trace_chunk_size = java_lang_Throwable::trace_chunk_size
|
||||
@ -1608,32 +1608,34 @@ class BacktraceBuilder: public StackObj {
|
||||
assert(mirrors != NULL, "mirror array should be initialized in backtrace");
|
||||
return mirrors;
|
||||
}
|
||||
static typeArrayOop get_cprefs(objArrayHandle chunk) {
|
||||
typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset));
|
||||
assert(cprefs != NULL, "cprefs array should be initialized in backtrace");
|
||||
return cprefs;
|
||||
static typeArrayOop get_names(objArrayHandle chunk) {
|
||||
typeArrayOop names = typeArrayOop(chunk->obj_at(trace_names_offset));
|
||||
assert(names != NULL, "names array should be initialized in backtrace");
|
||||
return names;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// constructor for new backtrace
|
||||
BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) {
|
||||
BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _names(NULL) {
|
||||
expand(CHECK);
|
||||
_backtrace = _head;
|
||||
_backtrace = Handle(THREAD, _head);
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
BacktraceBuilder(objArrayHandle backtrace) {
|
||||
BacktraceBuilder(Thread* thread, objArrayHandle backtrace) {
|
||||
_methods = get_methods(backtrace);
|
||||
_bcis = get_bcis(backtrace);
|
||||
_mirrors = get_mirrors(backtrace);
|
||||
_cprefs = get_cprefs(backtrace);
|
||||
_names = get_names(backtrace);
|
||||
assert(_methods->length() == _bcis->length() &&
|
||||
_methods->length() == _mirrors->length(),
|
||||
_methods->length() == _mirrors->length() &&
|
||||
_mirrors->length() == _names->length(),
|
||||
"method and source information arrays should match");
|
||||
|
||||
// head is the preallocated backtrace
|
||||
_backtrace = _head = backtrace();
|
||||
_head = backtrace();
|
||||
_backtrace = Handle(thread, _head);
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
@ -1653,8 +1655,8 @@ class BacktraceBuilder: public StackObj {
|
||||
objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK);
|
||||
objArrayHandle new_mirrors(THREAD, mirrors);
|
||||
|
||||
typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK);
|
||||
typeArrayHandle new_cprefs(THREAD, cprefs);
|
||||
typeArrayOop names = oopFactory::new_symbolArray(trace_chunk_size, CHECK);
|
||||
typeArrayHandle new_names(THREAD, names);
|
||||
|
||||
if (!old_head.is_null()) {
|
||||
old_head->obj_at_put(trace_next_offset, new_head());
|
||||
@ -1662,13 +1664,13 @@ class BacktraceBuilder: public StackObj {
|
||||
new_head->obj_at_put(trace_methods_offset, new_methods());
|
||||
new_head->obj_at_put(trace_bcis_offset, new_bcis());
|
||||
new_head->obj_at_put(trace_mirrors_offset, new_mirrors());
|
||||
new_head->obj_at_put(trace_cprefs_offset, new_cprefs());
|
||||
new_head->obj_at_put(trace_names_offset, new_names());
|
||||
|
||||
_head = new_head();
|
||||
_methods = new_methods();
|
||||
_bcis = new_bcis();
|
||||
_mirrors = new_mirrors();
|
||||
_cprefs = new_cprefs();
|
||||
_names = new_names();
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
@ -1690,7 +1692,11 @@ class BacktraceBuilder: public StackObj {
|
||||
|
||||
_methods->short_at_put(_index, method->orig_method_idnum());
|
||||
_bcis->int_at_put(_index, Backtrace::merge_bci_and_version(bci, method->constants()->version()));
|
||||
_cprefs->short_at_put(_index, method->name_index());
|
||||
|
||||
// Note:this doesn't leak symbols because the mirror in the backtrace keeps the
|
||||
// klass owning the symbols alive so their refcounts aren't decremented.
|
||||
Symbol* name = method->name();
|
||||
_names->symbol_at_put(_index, name);
|
||||
|
||||
// We need to save the mirrors in the backtrace to keep the class
|
||||
// from being unloaded while we still have this stack trace.
|
||||
@ -1705,10 +1711,10 @@ struct BacktraceElement : public StackObj {
|
||||
int _method_id;
|
||||
int _bci;
|
||||
int _version;
|
||||
int _cpref;
|
||||
Symbol* _name;
|
||||
Handle _mirror;
|
||||
BacktraceElement(Handle mirror, int mid, int version, int bci, int cpref) :
|
||||
_mirror(mirror), _method_id(mid), _version(version), _bci(bci), _cpref(cpref) {}
|
||||
BacktraceElement(Handle mirror, int mid, int version, int bci, Symbol* name) :
|
||||
_mirror(mirror), _method_id(mid), _version(version), _bci(bci), _name(name) {}
|
||||
};
|
||||
|
||||
class BacktraceIterator : public StackObj {
|
||||
@ -1717,7 +1723,7 @@ class BacktraceIterator : public StackObj {
|
||||
objArrayHandle _mirrors;
|
||||
typeArrayHandle _methods;
|
||||
typeArrayHandle _bcis;
|
||||
typeArrayHandle _cprefs;
|
||||
typeArrayHandle _names;
|
||||
|
||||
void init(objArrayHandle result, Thread* thread) {
|
||||
// Get method id, bci, version and mirror from chunk
|
||||
@ -1726,7 +1732,7 @@ class BacktraceIterator : public StackObj {
|
||||
_methods = typeArrayHandle(thread, BacktraceBuilder::get_methods(_result));
|
||||
_bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result));
|
||||
_mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result));
|
||||
_cprefs = typeArrayHandle(thread, BacktraceBuilder::get_cprefs(_result));
|
||||
_names = typeArrayHandle(thread, BacktraceBuilder::get_names(_result));
|
||||
_index = 0;
|
||||
}
|
||||
}
|
||||
@ -1741,7 +1747,7 @@ class BacktraceIterator : public StackObj {
|
||||
_methods->short_at(_index),
|
||||
Backtrace::version_at(_bcis->int_at(_index)),
|
||||
Backtrace::bci_at(_bcis->int_at(_index)),
|
||||
_cprefs->short_at(_index));
|
||||
_names->symbol_at(_index));
|
||||
_index++;
|
||||
|
||||
if (_index >= java_lang_Throwable::trace_chunk_size) {
|
||||
@ -1761,7 +1767,7 @@ class BacktraceIterator : public StackObj {
|
||||
|
||||
// Print stack trace element to resource allocated buffer
|
||||
static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id,
|
||||
int version, int bci, int cpref) {
|
||||
int version, int bci, Symbol* name) {
|
||||
ResourceMark rm;
|
||||
|
||||
// Get strings and string lengths
|
||||
@ -1769,11 +1775,7 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m
|
||||
const char* klass_name = holder->external_name();
|
||||
int buf_len = (int)strlen(klass_name);
|
||||
|
||||
Method* method = holder->method_with_orig_idnum(method_id, version);
|
||||
|
||||
// The method can be NULL if the requested class version is gone
|
||||
Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
|
||||
char* method_name = sym->as_C_string();
|
||||
char* method_name = name->as_C_string();
|
||||
buf_len += (int)strlen(method_name);
|
||||
|
||||
char* source_file_name = NULL;
|
||||
@ -1809,6 +1811,8 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m
|
||||
}
|
||||
}
|
||||
|
||||
// The method can be NULL if the requested class version is gone
|
||||
Method* method = holder->method_with_orig_idnum(method_id, version);
|
||||
if (!version_matches(method, version)) {
|
||||
strcat(buf, "Redefined)");
|
||||
} else {
|
||||
@ -1837,11 +1841,10 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m
|
||||
}
|
||||
|
||||
void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) {
|
||||
Handle mirror = method->method_holder()->java_mirror();
|
||||
Handle mirror (Thread::current(), method->method_holder()->java_mirror());
|
||||
int method_id = method->orig_method_idnum();
|
||||
int version = method->constants()->version();
|
||||
int cpref = method->name_index();
|
||||
print_stack_element_to_stream(st, mirror, method_id, version, bci, cpref);
|
||||
print_stack_element_to_stream(st, mirror, method_id, version, bci, method->name());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1850,7 +1853,7 @@ void java_lang_Throwable::print_stack_element(outputStream *st, const methodHand
|
||||
*/
|
||||
void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) {
|
||||
// First, print the message.
|
||||
print(throwable, st);
|
||||
print(throwable(), st);
|
||||
st->cr();
|
||||
|
||||
// Now print the stack trace.
|
||||
@ -1865,7 +1868,7 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st)
|
||||
|
||||
while (iter.repeat()) {
|
||||
BacktraceElement bte = iter.next(THREAD);
|
||||
print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._cpref);
|
||||
print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._name);
|
||||
}
|
||||
{
|
||||
// Call getCause() which doesn't necessarily return the _cause field.
|
||||
@ -1885,7 +1888,7 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st)
|
||||
throwable = Handle(THREAD, (oop) cause.get_jobject());
|
||||
if (throwable.not_null()) {
|
||||
st->print("Caused by: ");
|
||||
print(throwable, st);
|
||||
print(throwable(), st);
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
@ -2089,7 +2092,7 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t
|
||||
ResourceMark rm(THREAD);
|
||||
vframeStream st(THREAD);
|
||||
|
||||
BacktraceBuilder bt(backtrace);
|
||||
BacktraceBuilder bt(THREAD, backtrace);
|
||||
|
||||
// Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init
|
||||
// methods as preallocated errors aren't created by "java" code.
|
||||
@ -2144,7 +2147,7 @@ void java_lang_Throwable::get_stack_trace_elements(Handle throwable,
|
||||
method,
|
||||
bte._version,
|
||||
bte._bci,
|
||||
bte._cpref, CHECK);
|
||||
bte._name, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2159,15 +2162,14 @@ oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRA
|
||||
|
||||
Handle element = ik->allocate_instance_handle(CHECK_0);
|
||||
|
||||
int cpref = method->name_index();
|
||||
int version = method->constants()->version();
|
||||
fill_in(element, method->method_holder(), method, version, bci, cpref, CHECK_0);
|
||||
fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_0);
|
||||
return element();
|
||||
}
|
||||
|
||||
void java_lang_StackTraceElement::fill_in(Handle element,
|
||||
InstanceKlass* holder, const methodHandle& method,
|
||||
int version, int bci, int cpref, TRAPS) {
|
||||
int version, int bci, Symbol* name, TRAPS) {
|
||||
assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check");
|
||||
|
||||
// Fill in class name
|
||||
@ -2184,11 +2186,8 @@ void java_lang_StackTraceElement::fill_in(Handle element,
|
||||
java_lang_StackTraceElement::set_classLoaderName(element(), loader_name);
|
||||
}
|
||||
|
||||
// The method can be NULL if the requested class version is gone
|
||||
Symbol* sym = !method.is_null() ? method->name() : holder->constants()->symbol_at(cpref);
|
||||
|
||||
// Fill in method name
|
||||
oop methodname = StringTable::intern(sym, CHECK);
|
||||
oop methodname = StringTable::intern(name, CHECK);
|
||||
java_lang_StackTraceElement::set_methodName(element(), methodname);
|
||||
|
||||
// Fill in module name and version
|
||||
@ -2205,7 +2204,7 @@ void java_lang_StackTraceElement::fill_in(Handle element,
|
||||
java_lang_StackTraceElement::set_moduleVersion(element(), module_version);
|
||||
}
|
||||
|
||||
if (!version_matches(method(), version)) {
|
||||
if (method() == NULL || !version_matches(method(), version)) {
|
||||
// The method was redefined, accurate line number information isn't available
|
||||
java_lang_StackTraceElement::set_fileName(element(), NULL);
|
||||
java_lang_StackTraceElement::set_lineNumber(element(), -1);
|
||||
@ -2232,7 +2231,7 @@ Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* h
|
||||
|
||||
void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) {
|
||||
// set Method* or mid/cpref
|
||||
oop mname = stackFrame->obj_field(_memberName_offset);
|
||||
Handle mname(Thread::current(), stackFrame->obj_field(_memberName_offset));
|
||||
InstanceKlass* ik = method->method_holder();
|
||||
CallInfo info(method(), ik);
|
||||
MethodHandles::init_method_MemberName(mname, info);
|
||||
@ -2252,8 +2251,8 @@ void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle
|
||||
|
||||
short version = stackFrame->short_field(_version_offset);
|
||||
short bci = stackFrame->short_field(_bci_offset);
|
||||
int cpref = method->name_index();
|
||||
java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, cpref, CHECK);
|
||||
Symbol* name = method->name();
|
||||
java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, name, CHECK);
|
||||
}
|
||||
|
||||
void java_lang_StackFrameInfo::compute_offsets() {
|
||||
@ -3966,7 +3965,6 @@ bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant,
|
||||
|
||||
void JavaClasses::check_offsets() {
|
||||
bool valid = true;
|
||||
HandleMark hm;
|
||||
|
||||
#define CHECK_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
|
||||
valid &= check_offset(klass_name, cpp_klass_name :: field_name ## _offset, #field_name, field_sig)
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -155,7 +155,7 @@ class java_lang_String : AllStatic {
|
||||
static Handle internalize_classname(Handle java_string, TRAPS) { return char_converter(java_string, '.', '/', THREAD); }
|
||||
|
||||
// Conversion
|
||||
static Symbol* as_symbol(Handle java_string, TRAPS);
|
||||
static Symbol* as_symbol(oop java_string, TRAPS);
|
||||
static Symbol* as_symbol_or_null(oop java_string);
|
||||
|
||||
// Testers
|
||||
@ -457,7 +457,7 @@ class java_lang_Throwable: AllStatic {
|
||||
trace_methods_offset = 0,
|
||||
trace_bcis_offset = 1,
|
||||
trace_mirrors_offset = 2,
|
||||
trace_cprefs_offset = 3,
|
||||
trace_names_offset = 3,
|
||||
trace_next_offset = 4,
|
||||
trace_size = 5,
|
||||
trace_chunk_size = 32
|
||||
@ -485,7 +485,7 @@ class java_lang_Throwable: AllStatic {
|
||||
static int get_backtrace_offset() { return backtrace_offset;}
|
||||
static int get_detailMessage_offset() { return detailMessage_offset;}
|
||||
// Message
|
||||
static oop message(Handle throwable);
|
||||
static oop message(oop throwable);
|
||||
static void set_message(oop throwable, oop value);
|
||||
static Symbol* detail_message(oop throwable);
|
||||
static void print_stack_element(outputStream *st, const methodHandle& method, int bci);
|
||||
@ -503,7 +503,7 @@ class java_lang_Throwable: AllStatic {
|
||||
// Programmatic access to stack trace
|
||||
static void get_stack_trace_elements(Handle throwable, objArrayHandle stack_trace, TRAPS);
|
||||
// Printing
|
||||
static void print(Handle throwable, outputStream* st);
|
||||
static void print(oop throwable, outputStream* st);
|
||||
static void print_stack_trace(Handle throwable, outputStream* st);
|
||||
static void java_printStackTrace(Handle throwable, TRAPS);
|
||||
// Debugging
|
||||
@ -1322,7 +1322,7 @@ class java_lang_StackTraceElement: AllStatic {
|
||||
static oop create(const methodHandle& method, int bci, TRAPS);
|
||||
|
||||
static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method,
|
||||
int version, int bci, int cpref, TRAPS);
|
||||
int version, int bci, Symbol* name, TRAPS);
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -81,7 +81,7 @@ void ModuleEntry::set_version(Symbol* version) {
|
||||
|
||||
// Returns the shared ProtectionDomain
|
||||
Handle ModuleEntry::shared_protection_domain() {
|
||||
return Handle(JNIHandles::resolve(_pd));
|
||||
return Handle(Thread::current(), JNIHandles::resolve(_pd));
|
||||
}
|
||||
|
||||
// Set the shared ProtectionDomain atomically
|
||||
@ -269,12 +269,12 @@ void ModuleEntryTable::create_unnamed_module(ClassLoaderData* loader_data) {
|
||||
// For the boot loader, the java.lang.reflect.Module for the unnamed module
|
||||
// is not known until a call to JVM_SetBootLoaderUnnamedModule is made. At
|
||||
// this point initially create the ModuleEntry for the unnamed module.
|
||||
_unnamed_module = new_entry(0, Handle(NULL), NULL, NULL, NULL, loader_data);
|
||||
_unnamed_module = new_entry(0, Handle(), NULL, NULL, NULL, loader_data);
|
||||
} else {
|
||||
// For all other class loaders the java.lang.reflect.Module for their
|
||||
// corresponding unnamed module can be found in the java.lang.ClassLoader object.
|
||||
oop module = java_lang_ClassLoader::unnamedModule(loader_data->class_loader());
|
||||
_unnamed_module = new_entry(0, Handle(module), NULL, NULL, NULL, loader_data);
|
||||
_unnamed_module = new_entry(0, Handle(Thread::current(), module), NULL, NULL, NULL, loader_data);
|
||||
|
||||
// Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module
|
||||
// object.
|
||||
|
||||
@ -186,7 +186,7 @@ static void define_javabase_module(jobject module, jstring version,
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"Class loader must be the boot class loader");
|
||||
}
|
||||
Handle h_loader = Handle(THREAD, loader);
|
||||
Handle h_loader(THREAD, loader);
|
||||
|
||||
// Ensure the boot loader's PackageEntryTable has been created
|
||||
PackageEntryTable* package_table = get_package_entry_table(h_loader, CHECK);
|
||||
@ -324,7 +324,7 @@ void Modules::define_module(jobject module, jstring version,
|
||||
|
||||
// Only modules defined to either the boot or platform class loader, can define a "java/" package.
|
||||
if (!h_loader.is_null() &&
|
||||
!SystemDictionary::is_platform_class_loader(h_loader) &&
|
||||
!SystemDictionary::is_platform_class_loader(h_loader()) &&
|
||||
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
|
||||
const char* class_loader_name = SystemDictionary::loader_name(h_loader());
|
||||
size_t pkg_len = strlen(package_name);
|
||||
@ -484,7 +484,7 @@ void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"Class loader must be the boot class loader");
|
||||
}
|
||||
Handle h_loader = Handle(THREAD, loader);
|
||||
Handle h_loader(THREAD, loader);
|
||||
|
||||
log_debug(modules)("set_bootloader_unnamed_module(): recording unnamed module for boot loader");
|
||||
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -236,6 +236,7 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
|
||||
assert(!Universe::heap()->is_in_reserved(name),
|
||||
"proposed name of symbol must be stable");
|
||||
|
||||
HandleMark hm(THREAD); // cleanup strings created
|
||||
Handle string;
|
||||
// try to reuse the string if possible
|
||||
if (!string_or_null.is_null()) {
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -160,17 +160,17 @@ bool SystemDictionary::is_parallelDefine(Handle class_loader) {
|
||||
// Returns true if the passed class loader is the builtin application class loader
|
||||
// or a custom system class loader. A customer system class loader can be
|
||||
// specified via -Djava.system.class.loader.
|
||||
bool SystemDictionary::is_system_class_loader(Handle class_loader) {
|
||||
if (class_loader.is_null()) {
|
||||
bool SystemDictionary::is_system_class_loader(oop class_loader) {
|
||||
if (class_loader == NULL) {
|
||||
return false;
|
||||
}
|
||||
return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass() ||
|
||||
class_loader() == _java_system_loader);
|
||||
class_loader == _java_system_loader);
|
||||
}
|
||||
|
||||
// Returns true if the passed class loader is the platform class loader.
|
||||
bool SystemDictionary::is_platform_class_loader(Handle class_loader) {
|
||||
if (class_loader.is_null()) {
|
||||
bool SystemDictionary::is_platform_class_loader(oop class_loader) {
|
||||
if (class_loader == NULL) {
|
||||
return false;
|
||||
}
|
||||
return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass());
|
||||
@ -662,6 +662,8 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
|
||||
Ticks class_load_start_time = Ticks::now();
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
|
||||
// Fix for 4474172; see evaluation for more details
|
||||
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
|
||||
ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL);
|
||||
@ -1103,6 +1105,8 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
ClassFileStream* st,
|
||||
TRAPS) {
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
|
||||
// Classloaders that support parallelism, e.g. bootstrap classloader,
|
||||
// or all classloaders with UnsyncloadClass do not acquire lock here
|
||||
bool DoObjectLock = true;
|
||||
@ -1381,6 +1385,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
||||
|
||||
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
|
||||
{
|
||||
HandleMark hm(THREAD);
|
||||
Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
|
||||
check_loader_lock_contention(lockObject, THREAD);
|
||||
ObjectLocker ol(lockObject, THREAD, true);
|
||||
@ -1601,6 +1606,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha
|
||||
|
||||
void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) {
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
ClassLoaderData* loader_data = k->class_loader_data();
|
||||
Handle class_loader_h(THREAD, loader_data->class_loader());
|
||||
|
||||
@ -2608,8 +2614,9 @@ methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass,
|
||||
SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty));
|
||||
|
||||
int ref_kind = JVM_REF_invokeVirtual;
|
||||
Handle name_str = StringTable::intern(name, CHECK_(empty));
|
||||
objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
|
||||
oop name_oop = StringTable::intern(name, CHECK_(empty));
|
||||
Handle name_str (THREAD, name_oop);
|
||||
objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty));
|
||||
assert(appendix_box->obj_at(0) == NULL, "");
|
||||
|
||||
// This should not happen. JDK code should take care of that.
|
||||
@ -2619,12 +2626,12 @@ methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass,
|
||||
|
||||
// call java.lang.invoke.MethodHandleNatives::linkMethod(... String, MethodType) -> MemberName
|
||||
JavaCallArguments args;
|
||||
args.push_oop(accessing_klass()->java_mirror());
|
||||
args.push_oop(Handle(THREAD, accessing_klass()->java_mirror()));
|
||||
args.push_int(ref_kind);
|
||||
args.push_oop(klass()->java_mirror());
|
||||
args.push_oop(name_str());
|
||||
args.push_oop(method_type());
|
||||
args.push_oop(appendix_box());
|
||||
args.push_oop(Handle(THREAD, klass()->java_mirror()));
|
||||
args.push_oop(name_str);
|
||||
args.push_oop(method_type);
|
||||
args.push_oop(appendix_box);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::MethodHandleNatives_klass(),
|
||||
@ -2682,7 +2689,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
|
||||
}
|
||||
bool can_be_cached = true;
|
||||
int npts = ArgumentCount(signature).size();
|
||||
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
|
||||
objArrayHandle pts = oopFactory::new_objArray_handle(SystemDictionary::Class_klass(), npts, CHECK_(empty));
|
||||
int arg = 0;
|
||||
Handle rt; // the return type from the signature
|
||||
ResourceMark rm(THREAD);
|
||||
@ -2725,7 +2732,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
|
||||
|
||||
// call java.lang.invoke.MethodHandleNatives::findMethodHandleType(Class rt, Class[] pts) -> MethodType
|
||||
JavaCallArguments args(Handle(THREAD, rt()));
|
||||
args.push_oop(pts());
|
||||
args.push_oop(pts);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::MethodHandleNatives_klass(),
|
||||
@ -2768,7 +2775,8 @@ Handle SystemDictionary::link_method_handle_constant(KlassHandle caller,
|
||||
ResourceMark rm(THREAD);
|
||||
SignatureStream ss(signature, false);
|
||||
if (!ss.is_done()) {
|
||||
oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(),
|
||||
oop mirror = ss.as_java_mirror(Handle(THREAD, caller->class_loader()),
|
||||
Handle(THREAD, caller->protection_domain()),
|
||||
SignatureStream::NCDFError, CHECK_(empty));
|
||||
type = Handle(THREAD, mirror);
|
||||
ss.next();
|
||||
@ -2781,11 +2789,11 @@ Handle SystemDictionary::link_method_handle_constant(KlassHandle caller,
|
||||
|
||||
// call java.lang.invoke.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle
|
||||
JavaCallArguments args;
|
||||
args.push_oop(caller->java_mirror()); // the referring class
|
||||
args.push_oop(Handle(THREAD, caller->java_mirror())); // the referring class
|
||||
args.push_int(ref_kind);
|
||||
args.push_oop(callee->java_mirror()); // the target class
|
||||
args.push_oop(name());
|
||||
args.push_oop(type());
|
||||
args.push_oop(Handle(THREAD, callee->java_mirror())); // the target class
|
||||
args.push_oop(name);
|
||||
args.push_oop(type);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::MethodHandleNatives_klass(),
|
||||
@ -2832,16 +2840,16 @@ methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller
|
||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty);
|
||||
}
|
||||
|
||||
objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
|
||||
objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty));
|
||||
assert(appendix_box->obj_at(0) == NULL, "");
|
||||
|
||||
// call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, bsm, name, mtype, info, &appendix)
|
||||
JavaCallArguments args;
|
||||
args.push_oop(caller->java_mirror());
|
||||
args.push_oop(bsm());
|
||||
args.push_oop(method_name());
|
||||
args.push_oop(method_type());
|
||||
args.push_oop(info());
|
||||
args.push_oop(Handle(THREAD, caller->java_mirror()));
|
||||
args.push_oop(bsm);
|
||||
args.push_oop(method_name);
|
||||
args.push_oop(method_type);
|
||||
args.push_oop(info);
|
||||
args.push_oop(appendix_box);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -657,8 +657,8 @@ public:
|
||||
static instanceKlassHandle load_shared_class(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
TRAPS);
|
||||
static bool is_system_class_loader(Handle class_loader);
|
||||
static bool is_platform_class_loader(Handle class_loader);
|
||||
static bool is_system_class_loader(oop class_loader);
|
||||
static bool is_platform_class_loader(oop class_loader);
|
||||
|
||||
protected:
|
||||
static Klass* find_shared_class(Symbol* class_name);
|
||||
|
||||
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,6 +44,7 @@ VerificationType VerificationType::from_tag(u1 tag) {
|
||||
|
||||
bool VerificationType::resolve_and_check_assignability(instanceKlassHandle klass, Symbol* name,
|
||||
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object, TRAPS) {
|
||||
HandleMark hm(THREAD);
|
||||
Klass* obj = SystemDictionary::resolve_or_fail(
|
||||
name, Handle(THREAD, klass->class_loader()),
|
||||
Handle(THREAD, klass->protection_domain()), true, CHECK_false);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -126,7 +126,7 @@ void Verifier::log_end_verification(outputStream* st, const char* klassName, Sym
|
||||
}
|
||||
|
||||
bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) {
|
||||
HandleMark hm;
|
||||
HandleMark hm(THREAD);
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
// Eagerly allocate the identity hash code for a klass. This is a fallout
|
||||
@ -1991,6 +1991,7 @@ void ClassVerifier::class_format_error(const char* msg, ...) {
|
||||
}
|
||||
|
||||
Klass* ClassVerifier::load_class(Symbol* name, TRAPS) {
|
||||
HandleMark hm(THREAD);
|
||||
// Get current loader and protection domain first.
|
||||
oop loader = current_class()->class_loader();
|
||||
oop protection_domain = current_class()->protection_domain();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -209,7 +209,6 @@ const ImmutableOopMap* CodeBlob::oop_map_for_return_address(address return_addre
|
||||
}
|
||||
|
||||
void CodeBlob::print_code() {
|
||||
HandleMark hm;
|
||||
ResourceMark m;
|
||||
Disassembler::decode(this, tty);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user