Crash accessing vm.GetEnv in JNI

1118 views
Skip to first unread message

Felipe Monteiro de Carvalho

unread,
Nov 28, 2011, 10:43:31 AM11/28/11
to android-ndk
Hello,

I am trying to explore JNI with Pascal libraries, but my application
crashes inside JNI_OnLoad if I try to call anything from vm, not just
GetEnv. I tried already using 1 level of pointer dereferenciation or 2
(2 being the correct, I think. Pointer dereferenciation is ^ in
Pascal):

function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;
var
curVM:PJavaVM=nil;
curEnv:PJNIEnv=nil;
begin
curVM:=vm;
__android_log_write(ANDROID_LOG_INFO,'nativetest','JNI_OnLoad
called');
__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM=
%x', [PtrInt(CurVM)])));

__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM^=
%x', [PtrInt(CurVM^)])));

__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM^^.reserved0=
%x', [PtrInt(CurVM^^.reserved0)])));

__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM^^.GetEnv=
%x', [PtrInt(Pointer(@CurVM^^.GetEnv))])));
if curVM^^.GetEnv(curVM,@curEnv,JNI_VERSION_1_4)<>JNI_OK then begin //
<<<--- THIS CRASHES

__android_log_write(ANDROID_LOG_INFO{FATAL},'nativetest','curVM^.GetEnv
failed'); <- never shows
// result:=JNI_ERR;
// exit;
end;

What amazes me is that everything looks perfect. I verified the jni
bindings against my jni.h from the ndk and I couldn't find any error.
I can even access CurVM^^.reserved0 and also the value of GetEnv as a
pointer (see all values in the log bellow), but still it crashes
there.

I searched google and I couldn't find people having issues with that,
only when people create their own threads, but my application is
absolutely not creating any threads.

The full source is here:
http://lazarus-ccr.svn.sourceforge.net/viewvc/lazarus-ccr/bindings/android-ndk/examples/jnitest/jni/
http://lazarus-ccr.svn.sourceforge.net/viewvc/lazarus-ccr/bindings/android-ndk/

Another thing that puzzles me is that so far I managed to ignore this
problem, I can call any methods even without registering them, but
this problem blocks me from calling Java methods from the Pascal
library =(

D/dalvikvm(14150): GC_EXPLICIT freed 1701 objects / 120544 bytes in
412ms
I/ActivityManager( 102): Starting activity: Intent {
act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]
flg=0x10200000 cmp=com.pascal.lcltest/.LCLActivity }
I/ActivityManager( 102): Start proc com.pascal.lcltest for activity
com.pascal.lcltest/.LCLActivity: pid=15168 uid=10072 gids={}
I/JNI (15168): Trying to load liblclapp.so
D/dalvikvm(15168): Trying to load lib
/data/data/com.pascal.lcltest/lib/liblclapp.so 0x44929a80
W/Rosie (22307): mAddHtcWidgetByOtherActivity = false,
mIsOpenSlideWhenLeaveLaunch = true
D/dalvikvm(15168): Added shared lib
/data/data/com.pascal.lcltest/lib/liblclapp.so 0x44929a80
I/nativetest(15168): JNI_OnLoad called
I/nativetest(15168): CurVM=AA00
I/nativetest(15168): CurVM^=80889094
I/nativetest(15168): CurVM^^.reserved0=0
I/nativetest(15168): CurVM^^.GetEnv=808890AC
I/DEBUG ( 69): *** *** *** *** *** *** *** *** *** *** *** *** ***
*** *** ***
I/DEBUG ( 69): Build fingerprint:
'htc_wwe/htc_buzz/buzz/buzz:2.2.1/FRG83D/295397:user/release-keys'
I/DEBUG ( 69): pid: 15168, tid: 15168 >>> com.pascal.lcltest <<<
I/DEBUG ( 69): thread: .pascal.lcltest
I/DEBUG ( 69): signal 4 (SIGILL), fault addr 8083e098
I/DEBUG ( 69): r0 0000aa00 r1 be966738 r2 00010004 r3 80889094
I/DEBUG ( 69): r4 8083e099 r5 0000cd58 r6 810aefb0 r7 000a6238
I/DEBUG ( 69): r8 80813e00 r9 0000cd58 10 41056c04 fp be966774
I/DEBUG ( 69): ip afa030c8 sp be9666d8 lr 810e23fc pc 8083e098
cpsr 00000010
I/DEBUG ( 69): #00 pc 0003e098 /system/lib/libdvm.so
I/DEBUG ( 69): #01 lr 810e23fc
/data/data/com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 69):
I/DEBUG ( 69): code around pc:
I/DEBUG ( 69): 8083e078 fffe8475 6904b510 1c202101 fbd8f009
I/DEBUG ( 69): 8083e088 21071c20 fbd4f009 bd104800 00010006
I/DEBUG ( 69): 8083e098 1c16b570 f0091c0d 4b0dfb47 20031c04
I/DEBUG ( 69): 8083e0a8 2e0518f6 2c00d812 602cd101 2101e009
I/DEBUG ( 69): 8083e0b8 f0091c20 6ba0fbbd 60282107 f0091c20
I/DEBUG ( 69):
I/DEBUG ( 69): code around lr:
I/DEBUG ( 69): 810e23dc e3a02801 e3822004 e51b0038 e51b3038
I/DEBUG ( 69): 810e23ec e5933000 e5934018 e1a0e00f e1a0f004
I/DEBUG ( 69): 810e23fc e3500000 159f2198 159f117c 13a00004
I/DEBUG ( 69): 810e240c 1bff32d2 e59f218c e59f116c e3a00004
I/DEBUG ( 69): 810e241c ebff32ce e59f1180 e51b003c e51b203c
I/DEBUG ( 69):
I/DEBUG ( 69): stack:
I/DEBUG ( 69): be966698 afa0109d /system/lib/liblog.so
I/DEBUG ( 69): be96669c afa012f1 /system/lib/liblog.so
I/DEBUG ( 69): be9666a0 00000000
I/DEBUG ( 69): be9666a4 00000004
I/DEBUG ( 69): be9666a8 be9666a4 [stack]
I/DEBUG ( 69): be9666ac 00000001
I/DEBUG ( 69): be9666b0 81367514
/data/data/com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 69): be9666b4 0000000b
I/DEBUG ( 69): be9666b8 002377cc [heap]
I/DEBUG ( 69): be9666bc 00000018
I/DEBUG ( 69): be9666c0 b000c4a8 /system/bin/linker
I/DEBUG ( 69): be9666c4 8088a018 /system/lib/libdvm.so
I/DEBUG ( 69): be9666c8 0000cd58 [heap]
I/DEBUG ( 69): be9666cc 810aefb0
/data/data/com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 69): be9666d0 000a6238 [heap]
I/DEBUG ( 69): be9666d4 810e23d8
/data/data/com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 69): #00 be9666d8 41056c04
I/DEBUG ( 69): be9666dc b0001dbb /system/bin/linker
I/DEBUG ( 69): be9666e0 b00134dc
I/DEBUG ( 69): be9666e4 00000000
I/DEBUG ( 69): be9666e8 002377cc [heap]
I/DEBUG ( 69): be9666ec 0023777c [heap]
I/DEBUG ( 69): be9666f0 00237814 [heap]
I/DEBUG ( 69): be9666f4 00000000
I/DEBUG ( 69): be9666f8 808890ac /system/lib/libdvm.so
I/DEBUG ( 69): be9666fc 002377ac [heap]
I/DEBUG ( 69): be966700 00000000
I/DEBUG ( 69): be966704 8088a018 /system/lib/libdvm.so
I/DEBUG ( 69): be966708 0000cd58 [heap]
I/DEBUG ( 69): be96670c 810aefb0
/data/data/com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 69): be966710 000a6238 [heap]
I/DEBUG ( 69): be966714 80813e00 /system/lib/libdvm.so
I/DEBUG ( 69): be966718 0000cd58 [heap]
I/DEBUG ( 69): be96671c 41056c04
I/ActivityManager( 102): Process com.pascal.lcltest (pid 15168) has
died.

