Compiling C code (netcat) to native Android executable - android

I'm writing a bash script that uses Netcat to serve framebuffer over network connection, but first I need to compile it to native executable. I even got this script to work on a Ubuntu machine, where netcat is installed by default.
I found this https://github.com/android/platform_external_netcat but have no experience in NDK at all. This obviously doesn't use JNI or Java at all so default approach for making Android applications won't get me anywhere.
So the question is. How do I get an executable file from this source code?

If anybody else wants to know, this is from the NDK documentation:
SYSROOT=$NDK/platforms/android-<level>/arch-<arch>/
export CC="$NDK/toolchains/<name>/prebuilt/<system>/bin/<prefix>gcc --sysroot=$SYSROOT"
$CC -o foo.o -c foo.c
More specifically, for the netcat from https://github.com/android/platform_external_netcat
SYSROOT=$NDK/platforms/android-19/arch-arm
CC=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$SYSROOT
$CC -DANDROID -c -o atomicio.o atomicio.c
$CC -DANDROID -c -o netcat.o netcat.c
$CC -o netcat atomicio.o netcat.o
Replace the paths from SYSROOT and CC as appropriate.

Look in the Android sdk under docs/STANDALONE-TOOLCHAIN.html it describes how to use the ndk as standalone compiler which can produce arm binaries.

Related

Unable to run dynamically cross compiled application on arm device [duplicate]

I've two files:
lib.c
#include<stdio.h>
void hi() {
printf("Hi i'm a library function in lib.so\n");
}
and main.c
#include<stdio.h>
#include<dlfcn.h>
/* based on Jeff Scudder's code */
int main() {
void *SharedObjectFile;
void (*hi)();
// Load the shared libary;
SharedObjectFile = dlopen("./lib.so", RTLD_LAZY);
// Obtain the address of a function in the shared library.
ciao = dlsym(SharedObjectFile, "hi");
// Use the dynamically loaded function.
(*hi)();
dlclose(SharedObjectFile);
}
And I've tried to build an executables using the following commands:
export LD_LIBRARY_PATH=pwd
gcc -c -fpic lib.c
gcc -shared -lc -o lib.so lib.o
gcc main.c -ldl
And it works pretty well.
Then I've tried to export my program on Android (Nexus One, with ARM-v7-0a arch) using the following commands:
export LD_LIBRARY_PATH=pwd
arm-none-linux-gnueabi-gcc -c -fpic lib.c
arm-none-linux-gnueabi-gcc -shared -lc -o lib.so lib.o
arm-none-linux-gnueabi-gcc main.c -ldl -o main
adb push main /system/app
The result of executing ./main on the correct folder on my smartphone is just:
./main: not found
even if my file is right there!
Am I missing anything during the cross-compile process? Any help?
I'm using the cross-compiler from CodeSourcery and it works well for static programs without .so libraries.
Thanks
EDIT: as Igor states below, that was a linker issue. This command fixes it:
arm-none-linux-gnueabi-gcc -o test main.c -Wl,--dynamic-linker=/system/bin/linker -ldl
in my very case I need other libraries because in /system/lib/ there are no many .so files.
The "not found" message refers not to the shared object but to the dynamic linker. Linux uses /lib/ld-linux.so.2 (or /lib64/ld-linux-x86-64.so.2 for x64) while Android uses /bin/linker. You can check which dynamic loader your program uses with readelf -l, e.g.:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
You can specify a linker to use with ld's --dynamic-linker switch, but there are likely to be other differences. For example, Android uses a stripped-down libc implementation called bionic, and it may be missing functionality that your program relies on, or have different behavior.
You should use NDK or another Android-targeted toolchain when compiling programs for Android. Even though it's based on Linux kernel, the differences are large enough that Linux-targeted toolchains are not sufficient.

Native libs cross compiled from ubuntu linux targeting arm (android)

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.

Error during Cross-compiling C code with Dynamic libraries

