Kaydet (Commit) 4b7e7010 authored tarafından Tor Lillqvist's avatar Tor Lillqvist

Use DISABLE_DYNLOADING on Android

IN this branch these changes are not conditional. Unclear yet whether
this is what we finally will want to use or not. Maybe should make
these changes conditional and do this stuff in master instead?

Change-Id: I379d570a0e00648d295c675fd90eba6594ba3182
üst b62bead2
...@@ -62,21 +62,9 @@ public class Bootstrap extends NativeActivity ...@@ -62,21 +62,9 @@ public class Bootstrap extends NativeActivity
String apkFile, String apkFile,
String[] ld_library_path); String[] ld_library_path);
public static native boolean setup(int lo_main_ptr, public static native boolean setup(Object lo_main_argument,
Object lo_main_argument,
int lo_main_delay); int lo_main_delay);
// This is not just a wrapper for the C library dlopen(), but also
// loads recursively dependent libraries.
public static native int dlopen(String library);
// This is just a wrapper for the C library dlsym().
public static native int dlsym(int handle, String symbol);
// To be called after you are sure libgnustl_shared.so
// has been loaded
static native void patch_libgnustl_shared();
// Extracts files in the .apk that need to be extraced into the app's tree // Extracts files in the .apk that need to be extraced into the app's tree
static native void extract_files(); static native void extract_files();
...@@ -148,11 +136,6 @@ public class Bootstrap extends NativeActivity ...@@ -148,11 +136,6 @@ public class Bootstrap extends NativeActivity
if (!setup(dataDir, activity.getApplication().getPackageResourcePath(), llpa)) if (!setup(dataDir, activity.getApplication().getPackageResourcePath(), llpa))
return; return;
// We build LO code against the shared GNU C++ library
dlopen("libgnustl_shared.so");
// and need to patch it.
patch_libgnustl_shared();
// Extract files from the .apk that can't be used mmapped directly from it // Extract files from the .apk that can't be used mmapped directly from it
extract_files(); extract_files();
...@@ -224,35 +207,8 @@ public class Bootstrap extends NativeActivity ...@@ -224,35 +207,8 @@ public class Bootstrap extends NativeActivity
System.arraycopy(argv, 0, newargv, 1, argv.length); System.arraycopy(argv, 0, newargv, 1, argv.length);
argv = newargv; argv = newargv;
// Load the LO "program" here and look up lo_main // Load the LO "program" here
int loLib = dlopen(mainLibrary); System.loadLibrary(mainLibrary);
if (loLib == 0) {
Log.i(TAG, String.format("Error: could not load %s", mainLibrary));
mainLibrary = "libmergedlo.so";
loLib = dlopen(mainLibrary);
if (loLib == 0) {
Log.i(TAG, String.format("Error: could not load fallback %s", mainLibrary));
return;
}
}
int lo_main = dlsym(loLib, "lo_main");
if (lo_main == 0) {
Log.i(TAG, String.format("No lo_main in %s", mainLibrary));
return;
}
// Get extra libraries to load early, so that it's easier to debug
// them even with a buggy ndk-gdb that doesn't grok debugging
// information from libraries loaded after it has been attached to the
// process.
String extraLibs = getIntent().getStringExtra("lo-extra-libs");
if (extraLibs != null) {
for (String lib : extraLibs.split(":")) {
dlopen(lib);
}
}
// Start a strace on ourself if requested. // Start a strace on ourself if requested.
...@@ -272,7 +228,7 @@ public class Bootstrap extends NativeActivity ...@@ -272,7 +228,7 @@ public class Bootstrap extends NativeActivity
delay = Integer.parseInt(sdelay); delay = Integer.parseInt(sdelay);
// Tell lo-bootstrap.c the stuff it needs to know // Tell lo-bootstrap.c the stuff it needs to know
if (!setup(lo_main, argv, delay)) if (!setup(argv, delay))
return; return;
// Finally, call our super-class, NativeActivity's onCreate(), // Finally, call our super-class, NativeActivity's onCreate(),
...@@ -286,14 +242,12 @@ public class Bootstrap extends NativeActivity ...@@ -286,14 +242,12 @@ public class Bootstrap extends NativeActivity
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
// This is used to load the 'lo-bootstrap' library on application // Now with static loading we always have all native code in one native
// startup. The library has already been unpacked into // library which we always call liblo-native-code.so, regardless of the
// /data/data/<app name>/lib/liblo-bootstrap.so at installation // app. The library has already been unpacked into /data/data/<app
// time by the package manager. // name>/lib at installation time by the package manager.
static { static {
System.loadLibrary("lo-bootstrap"); System.loadLibrary("lo-native-code");
System.loadLibrary("gnustl_shared");
System.loadLibrary("libotouchlo");
} }
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -19,15 +19,154 @@ APP_DATA_PATH=/data/data/$(APP_PACKAGE) ...@@ -19,15 +19,154 @@ APP_DATA_PATH=/data/data/$(APP_PACKAGE)
SODEST=libs/$(ANDROID_APP_ABI) SODEST=libs/$(ANDROID_APP_ABI)
OBJLOCAL=obj/local/$(ANDROID_APP_ABI) OBJLOCAL=obj/local/$(ANDROID_APP_ABI)
define COPYSO
cp $(1) $(SODEST)$(if $(2),/$(2)) && $(STRIP) --strip-debug $(SODEST)$(if $(2),/$(2),/$(notdir $(1))) && \
cp $(1) $(OBJLOCAL)$(if $(2),/$(2))
endef
define COPYJAR define COPYJAR
cp $(1) libs cp $(1) libs
endef endef
LIBS = \
-Wl,--start-group \
$(addprefix -l,$(strip \
ascii_expat_xmlparse \
avmedialo \
basebmp \
basegfxlo \
bootstrap.uno \
canvastoolslo \
collator_data \
comphelpgcc3 \
configmgr.uno \
cppcanvaslo \
crypto \
dbaxmllo \
dbtoolslo \
deploymentmisclo \
dict_ja \
dict_zh \
drawinglayerlo \
editenglo \
expat_xmlparse \
expat_xmltok \
expwrap.uno \
fastsax.uno \
filterconfiglo \
fontconfig \
forlo \
foruilo \
freetype \
frmlo \
fsstorage.uno \
fwelo \
fwilo \
fwklo \
gcc3_uno \
hwplo \
i18nisolang1gcc3 \
i18npool.uno \
i18nregexplo \
i18nsearch.uno \
i18nutilgcc3 \
icudata \
icui18n \
icule \
icutu \
icuuc \
index_data \
introspection.uno \
java_uno \
jpeg \
jvmaccessgcc3 \
jvmfwk \
lcms2 \
libotouchlo \
lnglo \
lo-bootstrap \
localedata_en \
localedata_es \
localedata_euro \
localedata_others \
loglo \
log_uno_uno \
lpsolve55 \
lwpftlo \
msfilterlo \
mswordlo \
ooxlo \
orcus \
package2 \
reflection.uno \
reg \
saxlo \
sax_shared \
sblo \
sclo \
scdlo \
scfiltlo \
sddlo \
sdfiltlo \
sdlo \
sfxlo \
smdlo \
smlo \
sotlo \
spllo \
stocservices.uno \
store \
svgfilterlo \
svllo \
svtlo \
svxcorelo \
svxlo \
swdlo \
swlo \
t602filterlo \
textconv_dict \
textconversiondlgslo \
textfdlo \
textinstream.uno \
textoutstream.uno \
tklo \
tllo \
ucb1 \
ucbhelper4gcc3 \
ucpfile1 \
ucppkg1 \
uno_cppu \
uno_cppuhelpergcc3 \
uno_sal \
uno_salhelpergcc3 \
uno_cppuhelpergcc3 \
unordflo \
unoxmllo \
utllo \
uuilo \
vbahelperlo \
vbaswobj.uno \
vcllo \
wpftdrawlo \
wpftwriterlo \
xml2 \
xmlfalo \
xmlfdlo \
xmlreader \
xmlscriptlo \
xmlsecurity \
xoflo \
xolo \
xsec_fw \
xslt \
xsltdlglo \
xsltfilterlo \
xstor \
)) \
-Wl,--end-group
WHOLELIBS = \
-Wl,--whole-archive \
$(addprefix -l,$(strip \
juh \
)) \
-Wl,--no-whole-archive
# The default target just builds. # The default target just builds.
all: build-ant all: build-ant
...@@ -39,87 +178,16 @@ properties: ...@@ -39,87 +178,16 @@ properties:
echo "APP_ABI := $(ANDROID_APP_ABI)" >>jni/Application.mk echo "APP_ABI := $(ANDROID_APP_ABI)" >>jni/Application.mk
echo "APP_PLATFORM := android-14" >>jni/Application.mk echo "APP_PLATFORM := android-14" >>jni/Application.mk
link-so:
# Build the single .so for this app
mkdir -p $(OBJLOCAL)
$(CXX) -Wl,-Map,liblo-native-code.map -Wl,--no-undefined -DANDROID -DDISABLE_DYNLOADING -shared -o $(OBJLOCAL)/liblo-native-code.so -I$(OUTDIR)/inc native-code.cxx -L$(OUTDIR)/lib $(WHOLELIBS) $(LIBS) -lgnustl_static -landroid -llog -lz
mkdir -p $(SODEST)
cp $(OBJLOCAL)/liblo-native-code.so $(SODEST)
$(STRIP) --strip-debug $(SODEST)/liblo-native-code.so
copy-stuff: copy-stuff:
# First always clean # Then "assets". Let the directory structure under assets mimic
rm -rf libs $(OBJLOCAL)
mkdir -p $(SODEST) $(OBJLOCAL)
#
# Copy shared libraries (including UNO components) we need to
# libs/$(ANDROID_APP_ABI) so that ant will include them in the .apk.
#
# Copy them to obj/local/$(ANDROID_APP_ABI), too, where gdb will look for
# them.
#
for F in $(strip \
basegfxlo \
bootstrap.uno \
comphelpgcc3 \
dbaxmllo \
dbtoolslo \
expwrap.uno \
frmlo \
gcc3_uno \
i18nisolang1gcc3 \
icudatalo \
icui18nlo \
iculelo \
icuuclo \
introspection.uno \
java_uno \
juh \
juhx \
jvmaccessgcc3 \
jvmfwk \
libotouchlo \
lo-bootstrap \
localedata_en \
localedata_others \
lwpftlo \
mergedlo \
msfilterlo \
mswordlo \
ooxlo \
reflection.uno \
reg \
sclo \
scdlo \
scfiltlo \
sddlo \
smdlo \
stocservices.uno \
store \
svgfilterlo \
swdlo \
swlo \
t602filterlo \
textinstream.uno \
tllo \
ucbhelper4gcc3 \
ucppkg1 \
uno_cppu \
uno_cppuhelpergcc3 \
uno_sal \
uno_salhelpergcc3 \
uno_cppuhelpergcc3 \
unordflo \
unoxmllo \
vbahelperlo \
vbaswobj.uno \
wpftdrawlo \
wpftwriterlo \
xml2 \
xmlfdlo \
xmlreader \
xmlsecurity \
xslt \
); do \
$(call COPYSO,$(OUTDIR)/lib/lib$${F}.so); \
done
#
# Then the shared GNU C++ library
$(call COPYSO,$(ANDROID_NDK_HOME)/sources/cxx-stl/gnu-libstdc++/$(ANDROID_NDK_TOOLCHAIN_VERSION_SUBDIR)libs/$(ANDROID_APP_ABI)/libgnustl_shared.so)
#
# Then other "assets". Let the directory structure under assets mimic
# that under solver for now. # that under solver for now.
# #
# Please note that I have no idea what all of this is really necessary and for # Please note that I have no idea what all of this is really necessary and for
...@@ -216,10 +284,11 @@ copy-stuff: ...@@ -216,10 +284,11 @@ copy-stuff:
# #
# Then gdbserver and gdb.setup so that we can debug with ndk-gdb. # Then gdbserver and gdb.setup so that we can debug with ndk-gdb.
# #
mkdir -p $(SODEST)
cp $(ANDROID_NDK_GDBSERVER) $(SODEST) cp $(ANDROID_NDK_GDBSERVER) $(SODEST)
echo set solib-search-path ./obj/local/$(ANDROID_APP_ABI) >$(SODEST)/gdb.setup echo set solib-search-path ./obj/local/$(ANDROID_APP_ABI) >$(SODEST)/gdb.setup
build-ant: copy-stuff properties build-ant: copy-stuff link-so properties
# #
# Copy jar files we need # Copy jar files we need
# #
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "osl/detail/android-bootstrap.h"
extern "C"
{
extern void * hwp_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * sc_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * scd_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * scfilt_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * sw_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * swd_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * unoxml_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * xmlfd_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * xo_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
extern void * xof_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey );
}
extern "C"
__attribute__ ((visibility("default")))
const lib_to_component_mapping *
lo_get_libmap(void)
{
static lib_to_component_mapping map[] = {
{ "libhwplo.a", hwp_component_getFactory },
{ "libscdlo.a", scd_component_getFactory },
{ "libscfiltlo.a", scfilt_component_getFactory },
{ "libsclo.a", sc_component_getFactory },
{ "libswdlo.a", swd_component_getFactory },
{ "libswlo.a", sw_component_getFactory },
{ "libunoxmllo.a", unoxml_component_getFactory },
{ "libxmlfdlo.a", xmlfd_component_getFactory },
{ "libxoflo.a", xof_component_getFactory },
{ "libxolo.a", xo_component_getFactory },
{ NULL, NULL }
};
return map;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -929,13 +929,7 @@ public class DocumentLoader ...@@ -929,13 +929,7 @@ public class DocumentLoader
Bootstrap.setup(this); Bootstrap.setup(this);
// Avoid all the old style OSL_TRACE calls especially in vcl // Avoid all the old style OSL_TRACE calls especially in vcl
Bootstrap.putenv("SAL_LOG=+WARN+INFO-INFO.legacy.osl"); Bootstrap.putenv("SAL_LOG=+WARN+INFO");
// Load a lot of shlibs here explicitly in advance because that
// makes debugging work better, sigh
Bootstrap.dlopen("libmergedlo.so");
Bootstrap.dlopen("libswdlo.so");
Bootstrap.dlopen("libswlo.so");
// Log.i(TAG, "Sleeping NOW"); // Log.i(TAG, "Sleeping NOW");
// Thread.sleep(20000); // Thread.sleep(20000);
......
...@@ -2422,8 +2422,8 @@ else ...@@ -2422,8 +2422,8 @@ else
fi fi
AC_SUBST(DISABLE_SCRIPTING) AC_SUBST(DISABLE_SCRIPTING)
if test $_os = iOS; then if test $_os = iOS -o $_os = Android; then
# Disable dynamic_loading always for iOS # Disable dynamic_loading always for iOS and Android
enable_dynamic_loading=no enable_dynamic_loading=no
elif test -z "$enable_dynamic_loading"; then elif test -z "$enable_dynamic_loading"; then
# Otherwise enable it unless speficically disabled # Otherwise enable it unless speficically disabled
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
--disable-randr --disable-randr
--disable-randr-link --disable-randr-link
--disable-systray --disable-systray
--enable-mergelibs
--without-junit --without-junit
--without-ppds --without-ppds
--without-stlport --without-stlport
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
--disable-randr --disable-randr
--disable-randr-link --disable-randr-link
--disable-systray --disable-systray
--enable-mergelibs
--without-junit --without-junit
--without-ppds --without-ppds
--without-stlport --without-stlport
......
...@@ -67,6 +67,7 @@ $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/file.h,osl/detail/file. ...@@ -67,6 +67,7 @@ $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/file.h,osl/detail/file.
$(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/android_native_app_glue.h,osl/detail/android_native_app_glue.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/android_native_app_glue.h,osl/detail/android_native_app_glue.h))
$(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/android-bootstrap.h,osl/detail/android-bootstrap.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/android-bootstrap.h,osl/detail/android-bootstrap.h))
$(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/ios-bootstrap.h,osl/detail/ios-bootstrap.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/ios-bootstrap.h,osl/detail/ios-bootstrap.h))
$(eval $(call gb_Package_add_file,sal_inc,inc/osl/detail/component-mapping.h,osl/detail/component-mapping.h))
$(eval $(call gb_Package_add_file,sal_inc,inc/rtl/allocator.hxx,rtl/allocator.hxx)) $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/allocator.hxx,rtl/allocator.hxx))
$(eval $(call gb_Package_add_file,sal_inc,inc/rtl/alloc.h,rtl/alloc.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/alloc.h,rtl/alloc.h))
$(eval $(call gb_Package_add_file,sal_inc,inc/rtl/bootstrap.h,rtl/bootstrap.h)) $(eval $(call gb_Package_add_file,sal_inc,inc/rtl/bootstrap.h,rtl/bootstrap.h))
......
...@@ -43,8 +43,6 @@ ...@@ -43,8 +43,6 @@
#include <jni.h> #include <jni.h>
#include <linux/elf.h>
#include <android/log.h> #include <android/log.h>
#include "uthash.h" #include "uthash.h"
...@@ -299,40 +297,8 @@ engine_handle_cmd(struct android_app* state, ...@@ -299,40 +297,8 @@ engine_handle_cmd(struct android_app* state,
} }
} }
static char * /* The lo-native-code shared library is always loaded from Java, so this is
read_section(int fd, * always called by JNI first.
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) < (int) shdr->sh_size) {
close(fd);
free(result);
return NULL;
}
return result;
}
static void
free_ptrarray(void **pa)
{
void **rover = pa;
while (*rover != NULL)
free(*rover++);
free(pa);
}
/* The lo-bootstrap shared library is always loaded from Java, so
* this is always called by JNI first.
*/ */
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
jint jint
...@@ -345,133 +311,6 @@ JNI_OnLoad(JavaVM* vm, void* reserved) ...@@ -345,133 +311,6 @@ JNI_OnLoad(JavaVM* vm, void* reserved)
return JNI_VERSION_1_2; return JNI_VERSION_1_2;
} }
__attribute__ ((visibility("default")))
jobjectArray
Java_org_libreoffice_android_Bootstrap_dlneeds(JNIEnv* env,
jobject clazz,
jstring library)
{
char **needed;
int n_needed;
const char *libName;
jclass String;
jobjectArray result;
(void) clazz;
libName = (*env)->GetStringUTFChars(env, library, NULL);
needed = lo_dlneeds(libName);
(*env)->ReleaseStringUTFChars(env, library, libName);
if (needed == NULL)
return NULL;
n_needed = 0;
while (needed[n_needed] != NULL)
n_needed++;
/* Allocate return value */
String = (*env)->FindClass(env, "java/lang/String");
if (String == NULL) {
LOGE("Could not find the String class");
free_ptrarray((void **) needed);
return NULL;
}
result = (*env)->NewObjectArray(env, n_needed, String, NULL);
if (result == NULL) {
LOGE("Could not create the String array");
free_ptrarray((void **) needed);
return NULL;
}
for (n_needed = 0; needed[n_needed] != NULL; n_needed++)
(*env)->SetObjectArrayElement(env, result, n_needed, (*env)->NewStringUTF(env, needed[n_needed]));
free_ptrarray((void **) needed);
return result;
}
__attribute__ ((visibility("default")))
jint
Java_org_libreoffice_android_Bootstrap_dlopen(JNIEnv* env,
jobject clazz,
jstring library)
{
const char *libName;
void *p;
(void) clazz;
libName = (*env)->GetStringUTFChars(env, library, NULL);
p = lo_dlopen (libName);
(*env)->ReleaseStringUTFChars(env, library, libName);
return (jint) p;
}
__attribute__ ((visibility("default")))
jint
Java_org_libreoffice_android_Bootstrap_dlsym(JNIEnv* env,
jobject clazz,
jint handle,
jstring symbol)
{
const char *symName;
void *p;
(void) clazz;
symName = (*env)->GetStringUTFChars(env, symbol, NULL);
p = lo_dlsym ((void *) handle, symName);
(*env)->ReleaseStringUTFChars(env, symbol, symName);
return (jint) p;
}
__attribute__ ((visibility("default")))
jint
Java_org_libreoffice_android_Bootstrap_dlcall(JNIEnv* env,
jobject clazz,
jint function,
jobject argument)
{
jclass StringArray;
(void) clazz;
StringArray = (*env)->FindClass(env, "[Ljava/lang/String;");
if (StringArray == NULL) {
LOGE("Could not find String[] class");
return 0;
}
if ((*env)->IsInstanceOf(env, argument, StringArray)) {
int argc = (*env)->GetArrayLength(env, argument);
const char **argv = malloc(sizeof(char *) * (argc+1));
int i, result;
for (i = 0; i < argc; i++) {
argv[i] = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, argument, i), NULL);
/* LOGI("argv[%d] = %s", i, argv[i]); */
}
argv[argc] = NULL;
result = lo_dlcall_argc_argv((void *) function, argc, argv);
for (i = 0; i < argc; i++)
(*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, argument, i), argv[i]);
free(argv);
return result;
}
return 0;
}
// public static native boolean setup(String dataDir, // public static native boolean setup(String dataDir,
// String apkFile, // String apkFile,
// String[] ld_library_path); // String[] ld_library_path);
...@@ -591,22 +430,18 @@ get_jni_string_array(JNIEnv *env, ...@@ -591,22 +430,18 @@ get_jni_string_array(JNIEnv *env,
} }
// public static native boolean setup(int lo_main_ptr, // public static native boolean setup(Object lo_main_argument,
// Object lo_main_argument,
// int lo_main_delay); // int lo_main_delay);
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
jboolean jboolean
Java_org_libreoffice_android_Bootstrap_setup__ILjava_lang_Object_2I(JNIEnv* env, Java_org_libreoffice_android_Bootstrap_setup__Ljava_lang_Object_2I(JNIEnv* env,
jobject clazz, jobject clazz,
void *lo_main_ptr,
jobject lo_main_argument, jobject lo_main_argument,
jint lo_main_delay) jint lo_main_delay)
{ {
(void) clazz; (void) clazz;
lo_main = lo_main_ptr;
if (!get_jni_string_array(env, "setup: lo_main_argument", lo_main_argument, &lo_main_argc, &lo_main_argv)) if (!get_jni_string_array(env, "setup: lo_main_argument", lo_main_argument, &lo_main_argc, &lo_main_argv))
return JNI_FALSE; return JNI_FALSE;
...@@ -668,344 +503,16 @@ Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env, ...@@ -668,344 +503,16 @@ Java_org_libreoffice_android_Bootstrap_putenv(JNIEnv* env,
putenv(s); putenv(s);
(*env)->ReleaseStringUTFChars(env, string, s); {
} static int beenhere=0;
if (!beenhere) {
__attribute__ ((visibility("default"))) LOGI("lo-bootstrap: Sleeping for 20 seconds, start ndk-gdb NOW if that is your intention");
char ** sleep(20);
lo_dlneeds(const char *library) beenhere = 1;
{
int i, fd;
int n_needed;
char **result;
char *shstrtab;
char *dynstr = NULL;
Elf32_Ehdr hdr;
Elf32_Shdr shdr;
Elf32_Dyn dyn;
/* Open library and read ELF header */
fd = open(library, O_RDONLY);
if (fd == -1) {
LOGE("lo_dlneeds: Could not open library %s: %s", library, strerror(errno));
return NULL;
}
if (read(fd, &hdr, sizeof(hdr)) < (int) sizeof(hdr)) {
LOGE("lo_dlneeds: Could not read ELF header of %s", library);
close(fd);
return NULL;
}
/* Read in .shstrtab */
if (lseek(fd, hdr.e_shoff + hdr.e_shstrndx * sizeof(shdr), SEEK_SET) < 0) {
LOGE("lo_dlneeds: Could not seek to .shstrtab section header of %s", library);
close(fd);
return NULL;
}
if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) {
LOGE("lo_dlneeds: Could not read section header of %s", library);
close(fd);
return NULL;
}
shstrtab = read_section(fd, &shdr);
if (shstrtab == NULL)
return NULL;
/* Read section headers, looking for .dynstr section */
if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) {
LOGE("lo_dlneeds: Could not seek to section headers of %s", library);
close(fd);
return NULL;
}
for (i = 0; i < hdr.e_shnum; i++) {
if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) {
LOGE("lo_dlneeds: Could not read section header of %s", library);
close(fd);
return NULL;
}
if (shdr.sh_type == SHT_STRTAB &&
strcmp(shstrtab + shdr.sh_name, ".dynstr") == 0) {
dynstr = read_section(fd, &shdr);
if (dynstr == NULL) {
free(shstrtab);
return NULL;
}
break;
}
}
if (i == hdr.e_shnum) {
LOGE("lo_dlneeds: No .dynstr section in %s", library);
close(fd);
return NULL;
}
/* Read section headers, looking for .dynamic section */
if (lseek(fd, hdr.e_shoff, SEEK_SET) < 0) {
LOGE("lo_dlneeds: Could not seek to section headers of %s", library);
close(fd);
return NULL;
}
for (i = 0; i < hdr.e_shnum; i++) {
if (read(fd, &shdr, sizeof(shdr)) < (int) sizeof(shdr)) {
LOGE("lo_dlneeds: Could not read section header of %s", library);
close(fd);
return NULL;
}
if (shdr.sh_type == SHT_DYNAMIC) {
size_t dynoff;
/* Count number of DT_NEEDED entries */
n_needed = 0;
if (lseek(fd, shdr.sh_offset, SEEK_SET) < 0) {
LOGE("lo_dlneeds: Could not seek to .dynamic section of %s", library);
close(fd);
return NULL;
}
for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) {
if (read(fd, &dyn, sizeof(dyn)) < (int) sizeof(dyn)) {
LOGE("lo_dlneeds: Could not read .dynamic entry of %s", library);
close(fd);
return NULL;
}
if (dyn.d_tag == DT_NEEDED)
n_needed++;
}
/* LOGI("Found %d DT_NEEDED libs", n_needed); */
result = malloc((n_needed+1) * sizeof(char *));
n_needed = 0;
if (lseek(fd, shdr.sh_offset, SEEK_SET) < 0) {
LOGE("lo_dlneeds: Could not seek to .dynamic section of %s", library);
close(fd);
free(result);
return NULL;
}
for (dynoff = 0; dynoff < shdr.sh_size; dynoff += sizeof(dyn)) {
if (read(fd, &dyn, sizeof(dyn)) < (int) sizeof(dyn)) {
LOGE("lo_dlneeds: Could not read .dynamic entry in %s", library);
close(fd);
free(result);
return NULL;
}
if (dyn.d_tag == DT_NEEDED) {
/* LOGI("needs: %s\n", dynstr + dyn.d_un.d_val); */
result[n_needed] = strdup(dynstr + dyn.d_un.d_val);
n_needed++;
}
}
close(fd);
if (dynstr)
free(dynstr);
free(shstrtab);
result[n_needed] = NULL;
return result;
}
}
LOGE("lo_dlneeds: Could not find .dynamic section in %s", library);
close(fd);
return NULL;
}
__attribute__ ((visibility("default")))
void *
lo_dlopen(const char *library)
{
/*
* We should *not* try to just dlopen() the bare library name
* first, as the stupid dynamic linker remembers for each library
* basename if loading it has failed. Thus if you try loading it
* once, and it fails because of missing needed libraries, and
* your load those, and then try again, it fails with an
* infuriating message "failed to load previously" in the log.
*
* We *must* first dlopen() all needed libraries, recursively. It
* shouldn't matter if we dlopen() a library that already is
* loaded, dlopen() just returns the same value then.
*/
typedef struct loadedLib {
const char *name;
void *handle;
struct loadedLib *next;
} *loadedLib;
static loadedLib loaded_libraries = NULL;
loadedLib rover;
loadedLib new_loaded_lib;
struct stat st;
void *p;
char *full_name;
char **needed;
int i;
int found;
struct timeval tv0, tv1, tvdiff;
rover = loaded_libraries;
while (rover != NULL &&
strcmp(rover->name, library) != 0)
rover = rover->next;
if (rover != NULL)
return rover->handle;
/* LOGI("lo_dlopen(%s)", library); */
found = 0;
if (library[0] == '/') {
full_name = strdup(library);
if (stat(full_name, &st) == 0 &&
S_ISREG(st.st_mode))
found = 1;
else
free(full_name);
} else {
for (i = 0; !found && library_locations[i] != NULL; i++) {
full_name = malloc(strlen(library_locations[i]) + 1 + strlen(library) + 1);
strcpy(full_name, library_locations[i]);
strcat(full_name, "/");
strcat(full_name, library);
if (stat(full_name, &st) == 0 &&
S_ISREG(st.st_mode))
found = 1;
else
free(full_name);
}
}
if (!found) {
LOGE("lo_dlopen: Library %s not found", library);
return NULL;
}
needed = lo_dlneeds(full_name);
if (needed == NULL) {
free(full_name);
return NULL;
}
for (i = 0; needed[i] != NULL; i++) {
if (lo_dlopen(needed[i]) == NULL) {
free_ptrarray((void **) needed);
free(full_name);
return NULL;
}
}
free_ptrarray((void **) needed);
gettimeofday(&tv0, NULL);
p = dlopen(full_name, RTLD_LOCAL);
gettimeofday(&tv1, NULL);
timersub(&tv1, &tv0, &tvdiff);
LOGI("dlopen(%s) = %p, %ld.%03lds",
full_name, p,
(long) tvdiff.tv_sec, (long) tvdiff.tv_usec / 1000);
free(full_name);
if (p == NULL)
LOGE("lo_dlopen: Error from dlopen(%s): %s", library, dlerror());
new_loaded_lib = malloc(sizeof(*new_loaded_lib));
new_loaded_lib->name = strdup(library);
new_loaded_lib->handle = p;
new_loaded_lib->next = loaded_libraries;
loaded_libraries = new_loaded_lib;
return p;
}
__attribute__ ((visibility("default")))
void *
lo_dlsym(void *handle,
const char *symbol)
{
void *p = dlsym(handle, symbol);
/* LOGI("dlsym(%p, %s) = %p", handle, symbol, p); */
if (p == NULL)
LOGE("lo_dlsym: %s", dlerror());
return p;
}
__attribute__ ((visibility("default")))
int
lo_dladdr(void *addr,
Dl_info *info)
{
FILE *maps;
char line[200];
int result;
int found;
result = dladdr(addr, info);
if (result == 0) {
/* LOGI("dladdr(%p) = 0", addr); */
return 0;
}
maps = fopen("/proc/self/maps", "r");
if (maps == NULL) {
LOGE("lo_dladdr: Could not open /proc/self/maps: %s", strerror(errno));
return 0;
}
found = 0;
while (fgets(line, sizeof(line), maps) != NULL &&
line[strlen(line)-1] == '\n') {
void *lo, *hi;
char file[sizeof(line)];
file[0] = '\0';
if (sscanf(line, "%x-%x %*s %*x %*x:%*x %*d %[^\n]", (unsigned *) &lo, (unsigned *) &hi, file) == 3) {
/* LOGI("got %p-%p: %s", lo, hi, file); */
if (addr >= lo && addr < hi) {
if (info->dli_fbase != lo) {
LOGE("lo_dladdr: Base for %s in /proc/self/maps %p doesn't match what dladdr() said", file, lo);
fclose(maps);
return 0;
}
/* LOGI("dladdr(%p) = { %s:%p, %s:%p }: %s",
addr,
info->dli_fname, info->dli_fbase,
info->dli_sname ? info->dli_sname : "(none)", info->dli_saddr,
file); */
info->dli_fname = strdup(file);
found = 1;
break;
}
} }
} }
if (!found)
LOGE("lo_dladdr: Did not find %p in /proc/self/maps", addr);
fclose(maps);
return result;
}
__attribute__ ((visibility("default")))
int
lo_dlclose(void *handle)
{
/* As we don't know when the reference count for a dlopened shared
* object drops to zero, we wouldn't know when to remove it from
* our list, so we can't call dlclose().
*/
LOGI("lo_dlclose(%p)", handle);
return 0; (*env)->ReleaseStringUTFChars(env, string, s);
} }
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
...@@ -1235,195 +742,6 @@ lo_dlcall_argc_argv(void *function, ...@@ -1235,195 +742,6 @@ lo_dlcall_argc_argv(void *function,
return result; return result;
} }
#ifdef ARM
/* There is a bug in std::type_info::operator== and
* std::type_info::before() in libgnustl_shared.so in NDK r7 at
* least. They compare the type name pointers instead of comparing the
* type name strings. See
* http://code.google.com/p/android/issues/detail?id=22165 . So patch
* that, poke in jumps to our own code snippets below instead.
*/
/* Replacement std::type_info::operator== */
__asm(" .arm\n"
" .global replacement_operator_equals_arm\n"
"replacement_operator_equals_arm:\n"
" push {lr}\n"
/* Load name pointers into r0 and r1 */
" ldr r0, [r0, #4]\n"
" ldr r1, [r1, #4]\n"
/* First compare pointers */
" cmp r0, r1\n"
/* If equal, return true */
" beq .L.equals.1\n"
/* Otherwise call strcmp */
" bl strcmp\n"
/* And return true or false */
" cmp r0, #0\n"
" moveq r0, #1\n"
" movne r0, #0\n"
" b .L.equals.9\n"
".L.equals.1:\n"
" mov r0, #1\n"
".L.equals.9:\n"
" pop {pc}\n"
);
extern unsigned int replacement_operator_equals_arm;
/* The ARM (not Thumb) code of the operator== in NDK r7 */
static unsigned int expected_operator_equals_r7_code[] = {
0xe5903004, /* ldr r3, [r0, #4] */
0xe5910004, /* ldr r0, [r1, #4] */
0xe1530000, /* cmp r3, r0 */
0x13a00000, /* movne, #0 */
0x03a00001, /* moveq r0, #1 */
0xe12fff1e /* bx lr */
};
/* Ditto for std::type_info::before() */
__asm(" .arm\n"
" .global replacement_method_before_arm\n"
"replacement_method_before_arm:\n"
" push {lr}\n"
/* Load name pointers into r0 and r1 */
" ldr r0, [r0, #4]\n"
" ldr r1, [r1, #4]\n"
/* First compare pointers */
" cmp r0, r1\n"
/* If equal, return false */
" beq .L.before.1\n"
/* Otherwise call strcmp */
" bl strcmp\n"
/* And return true or false */
" cmp r0, #0\n"
" movlt r0, #1\n"
" movge r0, #0\n"
" b .L.before.9\n"
".L.before.1:\n"
" mov r0, #0\n"
".L.before.9:\n"
" pop {pc}\n"
);
extern unsigned int replacement_method_before_arm;
static unsigned int expected_method_before_r7_code[] = {
0xe5903004, /* ldr r3, [r0, #4] */
0xe5910004, /* ldr r0, [r1, #4] */
0xe1530000, /* cmp r3, r0 */
0x23a00000, /* movcs r0, #0 */
0x33a00001, /* movcc r0, #1 */
0xe12fff1e /* bx lr */
};
static void
patch(const char *symbol,
const char *plaintext,
unsigned *expected_code,
size_t expected_code_size,
unsigned *replacement_code)
{
void *libgnustl_shared;
void *code;
void *base;
size_t size;
/* libgnustl_shared.so should be already loaded as we build
* all LO code against it, so as we have loaded the .so
* containing lo_main() already, libgnustl_shared.so will have
* been brought in, too.
*/
libgnustl_shared = dlopen("libgnustl_shared.so", RTLD_LOCAL);
if (libgnustl_shared == NULL) {
LOGF("android_main: libgnustl_shared.so not mapped??");
exit(0);
}
code = dlsym(libgnustl_shared, symbol);
if (code == NULL) {
LOGF("android_main: %s not found!?", plaintext);
exit(0);
}
/* LOGI("%s is at %p", plaintext, operator_equals); */
if ((((unsigned) code) & 0x03) != 0) {
LOGE("android_main: Address of %s is not at word boundary, huh?", plaintext);
return;
}
if ((((unsigned) &replacement_code) & 0x03) != 0) {
LOGE("android_main: Address of replacement %s is not at word boundary, huh?", plaintext);
return;
}
if (memcmp(code, expected_code, expected_code_size) != 0) {
LOGI("android_main: Code for %s does not match that in NDK r7; not patching it", plaintext);
return;
}
base = ROUND_DOWN(code, getpagesize());
size = code + sizeof(expected_code_size) - ROUND_DOWN(code, getpagesize());
if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
LOGE("android_main: mprotect() failed: %s", strerror(errno));
return;
}
/* Poke in a jump to replacement_code instead */
((unsigned *) code)[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
((unsigned *) code)[1] = (unsigned) replacement_code;
}
static void
patch_libgnustl_shared(void)
{
patch("_ZNKSt9type_infoeqERKS_",
"std::type_info::operator==",
expected_operator_equals_r7_code,
sizeof(expected_operator_equals_r7_code),
&replacement_operator_equals_arm);
patch("_ZNKSt9type_info6beforeERKS_",
"std::type_info::before()",
expected_method_before_r7_code,
sizeof(expected_method_before_r7_code),
&replacement_method_before_arm);
}
#endif // ARM
// static native void patch_libgnustl_shared();
__attribute__ ((visibility("default")))
void
Java_org_libreoffice_android_Bootstrap_patch_1libgnustl_1shared(JNIEnv* env,
jobject clazz)
{
(void) env;
(void) clazz;
#ifdef ARM
patch_libgnustl_shared();
#endif
}
#define UNPACK_TREE "/assets/unpack" #define UNPACK_TREE "/assets/unpack"
static int static int
...@@ -1551,34 +869,30 @@ Java_org_libreoffice_android_Bootstrap_extract_1files(JNIEnv* env, ...@@ -1551,34 +869,30 @@ Java_org_libreoffice_android_Bootstrap_extract_1files(JNIEnv* env,
} }
/* Android's JNI works only to libraries loaded through Java's /* Android's JNI works only to libraries loaded through Java's
* System.loadLibrary(), it seems. Not to functions loaded by a dlopen() call * System.loadLibrary(), it seems. But now with just one big app-specific .so
* in native code. For instance, to call a function in libvcllo.so, we need to * on Android, that would not be a problem, but for historical reasons, we
* have its JNI wrapper here, and then call the VCL function from it. Oh well, * have JNI wrappers here, and then call the VCL etc function from them. Oh
* one could say it's clean to have all the Android-specific JNI functions * well, one could say it's clean to have all the Android-specific JNI
* here in this file. * functions here in this file.
*/ */
// public static native void initVCL(); // public static native void initVCL();
extern void InitVCLWrapper(void);
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
void void
Java_org_libreoffice_android_Bootstrap_initVCL(JNIEnv* env, Java_org_libreoffice_android_Bootstrap_initVCL(JNIEnv* env,
jobject clazz) jobject clazz)
{ {
void (*InitVCLWrapper)(void);
(void) env; (void) env;
(void) clazz; (void) clazz;
/* This obviously should be called only after libvcllo.so has been loaded */ InitVCLWrapper();
InitVCLWrapper = dlsym(RTLD_DEFAULT, "InitVCLWrapper");
if (InitVCLWrapper == NULL) {
LOGE("InitVCL: InitVCLWrapper not found");
return;
}
(*InitVCLWrapper)();
} }
extern void osl_setCommandArgs(int, char **);
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
void void
Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env, Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env,
...@@ -1588,14 +902,13 @@ Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env, ...@@ -1588,14 +902,13 @@ Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env,
char **c_argv; char **c_argv;
int c_argc; int c_argc;
Dl_info lo_bootstrap_info; Dl_info lo_bootstrap_info;
void (*osl_setCommandArgs)(int, char **);
(void) clazz; (void) clazz;
if (!get_jni_string_array(env, "setCommandArgs :argv", argv, &c_argc, (const char ***) &c_argv)) if (!get_jni_string_array(env, "setCommandArgs :argv", argv, &c_argc, (const char ***) &c_argv))
return; return;
if (lo_dladdr(Java_org_libreoffice_android_Bootstrap_setCommandArgs, &lo_bootstrap_info) != 0) { if (dladdr(Java_org_libreoffice_android_Bootstrap_setCommandArgs, &lo_bootstrap_info) != 0) {
char *new_argv0 = malloc(strlen(lo_bootstrap_info.dli_fname) + strlen(c_argv[0])); char *new_argv0 = malloc(strlen(lo_bootstrap_info.dli_fname) + strlen(c_argv[0]));
char *slash; char *slash;
strcpy(new_argv0, lo_bootstrap_info.dli_fname); strcpy(new_argv0, lo_bootstrap_info.dli_fname);
...@@ -1611,30 +924,20 @@ Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env, ...@@ -1611,30 +924,20 @@ Java_org_libreoffice_android_Bootstrap_setCommandArgs(JNIEnv* env,
c_argv[0] = new_argv0; c_argv[0] = new_argv0;
} }
osl_setCommandArgs = dlsym(RTLD_DEFAULT, "osl_setCommandArgs"); osl_setCommandArgs(c_argc, c_argv);
if (osl_setCommandArgs == NULL) {
LOGE("setCommandArgs: osl_setCommandArgs not found");
return;
}
(*osl_setCommandArgs)(c_argc, c_argv);
} }
extern int createWindowFoo(void);
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
jint jint
Java_org_libreoffice_android_Bootstrap_createWindowFoo(JNIEnv* env, Java_org_libreoffice_android_Bootstrap_createWindowFoo(JNIEnv* env,
jobject clazz) jobject clazz)
{ {
int (*createWindowFoo)(void);
(void) env; (void) env;
(void) clazz; (void) clazz;
lo_dlopen("libvcllo.so"); return createWindowFoo();
createWindowFoo = dlsym(RTLD_DEFAULT, "createWindowFoo");
if (createWindowFoo == NULL) {
LOGE("createWindowFoo: createWindowFoo not found");
return 0;
}
return (*createWindowFoo)();
} }
...@@ -1956,6 +1259,10 @@ lo_get_app(void) ...@@ -1956,6 +1259,10 @@ lo_get_app(void)
return app; return app;
} }
/* Note that android_main() is used only in NativeActivity-based apps. Only
* the android/qa/sc unit test app is such, and it is unclear whether there is
* any reason to continue maintaining that buildable.
*/
__attribute__ ((visibility("default"))) __attribute__ ((visibility("default")))
void void
android_main(struct android_app* state) android_main(struct android_app* state)
...@@ -1986,7 +1293,12 @@ android_main(struct android_app* state) ...@@ -1986,7 +1293,12 @@ android_main(struct android_app* state)
state->userData = &engine; state->userData = &engine;
state->onAppCmd = engine_handle_cmd; state->onAppCmd = engine_handle_cmd;
if (lo_dladdr(lo_main, &lo_main_info) != 0) { /* Look up lo_main() dynamically even if it is in the same .so as this code,
* but that is only in the case for code built to be used in a NativeActivity-based app.
*/
lo_main = dlsym(RTLD_DEFAULT, "lo_main");
if (dladdr(lo_main, &lo_main_info) != 0) {
lo_main_argv[0] = lo_main_info.dli_fname; lo_main_argv[0] = lo_main_info.dli_fname;
} }
......
...@@ -29,29 +29,19 @@ ...@@ -29,29 +29,19 @@
#ifndef ANDROID_BOOSTRAP_H #ifndef ANDROID_BOOSTRAP_H
#define ANDROID_BOOSTRAP_H #define ANDROID_BOOSTRAP_H
#if defined(ANDROID) #if defined(ANDROID)
#include <jni.h> #include <jni.h>
#include <dlfcn.h>
#include <dirent.h> #include <dirent.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct lo_apk_dir lo_apk_dir; #include <osl/detail/component-mapping.h>
char **lo_dlneeds(const char *library);
void *lo_dlopen(const char *library);
void *lo_dlsym(void *handle, typedef struct lo_apk_dir lo_apk_dir;
const char *symbol);
int lo_dladdr(void *addr,
Dl_info *info);
int lo_dlclose(void *handle);
void *lo_apkentry(const char *filename, void *lo_apkentry(const char *filename,
size_t *size); size_t *size);
...@@ -77,6 +67,7 @@ struct android_app *lo_get_app(void); ...@@ -77,6 +67,7 @@ struct android_app *lo_get_app(void);
#endif #endif
#endif // ANDROID #endif // ANDROID
#endif // ANDROID_BOOTSTRAP_H #endif // ANDROID_BOOTSTRAP_H
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- 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.
*/
#ifndef COMPONENT_MAPPING_H
#define COMPONENT_MAPPING_H
#ifdef DISABLE_DYNLOADING
#ifdef __cplusplus
extern "C" {
#endif
/* On iOS and perhaps Android static linking of the LO code into one
* executable (on Android, into one shared library) is used. In order to get
* the needed UNO coponent linked in, the "main" code for an app needs to
* implement the lo_get_libmap() function to map UNO component library names
* as produced in a build for iOS (like configmgr.uno.a or libsclo.a) to the
* corresponding component_getFactory functions.
*/
typedef struct {
const char *lib;
void * (*component_getFactory_function)(const char *, void *, void *);
} lib_to_component_mapping;
const lib_to_component_mapping *lo_get_libmap(void);
#ifdef __cplusplus
}
#endif
#endif /* DISABLE_DYNLOADING */
#endif /* COMPONENT_MAPPING_H */
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -36,19 +36,7 @@ ...@@ -36,19 +36,7 @@
extern "C" { extern "C" {
#endif #endif
/* On iOS static linking is used. In order to get the needed UNO #include <osl/detail/component-mapping.h>
* coponent linked in, the "main" code for an app needs to implement
* the lo_get_libmap() function to map UNO component library names as
* produced in a build for iOS (like configmgr.uno.a or libsclo.a) to
* the corresponding component_getFactory functions.
*/
typedef struct {
const char *lib;
void * (*component_getFactory_function)(const char *, void *, void *);
} lib_to_component_mapping;
const lib_to_component_mapping *lo_get_libmap(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -76,3 +76,5 @@ LINKFLAGSRUNPATH_URELIB= ...@@ -76,3 +76,5 @@ LINKFLAGSRUNPATH_URELIB=
LINKFLAGSRUNPATH_UREBIN= LINKFLAGSRUNPATH_UREBIN=
LINKFLAGSRUNPATH_OOO= LINKFLAGSRUNPATH_OOO=
LINKFLAGSRUNPATH_SDKBIN= LINKFLAGSRUNPATH_SDKBIN=
DLLPOST=.a
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment