I am writing a C++ code to execute 'top' command in android device. This is the code I use.
using namespace std;
int main()
{
char buffer[1024];
string result;
system("top -n 1 | head -n 4 | tail -n 3");
FILE *memcpu= popen("top -n 1 | head -n 4 | tail -n 3","r");
while (!feof(memcpu)) {
if (fgets(buffer, 1024, memcpu) != NULL)
result+=buffer;
}
cout<<"result you need\n"<<result;
}
I want to run this file in adb device. Hence I build the program using command
arm-linux-gnueabi-g++ -static -march=armv7-a name.cpp -o test
When I run the program, the string result is empty.
I tested the program by including system("top -n 1"); line in the program. But I am not getting any output from adb shell (empty string).
I build the same program using g++ and run in linux pc. And at that time I am getting the correct output. What might be the reason that I am not getting desired output in adb shell from android device?
When you build the program using command
arm-linux-gnueabi-g++ -static -march=armv7-a name.cpp -o test
a static binary is created. In order to link the libraries in android, the program must be built using android ndk build. And that solved the problem for me.
Related
CMakeLists.txt
STRING( REGEX REPLACE ".*/(.*)" "\\1" CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} )
SET(TARGET ${CURRENT_FOLDER})
PROJECT (${TARGET})
add_compile_options(-static -march=armv7-a)
aux_source_directory(./src SRCS)
add_executable(${TARGET} ${SRCS})
hello.c
#include <stdio.h>
int main(void)
{
printf("hello ARM!!!");
return 0;
}
adb push '.\Desktop\hello' /data/local/tmp
adb shell chmod 777 /data/local/tmp/hello
adb shell /data/local/tmp/hello
/system/bin/sh: /data/local/tmp/hello: No such file or directory
adb shell ls -l /data/local/tmp/
-rwxrwxrwx root root 10652 2021-01-21 17:03 hello
When I compile by the following command
arm-linux-gnueabi-gcc -static -march=armv7-a hello.c -o hello
adb push '.\Desktop\hello' /data/local/tmp
adb shell chmod 777 /data/local/tmp/hello
adb shell /data/local/tmp/hello
hello ARM!!!
I found that the compile_commands.json generated by cmake is
"command": "/bin/arm-linux-gnueabi-gcc-8 -g -static -march=armv7-a -o CMakeFiles/hello.dir/src/hello.c.o -c /home/dev/workspace/ASM/Projects/hello/src/hello.c",
I don't know how to solve this problem.
CMake use two steps to generate executable. The first step it compiles the source files ( c or c++) to object file. then it links the file needed to generate the executable(s).
The compile_commands.json will contain only the commands used to compile and not to link. normally you can find the command used to link in link.txt. this file can be found in CMakeFiles/<name>.dir/link.txt.
You can also , directly run your make commad with VERBOSE=1 to see the executed command on live.
For your problem, i think there is a problem with your TARGET variable, but without more information i can not be sure.
I'm trying to generate code coverage report for my native components with AOSP source code using soong build system.
I have extended aosp vhal but unit test cases are same as in below link.
http://androidxref.com/8.1.0_r33/xref/hardware/interfaces/automotive/vehicle/2.0/default/tests/
Tried adding below to cc_test, cc_binary in Android.bp
native_coverage : true,
cflags: [
"-g",
"-O0",
"-fprofile-arcs",
"-ftest-coverage",
],
ldflags : [
"-fprofile-arcs",
"-ftest-coverage",
],
Native binary unit-tests-coverage is generated in out/target/product but I can't find gcno intermediates for this.
Running below command gives me *.gcda files for each test files.
adb shell \
GCOV_PREFIX=/data/local/tmp \
GCOV_PREFIX_STRIP=`echo $ANDROID_BUILD_TOP | grep -o / | wc -l` \
/data/local/tmp/unit-tests-coverage
I have tried below links but not sure how to proceed :(
http://logan.tw/posts/2015/04/28/check-code-coverage-with-clang-and-lcov/
https://android.googlesource.com/platform/bionic.git/+/master-soong
https://android.googlesource.com/platform/build/soong/+/581341d%5E%21/
https://android.googlesource.com/platform/external/e2fsprogs/+/fedfb27%5E%21/
https://android.googlesource.com/platform/development/+/master/scripts/acov#23
http://androidxref.com/9.0.0_r3/xref/bionic/README.md#293
I'm not sure if google's vts framework can be used here to generate native code coverage.
https://codelabs.developers.google.com/codelabs/android-vts-8/#6
"gcnodir" is generated but not sure how to make use of it.
/coverage/data/nativetest64/vehicle-unit-tests-coverage/unit-tests-coverage.gcnodir
Posting answer to my question for other users on SO.
Install coverage tool :
sudo apt-get install lcov (This should install lcov-1.12)
sudo apt-get install gcc-4.6 (Clang generates .gcno approximately equal to gcc 4.2 that aren't compatible
with gcov-4.8. Installing gcc-4.6 to get gcov-4.6 and invoking lcov with '--gcov-tool /usr/bin/gcov-4.6')
Download LLVM 3.8 for llvm-cov to work : http://releases.llvm.org/download.html
All native unit test cases i.e instrumented binary needs to be executed on target. To build and emit clang's instrumentation based profiling. Example: http://androidxref.com/9.0.0_r3/xref/hardware/interfaces/automotive/vehicle/2.0/default/Android.bp#82 (Renamed to vehicle-manager-unit-test for shorter name)
export NATIVE_COVERAGE=true
Add native_coverage: true to test module in Android.bp
Go to: module-name/test
Use mm or make command to build native binary
Ex: For hardware/interfaces/automotive/vehicle/2.0/default/tests/ :
mma or make vehicle-manager-unit-test -j32
Copy coverage enabled instrumented binary to target
adb push out/target/product/product_name/data/nativetest64/vendor/vehicle-manager-unit-test /data/nativetest64/vehicle-manager-unit-test
adb shell chmod +x /data/nativetest64/vehicle-manager-unit-test
Run test cases and generate .gcda files
adb shell \
GCOV_PREFIX=/data/local/tmp \
GCOV_PREFIX_STRIP=echo $ANDROID_BUILD_TOP | grep -o / | wc -l \
/data/nativetest64/vehicle-manager-unit-test
adb shell find -iname *.gcda
adb pull /data/local/tmp/proc/self/cwd/out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0/default/vehicle-manager-unit-test/android_x86_64_silvermont_vendor_cov/obj/hardware/interfaces/automotive/vehicle/2.0/default/tests/ .(Destination folder)
Extract GCNO files from GCNODIR (archive file generated at
out/overage/data/nativetest64/vendor/vehicle-manager-unit-test ) to
same folder with GCDA files
llvm-cov gcov -f -b *.gcda (https://llvm.org/docs/CommandGuide/llvm-cov.html )
lcov --directory . --base-directory . --gcov-tool /usr/bin/gcov-4.6 --capture -o cov.info (http://ltp.sourceforge.net/coverage/lcov.php)
genhtml cov.info -o output
Here's the script which wraps all these commands:
https://gist.github.com/pankajgangwar/f070b8b54e83543f8e3638dcd2cae1b8
here it is explaned how to generate coverage reports, which do require GTest:
these flags enable the generation of test coverage: -fprofile-arcs -ftest-coverage
then one has to use gcov: gcov main_test.cpp
which's output then can be passed on to lcov (for reference):
$ lcov --coverage --directory . --output-file main_coverage.info
from which one can generate an lcov coverage report in HTML format:
$ genhtml main_coverage.info --output-directory out
these .gcda files in .gcnodir are gcov data files. gcov also has an output option --json-format, which might come handy when wanting to consume the coverage data with a web-service.
one of the examples from the links you've provided can be used to generate it for a whole project:
Collect the code coverage results:
$ lcov --directory . \
--base-directory . \
--gcov-tool gcov.sh \
--capture -o cov.info
Generate HTML files:
$ genhtml cov.info -o output
where the only difference is, that the wrapper script would need to be adjusted to call gcov. probably one could even omit the wrapper passed with option --gcov-tool, since it should be directly called.
since one can only prepare the coverage report by adding the compiler flags, the gcov and lcov commands should be setup as post-build script, so that they would automatically generate the report.
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.
So I'm trying to use memfetch to dump the memory of a particular process from my Samsung Galaxy Nexus.
I downloaded memfetch from http://lcamtuf.coredump.cx/
Extracted out its contents using the following command:
tar -xvf memfetch.tgz
Ran an ls on my memfetch directory:
ls
COPYING Makefile memfetch.c mffind.pl README
At this stage i'm supposed to run the make command to get my memfetch executable.
Editing the memfetch.c file, i removed the #include page.h line
So first i downloaded the Android ARM Architecture it with the following command. This was for static cross-compilation for the memfetch:
apt-get install gcc-arm0-linux-gnueabi
Then i edited Makefile at the following areas:
FILE = memfetch
CFLAGS = -Wall -09 -static
CC = arm-linux-gnueabi-gcc
So success, i had my memfetch executable:
make
arm-linux-gnueabi-gcc -Wall -09 -static memfetch.c -o memfetch
ls
COPYING Makefile memfetch memfetch.c mffind.pl README
Then i pushed the memfetch executable into my Android phone:
adb push memfetch /sdcard/memfetch
Now from here i worked things from my phone. I ran executed the adb shell command and created a directory to store the memfetch exectable, ideally to run it from there:
adb shell
su
cd /sdcard
mkdir tmp
mount -t tmpfs tmpfs tmp
cp memfetch tmp
cd tmp
chmod 6755 memfetch
Now here's where the problem comes. When i executed the memfetch, i was getting the following error:
./memfetch 1197
memfetch 0.05b by Michal Zalewski <lcamtuf#coredump.cx>
Usage ./memfetch [ -sawn ] [ -S xxx ] PID
-s - wait for fault signal before generating a dump
-a - skip non-anonymous maps (libraries etc)
-w - write index file to stdout instead of mfetch.lst
-m - avoid mmap(), helps to prevent hanging on some 2.2 boxes
-S xxx - dump segment containing address xxx (hex) only
No matter what PID i tried to dump, i always got the same error. I even tried with various flag combinations but none of them worked :(
Thanks for any help in advanced, let me know if any additional information is required.
That is because of stupidity of Windows Command Line, that make some null characters as input to linux commands.
the solution is, if you don't use other inputs "samwS" comment this lines,
while ((opt=getopt(argc,(void*)argv, "+samwS:h"))!=EOF)
switch(opt) {
case 's': waitsig=1; break;
case 'a': skipmap=1; break;
case 'w': textout=1; break;
case 'm': avoid_mmap=1; break;
case 'S': if (sscanf(optarg,"%x",&onlyseg)!=1)
fatal("Incorrect -S syntax (hex address expected).\n");
break;
default: usage(argv[0]);
}
it you use them just comment
default: usage(argv[0]);
I'm trying to write an android app that backs up data from selected directory of an android device to a remote host using rsync and ssh. When I run the rsync command from adb shell as follows, it works:
rsync -rvz -e "/system/xbin/ssh -y -p 22" "/mnt/sdcard/" "rajeesh#10.0.2.2:backup/"
But my java code using Runtime.exec fails with an error that says:
Error: rsync: failed to exec /system/xbin/ssh -y -p 22: No such file or directory (2)
The code I used is as follows:
String[] commands = {
"rsync", "-rvz", "-e", "\"/system/xbin/ssh -y -p 22\"",
"\"/mnt/sdcard/\"", "\"rajeesh#10.0.2.2:backup/\""
};
Process process = Runtime.getRuntime().exec(commands);
Both rsync and ssh have been placed at /system/xbin and chmoded to 755. Tried replacing "rsync" with "/system/xbin/rsync" also but the issue remains. What would be the issue here?
Found out the issue myself.
When run directly from the shell, quotes have specific meaning and they are required here as follows:
rsync -rvz -e "ssh -y -p 22" "/path/to/src/" "/path/to/dest"
My java snippet above was trying to run the command with the quotes escaped, like "\"arg\"". But quotes not required when used outside shell. The correct usage is:
String[] commands = {
"/system/xbin/rsync", "-rvz", "-e", "/system/xbin/ssh -y -p 22",
"/mnt/sdcard", "rajeesh#10.0.2.2:backup/"
};
I'm not sure but maybe problem is that the destination path (rajeesh#10.0.2.2:backup/) is not absolute?
Also if you what to sync your files in the same device, maybe you should try to not use ssh? And do something like that:
rsync -rvz /mnt/sdcard/some_directory /backup