I've two files:
lib.c
#include<stdio.h>
void hi() {
printf("Hi i'm a library function in lib.so\n");
}
and main.c
#include<stdio.h>
#include<dlfcn.h>
/* based on Jeff Scudder's code */
int main() {
void *SharedObjectFile;
void (*hi)();
// Load the shared libary;
SharedObjectFile = dlopen("./lib.so", RTLD_LAZY);
// Obtain the address of a function in the shared library.
ciao = dlsym(SharedObjectFile, "hi");
// Use the dynamically loaded function.
(*hi)();
dlclose(SharedObjectFile);
}
And I've tried to build an executables using the following commands:
export LD_LIBRARY_PATH=pwd
gcc -c -fpic lib.c
gcc -shared -lc -o lib.so lib.o
gcc main.c -ldl
And it works pretty well.
Then I've tried to export my program on Android (Nexus One, with ARM-v7-0a arch) using the following commands:
export LD_LIBRARY_PATH=pwd
arm-none-linux-gnueabi-gcc -c -fpic lib.c
arm-none-linux-gnueabi-gcc -shared -lc -o lib.so lib.o
arm-none-linux-gnueabi-gcc main.c -ldl -o main
adb push main /system/app
The result of executing ./main on the correct folder on my smartphone is just:
./main: not found
even if my file is right there!
Am I missing anything during the cross-compile process? Any help?
I'm using the cross-compiler from CodeSourcery and it works well for static programs without .so libraries.
Thanks
EDIT: as Igor states below, that was a linker issue. This command fixes it:
arm-none-linux-gnueabi-gcc -o test main.c -Wl,--dynamic-linker=/system/bin/linker -ldl
in my very case I need other libraries because in /system/lib/ there are no many .so files.
The "not found" message refers not to the shared object but to the dynamic linker. Linux uses /lib/ld-linux.so.2 (or /lib64/ld-linux-x86-64.so.2 for x64) while Android uses /bin/linker. You can check which dynamic loader your program uses with readelf -l, e.g.:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
You can specify a linker to use with ld's --dynamic-linker switch, but there are likely to be other differences. For example, Android uses a stripped-down libc implementation called bionic, and it may be missing functionality that your program relies on, or have different behavior.
You should use NDK or another Android-targeted toolchain when compiling programs for Android. Even though it's based on Linux kernel, the differences are large enough that Linux-targeted toolchains are not sufficient.

Building native library with standalone toolchain android arm

I am trying to build libraw as a Android shared library. It looks the lib is too complex to use with Android.mk etc, or better: I am not capable yet of doing that.
I tried the route of using a standalone toolchain from the NDK, but I am getting stuck when compiling this lib.
This is the path I take to compile the lib. Please point out if I am making obvious errors:
I downloaded the ndk.
ran: make-standalone-toolchain.sh
Added the bin folder of that standalone toolchain as first item in my PATH.
Ran ./configure with --host=arm-linux-androideabi. This succeeded
Ran make, here it crashed very fast.
LibRaw-0.14.4$ make
depbase=`echo internal/dcraw_common.lo | sed 's|[^/]*$|.deps/&|;s|\.lo$||'`;\
/bin/bash ./libtool --tag=CXX --mode=compile arm-linux-androideabi-g++ -DPACKAGE_NAME=\"LibRaw\" -DPACKAGE_TARNAME=\"libraw\" -DPACKAGE_VERSION=\"0.14.4\" -DPACKAGE_STRING=\"LibRaw\ 0.14.4\" -DPACKAGE_BUGREPORT=\"info#libraw.org\" -DPACKAGE_URL=\"http://www.libraw.org\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -I. -I/usr/local/include -g -O2 -MT internal/dcraw_common.lo -MD -MP -MF $depbase.Tpo -c -o internal/dcraw_common.lo internal/dcraw_common.cpp &&\
mv -f $depbase.Tpo $depbase.Plo
libtool: compile: arm-linux-androideabi-g++ -DPACKAGE_NAME=\"LibRaw\" -DPACKAGE_TARNAME=\"libraw\" -DPACKAGE_VERSION=\"0.14.4\" "-DPACKAGE_STRING=\"LibRaw 0.14.4\"" -DPACKAGE_BUGREPORT=\"info#libraw.org\" -DPACKAGE_URL=\"http://www.libraw.org\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -I. -I/usr/local/include -g -O2 -MT internal/dcraw_common.lo -MD -MP -MF internal/.deps/dcraw_common.Tpo -c internal/dcraw_common.cpp -fPIC -DPIC -o internal/.libs/dcraw_common.o
internal/dcraw_common.cpp: In member function 'void LibRaw::read_shorts(ushort*, int)':
internal/dcraw_common.cpp:119: error: 'swab' was not declared in this scope
internal/dcraw_common.cpp: In member function 'void LibRaw::write_ppm_tiff()':
internal/dcraw_common.cpp:9235: error: 'swab' was not declared in this scope
make: *** [internal/dcraw_common.lo] Error 1
I doubt this error message is helpfull here at stackoverflow, but I am left wondering if I should have applied some additional flags or configuration to get this to work?
Note that I am able to compile this lib succesfully if just compiling for my system without crosscompiling. (linux 32bit).
When I am looking to a instruction for building GDAL for Android (here), it uses a additional setting of LIBS="-lsupc++ -lstdc++". This links the STL and C++ exceptions?
However, when I set those before running my configure I get immediately errors like:
configure:3018: checking whether the C++ compiler works
configure:3040: arm-linux-androideabi-g++ conftest.cpp -lsupc++ -lstdc++ >&5
/tmp/android-chain/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: cannot find -lsupc++
collect2: ld returned 1 exit status
So, I am a bit stuck. Someone an idea?
I had to add an implementation of the swab function, since the NDK does not have that one.
Afterwards this compiled fine (but I used the crystax ndk).
A better way toolwise was to just use a Android.mk file and use ndk-build to compile it.
Linker error from the bottom of your question occurs because make-standalone-toolchain.sh from NDK r7 creates incomplete toolchain (it misses some libraries including libsupc++.a). I recommend you try making a toolchain from one of previous NDK releases (r6b should be fine).

Using native C Kiss_fft.c to calculate fft in android

My goal is to compile the kiss_fft libraries to use in JNI for android development.
However to begin with, I am attempting to just use the kiss_fft libraries on my linux machine in C.
when using Kiss_fft.c or Kiss_fftr.c from Kiss_fft (Kissfft
)to calculate the DFT. How exactly do you compile their libraries into your own file. In the top of my source C file, I #include kiss_fft.h and #include kiss_fftr.h, and also either place the kiss_fft souce code in my project root directory or in /usr/include/ in linux, then I compile with a makefile similar to this one:
#Makefile
#ARGS = -g -ansi -pedantic -Wall -Werror -O1
ARGS = -g -lsndfile -O1 -lm
FILES = spec_subv4.o kiss_fftr.o kiss_fft.o
spec_sub: $(FILES)
gcc $(ARGS) $(FILES) -o spec_sub
spec_subv4.o: spec_subv4.c
gcc -lsndfile $(ARGS) -c spec_subv4.c -o spec_subv4
kiss_fftr.o: kiss_fftr.c kiss_fftr.h kiss_fftr.h _kiss_fft_guts.h
gcc $(ARGS) -c kiss_fftr.c -o kiss_fftr
kiss_fft.o: kiss_fft.c _kiss_fft_guts.h
gcc $(ARGS) -c kiss_fftr.c -o kiss_fft
Looking through all the kiss_fft source files, I wrote this make file to build all the dependencies. However I still get
undefined reference to kiss_fft
undefined reference to kiss_fft_alloc
Which are internal functions of the kiss_fft libs.
Any help would be appreciated. Thanks
Your makefile targets never actually compile kiss_fft.c
e.g.
kiss_fft.o: kiss_fft.c _kiss_fft_guts.h
gcc $(ARGS) -c kiss_fftr.c -o kiss_fft
compiles kiss_fftr.c not kiss_fft.c
I think symbol/function kiss_fft, kiss_fft_alloc are not part of any libary included.
Few things must be checked before you link:
Check if symbols are available in library sndfile
nm | grep "kiss_fft"
Check if you have mentioned the PATH for library in make file.
Include your library path as
-L
Check if prototypes of these functions are in harder files
Include them with
-I
If any C,C++ combination code is used
Use extern "C" sytax.
prototypes of functions must match with prototypes included in library.
Worked it out, thanks for the input. I simply just compiled with:
gcc $# -g -lsndfile -lm -std=gnu99 spec_sub_kiss.c kiss_fft.c kiss_fftr.c -o spec_sub_kiss
Where the -lsndfile is the libraries to read and write some .wav files for my project.

Categories

Resources