Is anyone using Google Breakpad for Android native code (NDK) ?
If so, could you elaborate on how to get it up and running (the client side that is).
The docs are very limited and don't mention Android at all. The build system contains android information though which make me think it shouldn't be a problem.
Sorry about that, I did the initial port but I didn't really document anything. However, one of the Chrome engineers did some work on the port and wrote a really nice README:
https://chromium.googlesource.com/breakpad/breakpad/+/master/README.ANDROID
There's also an NDK-compatible Android.mk file in there now, so if you're using the standard NDK build system it should be simple to incorporate Breakpad.
I also found a good example project for that.
As it is in the project you can set up Google Breakpad like:
extern "C" {
void Java_com_pluusystem_breakpadjavacall_MainActivity_initNative(JNIEnv* env, jobject obj, jstring filepath)
{
const char *path = env->GetStringUTFChars(filepath, 0);
google_breakpad::MinidumpDescriptor descriptor(path);
exceptionHandler = new google_breakpad::ExceptionHandler(descriptor, NULL, DumpCallback, NULL, true, -1);
}
}
in the cpp side and like:
// Save Dump Path
initNative(getExternalCacheDir().getAbsolutePath());
in the java side.
After that implementing the bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) function you will be able to do something before the app crashes.
I have experienced and also found this issue which confirms me, that in this function you can't do java callbacks under ART just under DVM (before android 5 - Lollipop).
My example repo for Flutter Android/iOS: https://github.com/Sunbreak/flutter-breakpad.trial
Android
Build libbreakpad_client.a on Linux (e.g. https://multipass.run/)
$NDK is local path of your Android NDK directory
$CLI_BREAKPAD is local clone of https://github.com/Sunbreak/cli-breakpad.trial
cd $BREAKPAD/src/android
cp -r google_breakpad jni
$NDK/ndk-build
Install libbreakpad_client.a of all architectures
mkdir -p ./android/app/src/main/cmakeLibs
cp -r $BREAKPAD/src/android/obj/local/* ./android/app/src/main/cmakeLibs/
run on macOS/Linux
# Device/emulator connected
$ android_abi=`adb shell getprop ro.product.cpu.abi`
$ flutter run
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
I/flutter_breakpad(31631): JNI_OnLoad
D/flutter_breakpad(31631): Dump path: /data/data/com.example.flutter_breakpad/files/f5258c0e-eff3-433a-7ea47880-c756fc17.dmp
$ adb shell "run-as com.example.flutter_breakpad sh -c 'cat /data/data/com.example.flutter_breakpad/files/f5258c0e-eff3-433a-7ea47880-c756fc17.dmp'" >| libflutter-breakpad.so.dmp
run on Linux (e.g. https://multipass.run/)
$ $CLI_BREAKPAD/breakpad/linux/$(arch)/dump_syms build/app/intermediates/cmake/debug/obj/${android_abi}/libflutter-breakpad.so > libflutter-breakpad.so.sym
$ uuid=`awk 'FNR==1{print \$4}' libflutter-breakpad.so.sym`
$ mkdir -p symbols/libflutter-breakpad.so/$uuid/
$ mv ./libflutter-breakpad.so.sym symbols/libflutter-breakpad.so/$uuid/
$ $CLI_BREAKPAD/breakpad/linux/$(arch)/minidump_stackwalk libflutter-breakpad.so.dmp symbols/ > libflutter-breakpad.so.log
Related
I'm trying to build a standard "Hello, World!" command-line executable for Android. The executable is to be run via adb shell.
0. The Go (Golang) Source
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, world!")
}
1A. The Build Command
$ CGO_ENABLED=0 GOOS=android GOARCH=arm GOARM=7 go build .
1B. The Output (Line Breaks Rearranged to Prevent Scrollbars)
# github.com/asukakenji/cross
warning: unable to find runtime/cgo.a
/usr/local/go/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file
/var/folders/dd/6k6vkzbd6d5803xj9zkjdhmh0000gn/T/go-link-150305609/go.o,
file was built for unsupported file format
( 0x7F 0x45 0x4C 0x46 0x01 0x01 0x01 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 )
which is not the architecture being linked (x86_64):
/var/folders/dd/6k6vkzbd6d5803xj9zkjdhmh0000gn/T/go-link-150305609/go.o
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
1C. The Build Command, Again
The following command gives the same result:
$ env CGO_ENABLED=0 GOOS=android GOARCH=arm GOARM=7 go build .
2. The Build Command (Verbose)
I've tried using "-v" as mentioned like this:
$ CGO_ENABLED=0 GOOS=android GOARCH=arm GOARM=7 go build \
-x -ldflags "-extldflags -v" .
It gives me more than 100 lines of messages, so I don't post it here unless it's necessary. The go build command seems to try compiling the source with the clang bundled with Xcode.
3A. The Build Command (Successful, but...)
Given the hint that the wrong compiler is found, I tried to set $CC like this:
$ CGO_ENABLED=0 GOOS=android GOARCH=arm GOARM=7 \
CC=/path/to/arm-linux-androideabi/bin/clang go build .
arm-linux-androideabi is the output from make_standalone_toolchain.py (or make-standalone-toolchain.sh).
3B. The Output
The executable (named cross) is successfully built, with the following messages:
# github.com/asukakenji/cross
warning: unable to find runtime/cgo.a
I tried adb push it and run it with adb shell on Android, it worked fine.
My Questions
Why does it need a C compiler? Doesn't Go cross-compile out-of-the-box?
When building for Linux (instead of Android), the compilation works fine:
$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
Why?
The go build command keeps looking for runtime/cgo.a, even when I didn't use CGO in the source code, and even when I set CGO_ENABLED=0. How can I get rid of the warning? How is it harmful not having one?
if you run that code you find the android as an official target platform
listed as GOOS/GOARCH
$go tool dist list
Android isn't official target platform for cross-compilation. If all you need are command-line executables then you can set GOOS=linux because android is a linux under the hood, else take a look at https://github.com/golang/go/wiki/Mobile
The cgo requirement might be because go requires libc for DNS lookups on Android: https://github.com/golang/go/issues/8877
You need to use Android NDK to compile for android, you can download it from the link, or from Android Studio:
Then you can find the compilerlink in the route as below:
Last login: Fri Sep 4 09:25:16 on console
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
Hasans-Air:~ hajsf$ pwd
/Users/hajsf
Hasans-Air:~ hajsf$ cd Library
Hasans-Air:Library hajsf$ cd android
Hasans-Air:android hajsf$ cd sdk
Hasans-Air:sdk hajsf$ cd ndk
Hasans-Air:ndk hajsf$ ls
21.3.6528147
Hasans-Air:ndk hajsf$ cd 21.3.6528147
Hasans-Air:21.3.6528147 hajsf$ cd toolchains
Hasans-Air:toolchains hajsf$ cd llvm
Hasans-Air:llvm hajsf$ cd prebuilt
Hasans-Air:prebuilt hajsf$ ls
darwin-x86_64
Hasans-Air:prebuilt hajsf$ cd darwin-x86_64
Hasans-Air:darwin-x86_64 hajsf$ cd bin
Hasans-Air:bin hajsf$ pwd
/Users/hajsf/Library/android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin
Then you can use the one reflectiong:
Archeticture you want to build your android app for, like aarch64
Android API you want to compile for, like Android 30
You can see full list of availbe options there, and you can seect the one you want like aarch64-linux-android30-clang
If you are at Windows 10 you'll find it at:
"C:\Users\${user}\AppData\Local\Android\Sdk\ndk\${NKD_version}\toolchains\llvm\prebuilt\windows-x86_64\bin\aarch64-linux-android30-clang"
There are 4 avaiailble linkers which are:
//CC_FOR_TARGET=/Users/hajsf/Library/android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android30-clang
//CC_FOR_TARGET=/Users/hajsf/Library/android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/i686-linux-android30-clang
//CC_FOR_TARGET=/Users/hajsf/Library/android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/x86_64-linux-android30-clang
//CC_FOR_TARGET=/Users/hajsf/Library/android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi30-clang
After that only you can do cross copiling, as:
$ CGO_ENABLED=1
$ GOOS=android
$ GOARCH=arm64
$ CC_FOR_TARGET=/Users/hajsf/Library/android/sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android30-clang
$ go build -buildmode=c-shared -o lib-aarch64-android30.so lib.go
And a simple cgo file lib.go could be:
package main
import "C"
import "fmt"
//export HelloWorld
func HelloWorld() {
fmt.Printf("hello world from GO\n")
}
//export GetKey
func GetKey() *C.char {
theKey := "123-456-789"
return C.CString(theKey)
}
func main() {}
As shown copilation completed successfuly, and both lib-aarch64-android30.so and ib-aarch64-android30.h had been generated without any error.
Quick note, not to go far from the scope of the question, if you return a string, then the return value from this function must be explicitly freed in the C code if if you call it from C code, but as you call it from garbage collector environment, Java/Kotlin you do not want to worry about it.
If freeing the allocated buffer isn't convenient, its common to fill a buffer provided by the caller:
func GetKey(buff *C.char, n int) int
If you can allocate the memory but don't want to handle C strings, you can insert the buffer into a pointer and return the size.
func GetKey(buff **C.char) int
Cocos2d-x 3.7.1 + ndk r10e project on Mac trying to debug in Eclipse. Days pass and the errors keep coming...
I can build and run using cocos compile and cocos run with -p android -m debug --ndk-mode NDK_DEBUG=1 from the terminal in proj.android.
My app runs Ok (eventually) on my x86 emulator no problem.
Typing 'ndk-gdb' in the terminal from ./proj.android and I get the error
ERROR: Could not find gdb.setup under ./libs/
BUT the file gdb.setup (and gdbserver & libcocos2dcpp.so) can be seen in ./proj.android/libs/x86 !?
My AndroidManifest.xml includes android:debuggable="true"
My jni/Application.mk includes APP_ABI := x86 (only)
If anyone can tell me how I can diagnose or fix this problem then I guess I owe them a beer (in Yorkshire btw)
UPDATE: I have tried running up GDB using the --verbose flag. The output shows
Using gdb setup init: ./libs/armeabi/gdb.setup
Using app out directory: ./obj/local/armeabi
Guess I need to change to settings/init file somewhere??
I ran into the same problem. It seems something changed in recent version of Android Build tools.
The trick is:
ERROR: Could not find gdb.setup under ./libs/
It expects gdb.setup is in the directory libs but NOT libs/armeabi
so the simple workground is to copy gdb.setup and gdbserver from "libs/cpu" to "libs" and it works like a magic!
This is a bug caused by adb from android sdk.Issue 191085: ndk-gdb issue - Could not find gdb.setup under ./libs/ (even though it's there)
Currently previewl channel's adb whose version is 1.0.35 still has the same problem.
Without revert adb to 1.0.31.A simple workaround would be modify ndk-gdb a little: change the line if [ $? = 0 ]; then which is below adb_var_shell BCFILES run-as $PACKAGE_NAME /system/bin/sh -c "ls lib/*.bc" to if [ $? = 1 ]; then
I'm experimenting with native libs cross compiled from ubuntu. What I really want is to be able to compile my c++ libraries and use them in a Xamarin.Android app.
First, I have the arm gcc compiler: arm-linux-gnueabi-gcc. I have a simple lib (libmr.so) that has one function void Print(); that prints something to the console. I'm compiling with:
arm-linux-gnueabi-gcc -Wall -shared -o libmr.so mr.c
When inspecting it using file libmr.so everything seems to be good. However when I'm including it with my android app and try to load it, it is as if it doesn't exist. I'm certain it is there, the path is absolutely correct as I tried to load another lib (libmonodroid.so) from the same folder and it worked.
I tried inspecting both libs to find some kind of a difference:
$ objdump -x libmr.so | grep NEEDED
NEEDED libc.so.6
$ objdump -x libmonodroid.so | grep NEEDED
NEEDED libc.so
... (in addition to other libs)
This is the only difference I'm finding between the two. libmonodroid.so loads properly but libmr.so acts as if it doesn't exist. (I'm using dlopen to load a lib)
EDIT:
I built an executable using the same toolchain, gave me a clue:
Static linking with libc: arm-linux-gnueabi-gcc -Wall -o hi source.c -static. Pushed hi to my android devices and executed it with adb. Result: SUCCESS!
Dynamic linking with libc: arm-linux-gnueabi-gcc -Wall -o hi source.c. Result: it's not even there! Meaning ./hi gives /system/bin/sh: ./hi: not found although it's absolutely there.
So, looks like libc is really the culprit? Maybe I need to link dynamically with not libc.so.6 but with libc.so just like libmonodroid.so is doing?
Check this out for anyone having the same problem. Download the ndk, there's a standalone toolchain for building native libs that run on android that you can extract (you won't need the whole ndk).
I was able to run a basic app on ubuntu 15.04 with this Makefile in the same dir as my hi.c:
$ cat hi.c # create hi.c with favorite editor
#include <stdio.h>
int main(int argc, char** argv) {
int uid = getuid();
int eid = geteuid();
printf("Hello world\n");
printf("You are uid: %d and eid; %d", uid, eid);
return 0;
}
$ cat Makefile # create two line Makefile
CC=arm-linux-gnueabi-gcc
LDFLAGS=-static
$ make hi # build arm based hi executable file
arm-linux-gnueabi-gcc -static hi.c -o hi
$ file hi # check file type
hi: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=17b65e60cdd32449ac237bfd1b8238bfa1d416a0, not stripped
$ adb push hi /data/local/tmp # copy to droid fon
4403 KB/s (593252 bytes in 0.131s)
$ adb shell /data/local/tmp/hi # run hi executable
adb shell /data/local/tmp/hi
Hello world
You are uid: 2000 and eid; 2000
$ uname -a
Linux lenny 3.19.0-28-generic #30-Ubuntu SMP Mon Aug 31 15:52:51 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
Note that I do not have any NDK installed.
I have a Device on which I installed Android Gingerbread 2.3.4
Here i want to run C executable file on android device
I am able to run android NDK application on this Device and it runs perfect.
But I want to run only one hello.c executable file on the Device.
/* #includes #defines ... */
int main(){
// Do something when this is executed
return 0;
}
Is there any way to compile this file with Android NDK tool chain so I can run this file's executable?
I found one thing here but this is not working for me. I am using Android NDK, Revision 7b for Linux.
There is no directory structure like this.
First, let me say that my answer is dependent on your using NDK r7b (it'll work for r7c as well) on Linux (change paths appropriately for other systems).
Edit: Last tested with NDK r8e on Linux and Nexus 4 with adb from SDK Platform-Tools Rev 18 on Windows 7 (latest as of 2013-07-25) without root access.
Yet Another Edit: Please read this question for altering my instruction for native binaries that need to run on Android 5.0(Lollypop) and later.
Go to $NDK_ROOT (The topmost folder of NDK zip when unzipped).
Copy $NDK_ROOT/samples/hello-jni directory as $NDK_ROOT/sources/hello-world.
Go to $NDK_ROOT/sources/hello-world.
Edit AndroidManifest.xml to give the application an appropriate name (This is optional).
Go to $NDK_ROOT/sources/hello-world/jni. This is where the source code is.
Edit hello-jni.c, remove all the code, and put in your hello world code. Mine is:#include
int main( int argc, char* argv[])
{
printf("Hello, World!");
return 0;
}
Edit Android.mk and change the line include $(BUILD_SHARED_LIBRARY) to include $(BUILD_EXECUTABLE). You can also change the LOCAL_MODULE line to the name you want for your executable(default is hello-jni)
Go back to $NDK_ROOT/sources/hello-world
Run ../../ndk-build to create the executable.
Copy it from $NDK_ROOT/sources/hello-jni/libs/armeabi/hello-jni to /data/local/tmp on the Android device and change it's permissions to 755 (rwxr-xr-x). If you changed the LOCAL_MODULE line in $NDK_ROOT/sources/hello-world/jni/Android.mk, the executable name will be the new value of LOCAL_MODULE instead of hello-jni. (All this is done via adb from the Android SDK.)
Execute the binary with full path as /data/local/tmp/hello-jni, or whatever you named it to.
And you're done( and free to start on the documentation in $NDK_ROOT/docs to get a better idea of what to do).
The best/easiest place to put a executable is /data/local. You'll also need to chmod the binary as executable. Often you'll also need to do this in two steps to get the binary from /sdcard/ to /data/local:
$ adb push mybin /sdcard/
$ adb shell
$ cp /sdcard/mybin /data/local/mybin
$ cd /data/local
$ chmod 751 mybin
Caveats:
Not all systems have cp. You can use cat if this is the case:
$ cat /sdcard/mybin > /data/local/mybin
Some systems don't allow write in /data/local for the "shell" user. Try /data/local/tmp
the "/sdcard" location is not executable, meaning that any file there is not executable at all.
the only way to "adb push" executable would be to put them in "/data/local", which should be writable for adb, and allow execution for anyone.
I recently had the same problem on a new nexus-5. I'd like to add that /data/local was not writable by the user ("shell", uid 2000) I got with adb shell. But putting the executable in the subdirectory /data/local/tmp/ worked fine.
In a nutshell,
First, to cross-compile your C code from your host machine, use NDK toolchain with sysroot option and position independent option -fPIE -pie.
$NDKROOT/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-gcc \
--sysroot=$NDKROOT/platforms/android-22/arch-arm64 -fPIE -pie main.c -o main
the arch part arrch64 or arch-arm64, the toolchain version part 4.9, platform version part android-22, and the binary format for your host machine darwin-x86_64 may vary by your environment.
Second, push your binary under /data/local/tmp and execute it from adb shell.
Is there any way to have C/C++ compilers directly into the Android device ?
Something like I can adb shell the device and run gcc or agcc or something related to compiling C\C++ src files.
I googled, but there were just speculations, please help in this !
Thanks in Advance :) :)
Shoaib
If you install c4droid you can make an onboard executable by finding the gcc binary and calling it. I also have root on my phone.
On your phone or tablet:
Install c4droid(paid app) and additionally GCC plugin(free).
Install a terminal client. I use Better Term but there are free options as well.
find / -name gcc
/mnt/sdcard/Android/data/com.n0n3m4.droidc/files/gcc/bin/arm-linux-androideabi-gcc
cat > test.c
#include<stdio.h>
int main(){
printf("hello arm!\n");
return 0;
}
./mnt/sdcard/Android/data/com.n0n3m4.droidc/files/gcc/bin/arm-linux-androideabi-gcc test.c -o test
./test
hello arm!
Try C4droid
https://market.android.com/details?id=com.n0n3m4.droidc
or this app
https://market.android.com/details?id=GDE.Main