Segmentation fault using a Native Window in Android - android

We're trying to port a C++ application to Android. We think that using NativeActivity should be easiest, and let all OpenGL/EGL-stuff be done natively.
Right now, we're passing the ANativeWindow-pointer that we get from the android_app struct in android_native_app_glue.h through the application so that it can be used when the window is initialized. Here's a few relevant lines from this code (stripped from debug-code):
bool OpenGLWindowES::Initialize(EGLNativeWindowType wnd, EGLNativeDisplayType dsp,
EGLint redSize, EGLint greenSize, EGLint blueSize, EGLint alphaSize, EGLint depthSize, bool bMultiSample)
{
m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(m_display == EGL_NO_DISPLAY)
{
return false;
}
EGLint iMajorVersion, iMinorVersion;
if (!eglInitialize(m_display, &iMajorVersion, &iMinorVersion))
{
return false;
}
eglBindAPI(EGL_OPENGL_ES_API);
bool ecc = eglChooseConfig(m_display, attribs, &m_config, 1, &iConfigs);
if (!ecc || (iConfigs != 1))
{
return false;
}
EGLint format;
eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(wnd, 0, 0, format);
m_windowSurface = eglCreateWindowSurface(m_display, m_config, wnd, NULL);
//etc
}
This code proceeds with creating a context, makecurrent etc, but we don't get that far. We get a segmentation fault on eglCreateWindowSurface and since the display and config seem to be initialized correctly, this can only mean a problem with the ANativeWindow* (tyepdef'd to a EGLNativeWindowType). Error message:
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000058
We also get a segmentation fault if we call for example:
ANativeWindow_getHeight(wnd);
So the question is, what can cause a segmentation fault at this point? wnd is not null, we've checked this before, so it should be initalized somehow and should be ready to use. Did we miss something before calling this function, or can there be some problem with the pointer?
EDIT: We're currently wondering if this can have something to do with the APP_CMD_INIT_WINDOW command not being sent or received properly (we haven't implemented any command handling at all yet so we're looking into this).

Are you entirely sure that the window is correctly initialized?
The ANativeWindow pointer in the app struct is not automatically set when passed into the native entry point. It is provided by the main Android thread at a later point and will then be sent to the app via the callback system that app_glue has set up.
You need to handle the calls sent to the android_app yourself, in the native_activity example in the NDK they do it like this:
int ident;
int events;
struct android_poll_source* source;
// If not animating, we will block forever waiting for events.
// If animating, we loop until all events are read, then continue
// to draw the next frame of animation.
while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
(void**)&source)) >= 0) {
// Process this event.
if (source != NULL) {
source->process(state, source);
}
....
}
You probably need something like this in your main rendering loop, this will allow app_glue to automatically set the window correctly when it gets it from the main thread.

The problem is wnd, pass the state->window from the main function: void android_main(struct android_app* state) to your bool OpenGLWindowES::Initialize(...) method as the first parameter:
void android_main(struct android_app* state) {
Initialize(state->window /*, other arguments here... */);
}

Related

can't debunk eglSwapBuffers function

I am trying to thoroughly track from user-space into kernel-space to find somewhere I can hook my fingers in in kernel-space to pull some information for my CPU driver. While trying to understand the user-space side a little. I am looking to detect frame buffer swaps so that I can track FPS within the kernel (hopefully). I am working with an Odroid XU3 running Android 4.4.4 and a 3.10.9 kernel.
From what I can tell the buffer swap in the egl library is happening in the eglApi.cpp file with the function EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) pasted below. Now my problem is that I cannot understand how this function is working. It appears to me to call itself recursively as following the return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface) points me back to the same function due to
struct egl_t {
#include "EGL/egl_entries.in"
};
and from the source then
#define EGL_ENTRY(_r, _api, ...) #_api,
EGL_ENTRY(EGLBoolean, eglSwapBuffers, EGLDisplay, EGLSurface)
The complete function (minus trace stuff) pasted from the source file eglApi.cpp
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
ATRACE_CALL();
clearError();
const egl_display_ptr dp = validate_display(dpy);
if (!dp) return EGL_FALSE;
SurfaceRef _s(dp.get(), draw);
if (!_s.get())
return setError(EGL_BAD_SURFACE, EGL_FALSE);
#if EGL_TRACE
...
#endif
egl_surface_t const * const s = get_surface(draw);
if (CC_UNLIKELY(dp->traceGpuCompletion)) {
EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
if (sync != EGL_NO_SYNC_KHR) {
FrameCompletionThread::queueSync(sync);
}
}
if (CC_UNLIKELY(dp->finishOnSwap)) {
uint32_t pixel;
egl_context_t * const c = get_context( egl_tls_t::getContext() );
if (c) {
// glReadPixels() ensures that the frame is complete
s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
}
}
return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
}
I am missing something blatantly obvious and that someone can point out where this function performs the buffer swap so I can delve down the rabbit hole towards my safe place in kernel-space.

Android native C function as variable?

So, I'm working with a library that uses a callback function that is configured and called when it's needed. I need to access local variables in my c function from inside that function and can't make them members of the parent class for other reasons.
So, essentially this is my set up
callback.h
typedef void handler_func(uint8_t *data, size_t len);
typedef struct my_cfg {
handler_func *handler;
} my_cfg;
otherfile.c
#include "callback.h"
void test() {
char *test = "This is a test";
my_cfg cfg = { 0 };
memset(&cfg, 0, sizeof(my_cfg));
my_cfg.handler = my_handler;
// This is just an example, basically
// elsewhere in the code the handler
// function will be called when needed.
load_config(my_cfg);
}
void my_handler(uint8_t *data, size_t len) {
// I need to access the `test` var here.
}
What I need is something like this:
#include "callback.h"
void test() {
final char *test = "This is a test";
my_cfg cfg = { 0 };
memset(&cfg, 0, sizeof(my_cfg));
// This is the type of functionality I need.
my_cfg.handler = void (uint8_t *data, size_t len) {
printf("I can now access test! %s", test);
};
// This is just an example, basically
// elsewhere in the code the handler
// function will be called when needed.
load_config(my_cfg);
}
Please keep in mind that I cannot change the header files that define the function definition for handler_func, nor can I modify the my_cfg struct, nor can I modify the area of the code that is calling the handler_func, my_cfg.handler. They are all internal in the library.
(Also note that there may be code errors above, this is all psuedo code technically. I'm not at my computer, just typing this all out free hand on a tablet)
Edit
From what I understand, nested functions would solve this issue. But it appears that clang doesn't support nested functions.
Reference: https://clang.llvm.org/docs/UsersManual.html#gcc-extensions-not-implemented-yet
clang does not support nested functions; this is a complex feature
which is infrequently used, so it is unlikely to be implemented
anytime soon.
Is there another work around?

Finding the memory address of a Java local variable on the Dalvik Stack from native code

I am using JNI with Android Studio 1.5.1 targeting Android API 18 and my question is:
Q) Without using a tool or changing/modifying the Dalvik VM source code, how can I find the memory address of a Java local variable on the Dalvik Stack from native code?
For example, I try to use the following code (adapted from the Internet) to find the memory address of a Java local variable magicNumber = 0x23420023 but I am getting segmentation fault errors.
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("MyLibrary");
}
public native boolean findMagicNumber(int pid, int tid);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int magicNumber = 0x23420023 ;
int pid = android.os.Process.myPid();
int tid = android.os.Process.myTid();
findMagicNumber(pid, tid);
}
}
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "com_example_magicnumber2_MainActivity.h"
#include <unistd.h>
#include <memory.h>
#define ENOENT 2 /* No such file or directory */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define EINVAL 22 /* Invalid argument */
jboolean validAddress(char* address)
{
if ((access(address, F_OK)==-1) && !(errno == ENOENT) && !(errno == ENAMETOOLONG))
return JNI_FALSE;
else if ((access(address, F_OK)==-1) && (errno == ENOMEM) ||
(access(address, F_OK)==-1) && (errno == EACCES) ||
(access(address, F_OK)==-1) && (errno == EFAULT) ||
(access(address, F_OK)==-1) && (errno == EINVAL))
return JNI_FALSE;
else if (address == NULL)
return JNI_FALSE;
else
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_example_magicnumber2_MainActivity_findMagicNumber(JNIEnv *env, jobject obj, jint pid, jint tid) {
long long startaddr, endaddr, size, offset, inode;
char permissions[8], device[8], filename[200], line[250];
char *start, *end, *candidate;
int result, i = 0;
char filepath[100];
sprintf(filepath,"/proc/%d/task/%d", pid, tid);
FILE* file = fopen(filepath, "r");
jboolean found = JNI_FALSE;
while (fgets(line, sizeof(line), file) && !found) {
sscanf(line,"%llx-%llx %s %llx %s %llx", &startaddr, &endaddr, permissions, &offset, device, &inode);
start = startaddr;
end = endaddr;
mprotect( (void*)start , (end-start), PROT_READ);
candidate = memchr( start, 0x14, (end-start));
while( validAddress(candidate) && !found){
if ((validAddress(candidate[2]) && (candidate[2]== 0x23)) &&
(validAddress(candidate[3]) && (candidate[3] == 0x00)) &&
(validAddress(candidate[4]) && (candidate[4] == 0x42)) &&
(validAddress(candidate[5]) && (candidate[5] == 0x23))){
__android_log_print(ANDROID_LOG_DEBUG,"***","Location=%p WE FOUND IT!", candidate);
found = JNI_TRUE;
break;
return JNI_TRUE;
}
else if ((validAddress(candidate)) &&
validAddress(candidate=memchr(candidate+1, 0x14, (end-candidate)))){;
}
}
}
}
This is an update:
The previous code that I posted was not the latest one, here is the latest one:
The Java Code:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("MyLibrary");
}
public native boolean findMagicNumber(int pid, int tid);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int magicNumber = 0x23420023 ;
int pid = android.os.Process.myPid();
int tid = android.os.Process.myTid();
findMagicNumber(pid, tid);
System.out.println("magicNumber = " + magicNumber );
}
}
The native Code:
JNIEXPORT jboolean JNICALL Java_com_example_magicnumber2_MainActivity_findMagicNumber(JNIEnv *env, jobject obj, jint pid, jint tid) {
long long startaddr, endaddr, size, offset, inode;
char permissions[8], device[8], filename[200], line[250];
char *start, *end, *candidate;
int result, i = 0;
char filepath[100];
sprintf(filepath,"/proc/%d/task/%d/maps", pid, tid);
FILE* file = fopen(filepath, "r");
jboolean found = JNI_FALSE;
while (fgets(line, sizeof(line), file) && !found) {
sscanf(line,"%llx-%llx %s %llx %s %llx %s", &startaddr, &endaddr, permissions, &offset, device, &inode, filename);
if (((strstr(filename, "apk#classes.dex")))==NULL) {
continue;
}
__android_log_print(ANDROID_LOG_DEBUG, "*****************", "%llx-%llx %s %llx %s %llx %s",
startaddr, endaddr, permissions, offset, device, inode, filename);
start = startaddr;
end = endaddr;
candidate = memchr( start, 0x14, (end-start));
while( candidate !=0 && !found){
if ((candidate[2]== 0x23) &&
(candidate[3] == 0x00) &&
(candidate[4] == 0x42) &&
(candidate[5] == 0x23)){
__android_log_print(ANDROID_LOG_DEBUG,"********************************************************************","WE FOUND IT at %p!!!", candidate);
found = JNI_TRUE;
break;
}
else
candidate=memchr(candidate+1, 0x14, (end-candidate));
}
}
}
This code is working and it can find the magic number but it finds it in the memory region mapped to /data/dalvik-cache/data#app#com.example.magicnumber2-1.apk#classes.dex which is not the Dalvik stack.
However, by running the above code and by looking at these two papers : paper1 (appendix B, only the egg-hunting code, I do not need to change any Dalvik code, so skip the code changing part) and paper2, we can notice the following (also to comments on fadden's remarks below):
(1) It seems that the int value magicNumber is stored in one Dalvik register. Also it seems that it is stored in the Dalvik stack and it is not on the native code stack because the int variable magicNumber is declared and assigned a value in the Java code section.
(2) According to the paper1, this answer and as evidence by running the attached latest code, we are not searching for 0x14 using the memchr function but we want to make sure we are at the beginning of a memory cell that store the int in ARM CPUs.
(3) I do not need to call the findMagicNumber function again. I just need to find the memory address of the magic number in the Dalvik stack
(4) I do not need to find nearby variables to the MagicNumber, so this is not a problem in my case.
(5) The project is targeting only Dalvik, so ART is not a problem
(6) I agree, using mprotect() is not a good idea and was not necessary in my case.
(7) If you refer to paper2, you can see that access() can be used for something that it is not designed for, checking if a virtual memory address is valid or not. I’m not using access() for any file related operations, although it was written for that purpose
(8) I do not need to change the variable. I just need the address of the variable magicNumber on the Dalvik stack programmatically without using any tool or changing the Dalvik source code
I want to know which of the memory regions of /proc/pid/task/tid/maps Dalvik uses to store its stack.
As you can see in paper1, the authors in section B.2, line #4, did not explain which memory region from procs/maps they used to assign the start and end variables their values.
It looks like you're trying to open /proc/[pid]/task/[tid]/maps, walk through the map, and manually scan through every address range for a magic number. Setting aside the fact that you're opening the task directory rather than the maps magic file in that directory, this approach has a few problems:
You're not guaranteed that the value is unique. If it appears somewhere else in memory -- perhaps because the value was stored in two different Dalvik registers -- you'll be in the wrong place. If the JIT compiler has compiled this stretch of code, you don't know if the "active" value will be on the managed stack or in a spilled register on the native stack.
You're searching for 0x14, which isn't part of your magic number.
You're scanning for the local variable on the thread that created it. Even if you find it and can change it, once the findMagicNumber method returns, the stack-allocated variable will disappear. It's not guaranteed to be in the same place if the method is called again.
If you were hoping to find related variables nearby, you will again have trouble if the JIT compiler rearranges things.
ART compiles almost everything ahead of time, so this is even less likely to be useful there.
I'm also not sure why you're calling mprotect(), rather than simply skipping the segments that aren't readable. You're forcing the permissions to read-only, disabling write and execute permission, which will cause you to crash when execute permission is disabled for the chunk of code that's executing, or when a thread tries to execute and touches its stack.
The access() system call takes a filename, not a memory address, and reports file permissions. I don't think there's an "is this address valid" call, but since you just sscanf'ed the map entry you shouldn't need one.
The only reliable way to find and change the value of a local variable is to use the JDWP debug interface. The compiler and debugger support work together to make reliable read-write access to local variables possible.
To sum up: the code is seriously broken, the approach is unsound. What problem are you trying to solve?

mysterious JNI behavior on Android

I'm at wits end here and would like to know if anyone's seen anything similar when working with JNI within Android. I'm finding that CallVoidMethod() doesn't work for me unless the void java method had no parameters as well. However, if I simply change the targeted java method to have an int return, then CallIntMethod() works just fine. It's not the end of the world, but I'd like to omit the dummy int return value if I can, just for the sake of simplicity and correctness. The two (almost equivalent) code snippets are below:
// Example One - this works fine!
// java object method
public int java_callback(int value)
{
assert(value == 666);
return 0; // useless
}
// cpp native function
void cpp_callback()
{
// JNI globals
// g_jvm cached as is
// g_cls cached as GlobalRef
// g_obj cached as GlobalRef
JNIEnv *env;
g_jvm->AttachCurrentThread(&env, NULL);
jmethodID mid = env->GetMethodID(g_cls, "java_callback", "(I)I");
env->CallIntMethod(g_obj, mid, 666);
}
// Example Two - this doesn't work!?
// java object method
public void java_callback(int value)
{
assert(value == 666); // never gets here
}
// cpp native function
void cpp_callback()
{
// JNI globals
// g_jvm cached as is
// g_cls cached as GlobalRef
// g_obj cached as GlobalRef
JNIEnv *env;
g_jvm->AttachCurrentThread(&env, NULL);
jmethodID mid = env->GetMethodID(g_cls, "java_callback", "(I)V");
env->CallVoidMethod(g_obj, mid, 666);
}
Let me emphasize that the first example does indeed work, so there's no outside issues here. I simply can't get the code to work unless I have a dummy int return. Ideas?

Android app restarts automatically after a crash

My app is partly written in native app using C/C++. The problem is that whenever C/C++ part crashes for some reason the app dies and then restarts automatically. This causes all kinds of messy problems
Now of course, it should not crash in the native part and I'm trying to weed out all reasons why it would happen. However, if it does happen I'd like to:
Quit gracefully
If it does die, at least not try to restart automatically.
I'm curious as to why this behaviour happens. After some search I tried putting the following line in the main activity element of the AndroidManifest.xml:
android:finishOnTaskLaunch="true"
but the automatic restore still happens.
Anyone knows why this is happening and how to change it?
UPDATE:
I think a more fundamental question is,
Is there something similar to a callback if there is a native crash?
One of the answers suggested 'handling crash signals'. I'd be grateful for any links on how it can be done at an application or module level.
As it stands currently, if there is a crash the app just disappears, there's nothing in logcat, so no debugging is possible.
Try to handle crash signals (SIGSEGV etc.) and send kill to yourself in signal handler. This trick helps me.
Example:
#include <signal.h>
#include <unistd.h>
static void signal_handler(int signal, siginfo_t *info, void *reserved)
{
kill(getpid(),SIGKILL);
}
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
{
struct sigaction handler;
memset(&handler, 0, sizeof(handler));
handler.sa_sigaction = signal_handler;
handler.sa_flags = SA_SIGINFO;
sigaction(SIGILL, &handler, NULL);
sigaction(SIGABRT, &handler, NULL);
sigaction(SIGBUS, &handler, NULL);
sigaction(SIGFPE, &handler, NULL);
sigaction(SIGSEGV, &handler, NULL);
sigaction(SIGSTKFLT, &handler, NULL);
return(JNI_VERSION_1_6);
}
UPDATE2
if you want to see crashlog in android logcat you should use this signal handler
static void signal_handler(int signal, siginfo_t *info, void *reserved)
{
struct sockaddr_un addr;
size_t namelen;
socklen_t alen;
int s, err;
char name[] = "android:debuggerd";
namelen = strlen(name);
// Test with length +1 for the *initial* '\0'.
if ((namelen + 1) > sizeof(addr.sun_path)) {
errno = EINVAL;
return;
}
/* This is used for abstract socket namespace, we need
* an initial '\0' at the start of the Unix socket path.
*
* Note: The path in this case is *not* supposed to be
* '\0'-terminated. ("man 7 unix" for the gory details.)
*/
memset (&addr, 0, sizeof addr);
addr.sun_family = AF_LOCAL;
addr.sun_path[0] = 0;
memcpy(addr.sun_path + 1, name, namelen);
alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
s = socket(AF_LOCAL, SOCK_STREAM, 0);
if(s < 0) return;
RETRY_ON_EINTR(err,connect(s, (struct sockaddr *) &addr, alen));
if (err < 0) {
close(s);
s = -1;
}
pid_t tid = gettid();
if(s>=0)
{
/* debugger knows our pid from the credentials on the
* local socket but we need to tell it our tid. It
* is paranoid and will verify that we are giving a tid
* that's actually in our process
*/
int ret;
RETRY_ON_EINTR(ret, write(s, &tid, sizeof(unsigned)));
if (ret == sizeof(unsigned)) {
/* if the write failed, there is no point to read on
* the file descriptor. */
RETRY_ON_EINTR(ret, read(s, &tid, 1));
//notify_gdb_of_libraries();
}
close(s);
}
wait(NULL);
kill(getpid(),SIGKILL);
}
I took it from android source (can't insert link because android.git.kernel.org is down), but I am not sure that it will work in future Android releases
By default your application should not be automatically restarting. Generally one would have to register for this kind of thing, e.g. via the AlarmManager/keep alives.
Do you have a service as part of your application?

Categories

Resources