Any ideas?

thanks,
Felipe Monteiro de Carvalho

David Turner

unread,
Nov 28, 2011, 10:56:20 AM11/28/11
to andro...@googlegroups.com
Looks like there is something wrong with your declarations in jni.pas
A PJavaVM should be a pointer to a record containing 4 reserved pointers + a bunch of other pointers.

But you seem to define it as a pointer to a record holding a pointer to a record containing such data.
I.e. it looks like you're using one superfluous redirection.

In other words, you shouldn't use vm^^.GetEnv(...) but vm^.GetEnv(..), same for the PJniEnv definition.



--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.


Felipe Monteiro de Carvalho

unread,
Nov 29, 2011, 6:00:34 AM11/29/11
to android-ndk
On Nov 28, 4:56 pm, David Turner <di...@android.com> wrote:
> Looks like there is something wrong with your declarations in jni.pas
> A PJavaVM should be a pointer to a record containing 4 reserved pointers +
> a bunch of other pointers.

Are you sure? Looking at android-ndk-r5/platforms/android-8/arch-arm/
usr/include/jni.h I see:

#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif

Pascal should be treated as C here, so we use the lower definition,
which is a pointer to a JNIInvokeInterface, which is defined as:

/*
* JNI invocation interface.
*/
struct JNIInvokeInterface {
void* reserved0;
void* reserved1;
void* reserved2;

jint (*DestroyJavaVM)(JavaVM*);
jint (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*);
jint (*DetachCurrentThread)(JavaVM*);
jint (*GetEnv)(JavaVM*, void**, jint);
jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**,
void*);
};

So it is a structure with 3 pointers and 5 pointers to methods.

From here: http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

I see: jint JNI_OnLoad(JavaVM *vm, void *reserved);

So joining all together: vm is a pointer to a JavaVM and JavaVM is a
pointer to a JNIInvokeInterface.

If it was C++ then JavaVM would be a structure with a pointer and some
methods, but I am using the C interface here.

> But you seem to define it as a pointer to a record holding a pointer to a
> record containing such data.

I think you are mixing _JavaVM and JavaVM, which are unrelated when
one uses the C interface to JNI (as opposed to the C++ interface to
it).

From jni.pas located here:
http://lazarus-ccr.svn.sourceforge.net/viewvc/lazarus-ccr/bindings/android-ndk/jni.pas?revision=1437&view=markup

JNIEnv=^JNINativeInterface;
JavaVM=^JNIInvokeInterface;

Like like in jni.h for C and also:

JNIInvokeInterface=packed record
reserved0:pointer;
reserved1:pointer;
reserved2:pointer;

DestroyJavaVM:function(PVM:PJavaVM):JInt;{$ifdef mswindows}
stdcall;{$else}cdecl;{$endif}

AttachCurrentThread:function(PVM:PJavaVM;PEnv:PPJNIEnv;Args:pointer):JInt;
{$ifdef mswindows}stdcall;{$else}cdecl;{$endif}
DetachCurrentThread:function(PVM:PJavaVM):JInt;{$ifdef mswindows}
stdcall;{$else}cdecl;{$endif}
GetEnv:function(PVM:PJavaVM;PEnv:Ppointer;Version:JInt):JInt;
{$ifdef mswindows}stdcall;{$else}cdecl;{$endif}

AttachCurrentThreadAsDaemon:function(PVM:PJavaVM;PEnv:PPJNIEnv;Args:pointer):JInt;
{$ifdef mswindows}stdcall;{$else}cdecl;{$endif}
end;

Which looks the same as the C declaration for me.

> I.e. it looks like you're using one superfluous redirection.

I already tested this hypothesis, and if this was the case it would
crash in my calls in the beginning of JNI_OnLoad, but they all show
fine in the log:

I/nativetest(15168): JNI_OnLoad called
I/nativetest(15168): CurVM=AA00
I/nativetest(15168): CurVM^=80889094
I/nativetest(15168): CurVM^^.reserved0=0
I/nativetest(15168): CurVM^^.GetEnv=808890AC

I rather suspect of something else. Maybe the C interfaces for JNI are
unsupported and only the C++ ones are supported?

Or maybe my structure has a different alignment then expected? But it
contains only things which fit 32-bits like pointers, so this would be
very unlikely and I do specify {$packrecords c}

It is very strange that it crashes with SIGILL. Normally crashes are
SIGSEGV

Felipe Monteiro de Carvalho

unread,
Nov 29, 2011, 11:37:38 AM11/29/11
to android-ndk
Hello,

Maybe assembler comparison could be helpful?

Here is mine for JNI_OnLoad:

function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;

.section .text.n_customdrawnint_jni_onload$pjavavm$pointer$$longint
.balign 4
.globl CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$$LONGINT
.type CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$$LONGINT,#function
CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$$LONGINT:
.stabs "JNI_ONLOAD:F7",36,0,126,CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM
$POINTER$$LONGINT
.stabs "VM:R3",64,0,202,0
.stabs "VM:3",160,0,202,-44
.stabs "RESERVED:R5",64,0,202,1
.stabs "RESERVED:5",160,0,202,-48
.stabs "result:7",160,0,126,-52
.stabs "./customdrawn/customdrawnobject_android.inc",132,0,0,.Lf25
.Lf25:
.stabn 68,0,129,.Ll240 - CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$
$LONGINT
.Ll240:
mov r12,r13
stmfd r13!,{r4,r11,r12,r14,r15}
sub r11,r12,#4
sub r13,r13,#140
str r0,[r11, #-44]
str r1,[r11, #-48]

This means that VM is in R3 and Reserved in R5

And the crashing like:

if VM^^.GetEnv(VM, @curEnv,JNI_VERSION_1_4)<>JNI_OK then begin

.stabn 68,0,135,.Ll249 - CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$
$LONGINT
.Ll249:
ldr r1,.Lj1162
mov r2,#65536
orr r2,r2,#4
ldr r0,[r11, #-44]
ldr r3,[r11, #-44]
ldr r3,[r3]
ldr r4,[r3, #24] <--- Address to Jump to in r4
mov r14,r15
mov r15,r4 <-- This is the Jump
cmp r0,#0 <-- This is the IF
beq .Lj1178

From the crash log and my debug log calls I see that:
r0 0000aa00 r1 81440150 r2 00010004
r0 = vm exactly as passed into my routine, so it cannot possibly be
wrong
r1 = @curEnv
r2 = JNI_VERSION_1_4 is correct

So only 2 things can be wrong here: r1 or the address to jump to

I would be immensely grateful if someone can give an equivalent
assembler for C =)

Another idea would be the Pascal exception handling interfering with
Dalvik, but I tryed to add a null exception mask and it didn't help
with this Pascal call: SetExceptionMask([]);

David Turner

unread,
Nov 29, 2011, 11:54:42 AM11/29/11
to andro...@googlegroups.com
My Pascal is rusty but I think you are still double-dereferencing here:

       ldr     r3,[r11, #-44]    ====> load 'vm' from stack frame where it was saved in the prologue
       ldr     r3,[r3]              ====> read first word at 'vm', i.e. reserved[0] !! THIS IS BAD
       ldr     r4,[r3, #24]       ====> try to access reserved[0] + 24 and load something from it. BOOM

That should really be:

       ldr     r3,[r11, #-44]    ====> load 'vm' from stack frame where it was saved in the prologue
       ldr     r4,[r3, #24]       ====> load address to jump to.

Also your assembly is a bit weird, the sequence:

mov r14, r15
mov r15, r4

Can be replaced by the shorter equivalent:

blx r4

unless you're targetting ARMv4T, which isn't supported by Android anyway (we required a minimum or ARMv5TE and I doubt there are actual devices that aren't at least ARMv6 these days).

In Pascal, this means:

VM^^.GetEnv(...)

Should really be

VM^.GetEnv(...)


Felipe Monteiro de Carvalho

unread,
Nov 29, 2011, 12:12:32 PM11/29/11
to android-ndk
Hello,

On Nov 29, 5:54 pm, David Turner <di...@android.com> wrote:
> My Pascal is rusty but I think you are still double-dereferencing here:

Yes, I am double-dereferencing because it appears to be correct to me
as I explained previously:

typedef const struct JNIInvokeInterface* JavaVM;

jint JNI_OnLoad(JavaVM *vm, void *reserved);

vm is a pointer to JavaVM, JavaVM is a pointer to JNIInvokeInterface.
My C is not very good but I think that JNIInvokeInterface* JavaVM
means that JavaVM is a pointer to JNIInvokeInterface.

In C++ you use only 1 derefecenciation because you call a wrapper
method which does the second dereferenciation for you:

/*
* C++ version.
*/
struct _JavaVM {
const struct JNIInvokeInterface* functions;

#if defined(__cplusplus)
jint DestroyJavaVM()
{ return functions->DestroyJavaVM(this); } <--- See how it does
functions-> the second dereferenciation
jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)
{ return functions->AttachCurrentThread(this, p_env, thr_args); }
jint DetachCurrentThread()
{ return functions->DetachCurrentThread(this); }
jint GetEnv(void** env, jint version)
{ return functions->GetEnv(this, env, version); }
jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args)
{ return functions->AttachCurrentThreadAsDaemon(this, p_env,
thr_args); }
#endif /*__cplusplus*/
};

And this C++ definition appears to be binary compatible with the C
one, because the first element of the record is the functions pointer
to a JNIInvokeInterface

But ok, I just changed my call to use only 1 derefenciation (In Pascal
you cannot simply change ^^ to ^, Pascal has strong typing so the
compiler won't allow, so we use typecasts to this kind of thing):

if JavaVM(vm)^.GetEnv(vm, @curEnv, JNI_VERSION_1_4)<>JNI_OK then
begin

And it crashes anyway:

D/dalvikvm( 5102): Added shared lib /data/data/com.pascal.lcltest/lib/
liblclapp.so 0x447f1a80
I/nativetest( 5102): JNI_OnLoad called
I/nativetest( 5102): CurVM=AA00
I/nativetest( 5102): CurVM^=80889094
I/nativetest( 5102): CurVM^^.reserved0=0
I/nativetest( 5102): CurVM^^.GetEnv=808890AC
I/nativetest( 5102): @curEnv=81440160


W/Rosie (22307): mAddHtcWidgetByOtherActivity = false,
mIsOpenSlideWhenLeaveLaunch = true

I/DEBUG ( 2518): *** *** *** *** *** *** *** *** *** *** *** *** ***
*** *** ***
I/DEBUG ( 2518): Build fingerprint: 'htc_wwe/htc_buzz/buzz/buzz:
2.2.1/FRG83D/295397:user/release-keys'
I/DEBUG ( 2518): pid: 5102, tid: 5102 >>> com.pascal.lcltest <<<
I/DEBUG ( 2518): thread: .pascal.lcltest
I/DEBUG ( 2518): signal 4 (SIGILL), fault addr 40028dd0
I/DEBUG ( 2518): r0 00002200 r1 81440160 r2 00010004 r3 0000aa00
I/DEBUG ( 2518): r4 40028d70 r5 0000cd58 r6 810afdd0 r7 001321f8
I/DEBUG ( 2518): r8 80813e00 r9 0000cd58 10 41056c04 fp be966774
I/DEBUG ( 2518): ip afa030c8 sp be9666d8 lr 810e413c pc
40028dd0 cpsr 60000010
I/DEBUG ( 2518): #00 pc 40028dd0 /dev/ashmem/mspace/
dalvik-heap/zygote/0 (deleted)
I/DEBUG ( 2518): #01 lr 810e413c /data/data/
com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 2518):
I/DEBUG ( 2518): code around pc:
I/DEBUG ( 2518): 40028db0 00000000 00000000 00000000 00000000
I/DEBUG ( 2518): 40028dc0 00000000 00000000 40019098 00000000
I/DEBUG ( 2518): 40028dd0 ffffffff 00000000 00000000 00000023
I/DEBUG ( 2518): 40028de0 4001a3a8 00000000 00000003 00000000
I/DEBUG ( 2518): 40028df0 0101009c 0101009f 010100a0 00000023
I/DEBUG ( 2518):
I/DEBUG ( 2518): code around lr:
I/DEBUG ( 2518): 810e411c e59f10e0 e3a02801 e3822004 e51b002c
I/DEBUG ( 2518): 810e412c e51b302c e5934018 e1a0e00f e1a0f004
I/DEBUG ( 2518): 810e413c e3500000 0a000006 e59f20c0 e59f109c
I/DEBUG ( 2518): 810e414c e3a00004 ebff2f0b e3e00000 e50b0034
I/DEBUG ( 2518): 810e415c ea000006 e59f20a8 e59f1080 e3a00004
I/DEBUG ( 2518):
I/DEBUG ( 2518): stack:
I/DEBUG ( 2518): be966698 afa0109d /system/lib/liblog.so
I/DEBUG ( 2518): be96669c afa012f1 /system/lib/liblog.so
I/DEBUG ( 2518): be9666a0 00000000
I/DEBUG ( 2518): be9666a4 00000004
I/DEBUG ( 2518): be9666a8 be9666a4 [stack]
I/DEBUG ( 2518): be9666ac 00000001
I/DEBUG ( 2518): be9666b0 8136ac68 /data/data/
com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 2518): be9666b4 0000000b
I/DEBUG ( 2518): be9666b8 002383dc [heap]
I/DEBUG ( 2518): be9666bc 00000011
I/DEBUG ( 2518): be9666c0 b000c4a8 /system/bin/linker
I/DEBUG ( 2518): be9666c4 8088a018 /system/lib/libdvm.so
I/DEBUG ( 2518): be9666c8 8088a018 /system/lib/libdvm.so
I/DEBUG ( 2518): be9666cc 0000cd58 [heap]
I/DEBUG ( 2518): be9666d0 810afdd0 /data/data/
com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 2518): be9666d4 810e411c /data/data/
com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 2518): #00 be9666d8 41056c04
I/DEBUG ( 2518): be9666dc b0001dbb /system/bin/linker
I/DEBUG ( 2518): be9666e0 b00134dc
I/DEBUG ( 2518): be9666e4 00000000
I/DEBUG ( 2518): be9666e8 002383dc [heap]
I/DEBUG ( 2518): be9666ec 002383b4 [heap]
I/DEBUG ( 2518): be9666f0 00238304 [heap]
I/DEBUG ( 2518): be9666f4 00238374 [heap]
I/DEBUG ( 2518): be9666f8 00000000
I/DEBUG ( 2518): be9666fc 81440160 /data/data/
com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 2518): be966700 00238334 [heap]
I/DEBUG ( 2518): be966704 00000000
I/DEBUG ( 2518): be966708 8088a018 /system/lib/libdvm.so
I/DEBUG ( 2518): be96670c 0000cd58 [heap]
I/DEBUG ( 2518): be966710 810afdd0 /data/data/
com.pascal.lcltest/lib/liblclapp.so
I/DEBUG ( 2518): be966714 001321f8 [heap]
I/DEBUG ( 2518): be966718 80813e00 /system/lib/libdvm.so
I/DEBUG ( 2518): be96671c 0000cd58 [heap]
I/ActivityManager( 102): Process com.pascal.lcltest (pid 5102) has
died.
E/ActivityManager( 102): fail to set top app changed!

Felipe Monteiro de Carvalho

unread,
Nov 29, 2011, 12:24:09 PM11/29/11
to android-ndk
Hello,

> ldr r4,[r3, #24] ====> try to access reserved[0] +
24 and
load something from it. BOOM

If it was easy like that it would be great =) Getting a SIGSEGV inside
my code would be easy to fix. The problem is that it crashes inside
dalvik, not in my library.

For completeness the new assembler using 1 dereferenciation is:

.stabn 68,0,139,.Ll249 - CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$


$LONGINT
.Ll249:
ldr r1,.Lj1162
mov r2,#65536
orr r2,r2,#4
ldr r0,[r11, #-44]
ldr r3,[r11, #-44]

ldr r4,[r3, #24]
mov r14,r15
mov r15,r4
cmp r0,#0
beq .Lj1178

Felipe Monteiro de Carvalho

unread,
Nov 30, 2011, 11:11:58 AM11/30/11
to android-ndk
Another thing which I tried was changing from SurfaceView to View,
thinking that maybe the problem was because I am calling my JNI
routines from onDraw from my surface, but nothing changed =(

I also tryed:

if vm^^.AttachCurrentThread(curVM,@curEnv,nil)<>JNI_OK then

Just as a long shot to see if it could work. But also crashes.

At least one other person has this problem, but his is specific for
HTC while mine seams to be everywhere (although I only tested in HTC
Wildfire and in the emulator):
http://stackoverflow.com/questions/8079917/vm-getenv-segfaults-only-on-htc-devices

I am running out of ideas. And the worse thing is that this really
blocks a lot of functionality. To start with I cannot implement text
rendering in my framework unless I add something like pango or
freetype, which is not something I am looking forward to, the standard
platform text rendering would be much better.

Felipe Monteiro de Carvalho

unread,
Nov 30, 2011, 12:14:19 PM11/30/11
to android-ndk
Hello,

Ok, it seams that I found the problem!

Now I tested in other devices without any code changes (so using 2
dereferenciations) and it works in all of them, for example HTC Desire
HD with Android 2.2, Motorola Atrix, etc.

It looks like that it only crashes in HTC Wildfire updated to 2.2. No
idea if it crashes in all updated wildfires (it won't run in the stock
one because my project is for 2.2+), or what is special in Wildfire or
my particular Wildfire...

I haven't actually studied this deep to see if it also behaves 100%
correct everywhere but I tested a couple of calls and they all work
fine now. So I am no longer stuck =)

Felipe Monteiro de Carvalho

unread,
Nov 30, 2011, 3:49:31 PM11/30/11
to android-ndk

Ah, it still crashes in the emulator =( It is not indispensable to
support the emulator and Wildfire, but I'm still interrested in ideas
of how to definetivelly fix this.

David Turner

unread,
Dec 1, 2011, 6:50:32 AM12/1/11
to andro...@googlegroups.com
On Tue, Nov 29, 2011 at 6:24 PM, Felipe Monteiro de Carvalho <felipemonte...@gmail.com> wrote:
Hello,

 >      ldr     r4,[r3, #24]       ====> try to access reserved[0] +
24 and
load something from it. BOOM

If it was easy like that it would be great =) Getting a SIGSEGV inside
my code would be easy to fix. The problem is that it crashes inside
dalvik, not in my library.


I just double-checked and you're right. Sorry, my bad. You're right that a double-dereference is needed here.
 
For completeness the new assembler using 1 dereferenciation is:

       .stabn 68,0,139,.Ll249 - CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$
$LONGINT
.Ll249:
       ldr     r1,.Lj1162
       mov     r2,#65536
       orr     r2,r2,#4
       ldr     r0,[r11, #-44]
       ldr     r3,[r11, #-44]
       ldr     r4,[r3, #24]
       mov     r14,r15
       mov     r15,r4

One possible explanation for the crash is that the mov r15, r4 doesn't perform an ARM/thumb mode switch on all devices.
Can you try modifying the code generator to use "blx r4" instead of "mov r14, r15; mov r15, r4". This is equivalent except that it is guaranteed to perform the ARM/thumb switch properly on all devices.

Just conjecturing though, but I can't think of anything else right now.
 
       cmp     r0,#0
       beq     .Lj1178

thanks,

Felipe Monteiro de Carvalho

Felipe Monteiro de Carvalho

unread,
Dec 1, 2011, 8:44:55 AM12/1/11
to android-ndk
On Dec 1, 12:50 pm, David Turner <di...@android.com> wrote:
> One possible explanation for the crash is that the mov r15, r4 doesn't
> perform an ARM/thumb mode switch on all devices.
> Can you try modifying the code generator to use "blx r4" instead of "mov
> r14, r15; mov r15, r4". This is equivalent except that it is guaranteed to
> perform the ARM/thumb switch properly on all devices.
>
> Just conjecturing though, but I can't think of anything else right now.

Ah, thank you so much, that was brilliant! =)

I hadn't though about the CPU instruction set at all previously, so I
was just using the default. I don't know what it defaults to, maybe
arm4? Then using fpc -i one can choose from these options:

Supported CPU instruction sets:
ARMV3
ARMV4
ARMV5
ARMV6
ARMV7M
CORTEXM3

So I just added -CpARMV6 to my build options and now GetEnv and other
JNI calls work properly in my HTC Wildfire =)

Here is the new assembler of the problematic line:

.stabn 68,0,144,.Ll327 - CUSTOMDRAWNINT_JNI_ONLOAD$PJAVAVM$POINTER$
$LONGINT
.Ll327:
ldr r1,.Lj1421
mov r2,#65536
orr r2,r2,#4
ldr r0,.Lj1332
ldr r0,[r0]
ldr r3,[r11, #-44]
ldr r3,[r3]
ldr r3,[r3, #24]
blx r3
cmp r0,#0
beq .Lj1418

thank a lot again, you just saved me some money from buying a new
phone and also a lot of headaches =)

Felipe Monteiro de Carvalho

Reply all
Reply to author
Forward
0 new messages