blob: d6d69cb439aa8b704ce5ea3c51f29aca04a93444 [file] [log] [blame]
/*
* 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;
}