summaryrefslogtreecommitdiffstats
path: root/sal/osl/android/jni/lo-bootstrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/android/jni/lo-bootstrap.c')
-rw-r--r--sal/osl/android/jni/lo-bootstrap.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/sal/osl/android/jni/lo-bootstrap.c b/sal/osl/android/jni/lo-bootstrap.c
new file mode 100644
index 000000000000..3905c51db1a9
--- /dev/null
+++ b/sal/osl/android/jni/lo-bootstrap.c
@@ -0,0 +1,265 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http: *www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * Copyright (C) 2011 Tor Lillqvist <tml@iki.fi> (initial developer)
+ * Copyright (C) 2011 SUSE Linux http://suse.com (initial developer's employer)
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <jni.h>
+#include <linux/elf.h>
+#include <android/log.h>
+
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "lo-bootstrap", __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "lo-bootstrap", __VA_ARGS__))
+
+static char *
+read_section(JNIEnv *env,
+ int fd,
+ Elf32_Shdr *shdr)
+{
+ char *result;
+
+ result = malloc(shdr->sh_size);
+ if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) {
+ close(fd);
+ free(result);
+ return NULL;
+ }
+ if (read(fd, result, shdr->sh_size) < shdr->sh_size) {
+ close(fd);
+ free(result);
+ return NULL;
+ }
+
+ return result;
+}
+
+jobjectArray
+Java_org_libreoffice_android_Bootstrap_dlneeds( JNIEnv* env,
+ jobject clazz,
+ jstring library)
+{
+ int i, fd;
+ int n_needed;
+ const jbyte *libName;
+ jobjectArray result;
+ char *shstrtab, *dynstr;
+ Elf32_Ehdr hdr;
+ Elf32_Shdr shdr;
+ Elf32_Dyn dyn;
+
+ /* Open library and read ELF header */
+
+ libName = (*env)->GetStringUTFChars(env, library, NULL);
+
+ LOGI("dlneeds(%s)\n", libName);
+
+ fd = open (libName, O_RDONLY);
+ if (fd == -1) {
+ LOGI("Could not open library");
+ return NULL;
+ }
+
+ if (read(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
+ close(fd);
+ LOGI("Could not read ELF header");
+ return NULL;
+ }
+
+ /* Read in .shstrtab */
+
+ if (lseek(fd, hdr.e_shoff + hdr.e_shstrndx * sizeof(shdr), SEEK_SET) < 0) {
+ close(fd);
+ LOGI("Could not seek to .shstrtab section header");
+ return NULL;
+ }
+ if (read(fd, &shdr, sizeof(shdr)) < sizeof(shdr)) {
+ close(fd);
+ LOGI("Could not read section header");
+ return NULL;
+ }
+
+ shstrtab = read_section(env, fd, &shdr);
+ if (shstrtab == NULL)
+ return NULL;
+
+ /* Read section headers, looking for .dynstr section */
+
+ if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) {
+ close(fd);
+ LOGI("Could not seek to section headers");
+ return NULL;
+ }
+ for (i = 0; i < hdr.e_shnum; i++) {
+ if (read(fd, &shdr, sizeof(shdr)) < sizeof(shdr)) {
+ close(fd);
+ LOGI("Could not read section header");
+ return NULL;
+ }
+ if (shdr.sh_type == SHT_STRTAB &&
+ strcmp(shstrtab + shdr.sh_name, ".dynstr") == 0) {
+ dynstr = read_section(env, fd, &shdr);
+ if (dynstr == NULL) {
+ free(shstrtab);
+ return NULL;
+ }
+ break;
+ }
+ }
+
+ if (i == hdr.e_shnum) {
+ close(fd);
+ LOGI("No .dynstr section");
+ return NULL;
+ }
+
+ /* Read section headers, looking for .dynamic section */
+
+ if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) {
+ close(fd);
+ LOGI("Could not seek to section headers");
+ return NULL;
+ }
+ for (i = 0; i < hdr.e_shnum; i++) {
+ if (read(fd, &shdr, sizeof(shdr)) < sizeof(shdr)) {
+ close(fd);
+ LOGI("Could not read section header");
+ return NULL;
+ }
+ if (shdr.sh_type == SHT_DYNAMIC) {
+ int dynoff;
+ int *libnames;
+ jclass String;
+
+ /* Count number of DT_NEEDED entries */
+ n_needed = 0;
+ if (lseek(fd, shdr.sh_offset, SEEK_SET) < 0) {
+ close(fd);
+ LOGI("Could not seek to .dynamic section");
+ return NULL;
+ }
+ for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) {
+ if (read(fd, &dyn, sizeof(dyn)) < sizeof(dyn)) {
+ close(fd);
+ LOGI("Could not read .dynamic entry");
+ return NULL;
+ }
+ if (dyn.d_tag == DT_NEEDED)
+ n_needed++;
+ }
+
+ LOGI("Found %d DT_NEEDED libs", n_needed);
+
+ /* Allocate return value */
+
+ String = (*env)->FindClass(env, "java/lang/String");
+ if (String == NULL) {
+ close(fd);
+ LOGI("Could not find the String class");
+ return NULL;
+ }
+
+ result = (*env)->NewObjectArray(env, n_needed, String, NULL);
+ if (result == NULL) {
+ close (fd);
+ LOGI("Could not create the String array");
+ return NULL;
+ }
+
+ n_needed = 0;
+ if (lseek(fd, shdr.sh_offset, SEEK_SET) < 0) {
+ close(fd);
+ LOGI("Could not seek to .dynamic section");
+ return NULL;
+ }
+ for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) {
+ if (read(fd, &dyn, sizeof(dyn)) < sizeof(dyn)) {
+ close(fd);
+ LOGI("Could not read .dynamic entry");
+ return NULL;
+ }
+ if (dyn.d_tag == DT_NEEDED) {
+ LOGI("needs: %s\n", dynstr + dyn.d_un.d_val);
+ (*env)->SetObjectArrayElement(env, result, n_needed, (*env)->NewStringUTF(env, dynstr + dyn.d_un.d_val));
+ n_needed++;
+ }
+ }
+
+ close(fd);
+ free(dynstr);
+ free(shstrtab);
+ return result;
+ }
+ }
+
+ return NULL;
+}
+
+jint
+Java_org_libreoffice_android_Bootstrap_dlopen(JNIEnv* env,
+ jobject clazz,
+ jstring library)
+{
+ const jbyte *libName = (*env)->GetStringUTFChars(env, library, NULL);
+ void *p = dlopen (libName, RTLD_LOCAL);
+ LOGI("dlopen(%s) = %p", libName, p);
+ if (p == NULL) {
+ LOGI(dlerror());
+ return 0;
+ }
+ return (jint) p;
+}
+
+jint
+Java_org_libreoffice_android_Bootstrap_dlsym(JNIEnv* env,
+ jobject clazz,
+ jint handle,
+ jstring symbol)
+{
+ const jbyte *symName = (*env)->GetStringUTFChars(env, symbol, NULL);
+ void *p = dlsym ((void *)handle, symName);
+ LOGI("dlsym(%p,%s) = %p", handle, symName, p);
+ if (p == NULL) {
+ LOGI(dlerror());
+ return 0;
+ }
+ return (jint) p;
+}
+
+jint
+Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env,
+ jobject clazz,
+ jint function,
+ jobject argument)
+{
+ /* To be implemented */
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */