Print C stack trace on Android 5/Lollipop - android

I'm trying to debug JNI code written in C running on Android 5. When one of my functions is called, I want to write a stack trace to the adb log so I can see where the function was called from.
The first resources I found indicated I needed to use libcorkscrew, and included complete examples of how to use the library. Unfortunately it seems libcorkscrew is gone from Android 5, and now libunwind is supposed to be used. For my project, there are several problems:
Instructions for getting libunwind into the project are sparse and/or misleading - some resources say to download the project from github and build it (with directions that do not work), others indicate the library is already part of Android 5.
All of the examples are written in C++, and it seems that libunwind only has C++ bindings for the functions within it. Since my code is C, not C++, and writing to a log function rather than through the C++ stdlib, this isn't usable.
Among others, I looked at these pages:
Native Stack Traces on Android Lollipop with libunwind
There's no "libcorkscrew" in Android 5.0...
Android NDK: getting the backtrace
Is there a way to get a stack trace in C code on Android 5 without crashing the program?

Instructions for getting libunwind into the project are sparse and/or misleading
Compiled libunwind is included into modern Android NDKs, such as NDK r16b, at sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libunwind.a. You will have to provide this file to the linker. You will also need to download matching headers, namely libunwind.h and __libunwind_config.h. For NDK r16b, these headers can be fetched here: https://android.googlesource.com/platform/external/libunwind_llvm/+/ndk-r16/include/ .
it seems that libunwind only has C++ bindings
No, it's not so. Most of libunwind bindings are C bindings.
Here is a sample Android command-line app in pure C that uses libunwind:
https://github.com/alexeikh/android-ndk-backtrace-test

Can you use backtrace_symbos_fd at Android? If you can, you could use this one:
void *array[100];
size_t size;
size = backtrace (array, 100);
backtrace_symbols_fd (array, size, STDOUT_FILENO);

Related

Android Studio | CPP file errors error: undefined reference to 'AndroidBitmap_unlockPixels' In bitmap library

I'm trying to use AndroidJniBitmapOperations library.
But I'm a Junior Dev, with no knowledge in the NDK, JNI world.
I succeed to resolve a few errors like 'UnsatisfiedLinkError', but Now I'm getting a new one when I trying to build:
error: undefined reference to 'AndroidBitmap_unlockPixels'
Also I get a few errors inside the CPP file:
1."Incorrect type for parameter 'prarmeterName', which should have type 'jint'.
2."Add extern 'C'"
But I don't sure if the last 2 are important.
Help me to update this library, because its important and talked in SO several times, like: here.
The link for the library it self:
https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations
All what I have done until now is:
https://github.com/LiorA1/MyRevApp
You need to link the library that provides that API. In https://github.com/LiorA1/MyRevApp/blob/master/app/src/main/cpp/CMakeLists.txt, copy the code that you have for the logging library like so:
find_library(log-lib log)
find_library(jnigraphics-lib jnigraphics)
target_link_libraries(JniBitmapOperationsLibrary ${log-lib} ${jnigraphics-lib})
Although I think the template code is actually overly complicated here and you can simplify to just:
target_link_libraries(JniBitmapOperationsLibrary -llog -ljnigraphics)
Untested though.
As for how you can figure out which library you need to use for each Android API, I find the easiest way is to search for it on cs.android.com. For this one, I searched for AndroidBitmap_unlockPixels file:.*\.map\.txt (every NDK API is enumerated in a *.map.txt file). You can also use this page, but the code search is authoritative and makes it easier to look up an individual function rather than just "bitmap", in this case.

Linking errors when using functions from <complex.h> in using API level 22

I'm porting a C and C++ library that currently works on iOS to be used on an Android application. I'm down to these last 3 linker errors (obfuscated for privacy reasons):
/Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10184: error: undefined reference to 'cexp'
/Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10184: error: undefined reference to 'cpowf'
/Users/fer662/projects/xxx/jni/xxx_preprocessing.c:10285: error: undefined reference to 'cabs'
Now I understand these normally come from linking with libm.so (-lm), but i'm doing that already. If I go and check the offending so with nm:
nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-22/arch-x86/usr/lib/libm.so | grep cpow
Nothing comes back. It DOES hoever, if I use api 28
nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-28/arch-x86/usr/lib/libm.so | grep cpow
00003900 T cpow
00003910 T cpowf
00003920 T cpowl
Also, in the static library it does show, even on api 22:
nm -g /Users/fer662/Library/Android/sdk/ndk-bundle/platforms/android-22/arch-x86/usr/lib/libm.a | grep cpow
s_cpow.o:
00000000 T cpow
s_cpowf.o:
00000000 T cpowf
s_cpowl.o:
00000000 T cpowl
The inconsistency is puzzling. Shouldn't it be missing from the header altogether if not supported? Why does the static lib have it and the dylib not?
Would it make sense to statically link against it? And if so, how would I do it, taking into account the right path for the current api version?
My other option seems to go steal an implementation of libm (say http://openlibm.org/) or just these 3 functions I'm using from it.
tl;dr: yes, static linking libm.a should be fine
Check the libm.map.txt file: https://android.googlesource.com/platform/bionic/+/master/libm/libm.map.txt#289
These functions weren't added to Android until O.
Also, in the static library it does show, even on api 22
The static library isn't an API 22 static library. It's actually a ToT build from AOSP. If you're going to static link something, there's no point in using something old.
The reason it (there's actually only one version of libc.a/libm.a per ABI) is duplicated into each API directory is because build systems made for old NDKs expect it. If you look at the unified toolchain in r19 (toolchains/llvm/prebuilts/$HOST), you'll see that there's only one copy per ABI.
The inconsistency is puzzling. Shouldn't it be missing from the header altogether if not supported? Why does the static lib have it and the dylib not?
The header has an ifdef guard that hides it: https://android.googlesource.com/platform/prebuilts/ndk/+/dev/platform/sysroot/usr/include/complex.h#237
If you had a declaration for these functions and you think you were building for API 22, there's something wrong with your build system.
Would it make sense to statically link against it? And if so, how would I do it, taking into account the right path for the current api version?
In general for these sorts of problems this isn't a good solution since the Zygote has already loaded a libc, and loading another one can lead to all sorts of issues since they can conflict. Additionally, much of libc's networking is actually dispatched to netd, and the protocol between libc and netd has changed in the past (and is unfortunately not a versioned protocol).
Building with libc.a is only viable with standalone executables (think strace and gdbserver) rather than apps, and even then only if you don't need networking.
That said, libm.a is much simpler. The complex interactions that make libc.a unusable for apps don't affect libm. The only time you'll end up actually running code in libm is when the compiler somehow failed to inline the operation. Static linking libm.a into your application should be fine.

android NDK HOWTO get stack trace without backtrace

I want to get stack trace when my progrom crash in my .so library, in fact, i call the interface in .so from JNI.
And I follow a old question, but not worked.
All I get in the dumpBacktrace is the signal handler itself.
Here's the link of old question.
platform: arm, ndk-version: android-ndk-r10d
you should definitely check out coffecatch: https://github.com/xroche/coffeecatch

Why SDL_Window is an incomplete type?

I am porting to SDL2 and the Android platform a C++ game that uses SDL 1.2. Everything went well so far except for one thing: when I try to access the fields of SDL_Window, the compiler tells me
error: invalid use of incomplete type 'SDL_Window {aka struct SDL_Window}'
I think my installation of SDL may be faulty. I have compiled SDL 2.0.0 from the source found on libsdl.org using the folloing command:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_PLATFORM=android-18
Then, I have copied the freshly built libSDL2.so into $ANDROID_TOOLCHAIN/sysroot/usr/lib and the files in the include/ directory in $ANDROID_TOOLCHAIN/sysroot/usr/include/SDL. These files are given to CMake and referenced by the game's code. I managed to convert every SDL calls and now I am stuck with this SDL_Window problem.
I did a quick search in SDL's source code and found that SDL.h includes SDL_video.h which contains a typedef SDL_Window on struct SDL_Window. Then I searched for this struct and did not find anything except in the original source archive, in a file named src/video/SDL_sysvideo.h. Since it is not a file of the API, I doubt I have to include it in my code.
So, how to find a definition of SDL_Window in SDL2, for Android (if this is relevant)?
It appears that the problem is a lack of knowledge of SDL 2's API. Let's remember that one does not access the fields of struct SDL_Window: there are functions to get the size and the flags of the window, such as SDL_GetWindowFlags and SDL_GetWindowSize.
So the problem is absolutely not related to the installation of the SDL or to Android builds. Sorry for the waste of time, people of the Web.
I would expect that you are expected to only deal in pointers to SDL_Window objects, and not actually put a full SDL_Window object on the stack.

dlsym returning symbol not found in android after succesful return of dlopen

I am loading one shared library from another. Lets say foo2.so from foo1.so
I am using dlopen followed by dlsym
dlopen succeed with proper handle but dlsym returns with "symbol not found" error .I have used dlerror to print the error.
These are the things i tried. In foo2.so .mk file I added
LOCAL_LDFLAGS += -Wl,--export-dynamic.
I checked the symbol in foo2.so using nm and it is there.
Both the modules are in C except one wrapper file in foo1.so which is in C++, Calling file is in C.
Can any one suggest whether i missed any thing . I am running this on android emulator on froyo.
I would be tempted to poke around at the implementation level and verify things. Look in /proc/PID#/maps and make sure both libraries are loaded.
objdump both caller and callee and make sure that C++ bit didn't mangle the name.
Are you using a suitable RTLD_ flag, and is dlsym getting a valid handle returned by dlopen ?
Can you build (a simplified version of) the two libraries and test executable for a desktop linux or cygwin in order to make sure what you want to do is generally workable - ie, that the problem is android-specific?

Categories

Resources