다음에서 이어지는 글 

(ndk-gdb가 잘 동작하지 않는 경우 한가지 - run-as에 문제가 있을때 해결법 (1편))



참고로 아래 절차를 성공적으로 수행하려면 에뮬레이터는 상관없지만 폰은 루팅이 되어 있어야 한다.

전편에서 run-as를 원위치로 넣을때 주의해야 할 점이 있다고 했는데 바로 file permission과 file owner ship이다.
원래 있던 run-as의 속성을 보면 다음과 같이 나타난다.
-rwsr-s--- root     shell       59848 2011-11-20 14:36 run-as

새로 만든 run-as를 위와 똑같이 속성을 맞추기 위해서 다음의 명령어를 실행해야 한다.

# chown 0.2000 run-as
# chmod 6750 run-as

참고사항: file permission에 대해 (다음 링크 참조: http://danielmiessler.com/study/unixlinux_permissions/)




-rwsr-s--- root     shell       59848 2011-11-20 14:36 run-as

참고 링크에서도 나와있지만 setuid가 존재하는 이유를 설명하면 사용자가 어떤 파일을 실행할때 권한이 부족해서 실행할 수 없는 경우가 있다. 사용자의 권한이 낮은 경우에도 불구하고 때때로 특정 작업을 할때 사용자의 권한을 높일 수 있도록 하는 방법을 도입한 것이 setid 항목이다. 의미는 setid의 항목이 1로 enable되어 있는 경우 해당파일(run-as)를 누가 접근하던지 상관없이 소유자의 권한이 주어지게 된다. 예를 들어 위와 같은 경우 uid가 일반 사용자이고 run-as의 소유자가 root로 되어 있다. 이때 s=0으로 되어 있으면 일반 사용자가 root가 소유자인 run-as를 읽으려 하면 권한 부족으로 못 읽지만 s=1로 되어 있으면 가능해진다. 이때 x=1이면 일반 사용자가 실행가능하게 된다.

참고로 s=1이고 x=0이면 문자표현에서는 대문자'S'로 표시되고 일반사용자가 파일을 실행할수 없게 된다.


Posted by kevino
,

어떤 ndk 프로젝트를 개발하다가 디버깅하기 위해 ndk-gdb를 실행하면 다음과 같은 오류를 내놓으면서 진행되지 않는 문제가 있다.

Found package name: com.louis.testnative

ABIs targetted by application: armeabi

Device API Level: 10

Device CPU ABIs: armeabi-v7a armeabi

Compatible device ABI: armeabi

Using gdb setup init: ./libs/armeabi/gdb.setup

Using toolchain prefix: /cygdrive/c/NVPACK/android-ndk-r8//toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-

Using app out directory: ./obj/local/armeabi

Found debuggable flag: true

Found device gdbserver: /data/data/com.louis.testnative/lib/gdbserver

ERROR: Could not extract package's data directory. Are you sure that

       your installed application is debuggable?


로그에서 보여지다시피 패키지는 찾았으나 아래 로그에서는 패키지를 못찾겠다고 에러를 출력하는데 이때 의심해 봐야 할 것이 /system/bin/run-as의 버그를 의심해야 한다. 

관련내용은 다음 링크(http://code.google.com/p/android/issues/detail?id=16391)


이미 패치가 나와 있는 관계로 수정해서 새로운 run-as를 만들어 이전과 똑같은 위치에 넣어두고 시스템을 재시작하면 오류가 해결된다.(확인요망)


새로 만든 run-as를 /system/bin에 넣어줄때 몇가지 주의해야 할 사항이 있는데 이는 별도의 게시물로 해서 좀더 자세하게 설명한다.



Posted by kevino
,

1. adb shell로 실행하는 명령어를 root권한으로 실행하게 만들려면

 참고(http://android.stackexchange.com/questions/5884/is-there-a-way-for-me-to-run-adb-shell-as-root-without-typing-in-su)

   안드로이드 루트 폴더에 default.prop이라는 파일을 찾아서 ro.secure=1로 되어 있는 부분을 ro.secure=0으로 바꿔주고 시스템을 재시작한다.(검증 되지 않음)

   재시작후 adb root를 실행하면 adbd가 root권한을 갖게 되어서 이후 adb shell [명령어] 들은 모두 root권한으로 실행되게 된다고 한다.


2. 

Posted by kevino
,

Building android native application

(Referred to following link: http://software.intel.com/en-us/articles/ndk-android-application-porting-methodologies/)



0. Prerequisites

1. Need to install Tegra android development pack from here

2. Install latest cygwin with development tools including gcc, unzip and etc.



1. Download a zipped source code from here.


2. Build apk file


   <Added>

    Set environment variable ANDROID_HOME to $ANDROID_SDK_DIR

   </Added>


    a. $ ndk-build NDK_DEBUG=1 APP_ABI="armeabi armeabi-v7a x86"

    b. $ android.bat update project --path .

           If you see a error something like "Error: The project either has no target set or the target is invalid.", then you need to define what target you want to use using "--target" option. For example, 

    b-1. $ android.bat update project --path . -t android-15

    c. $ ant -f build.xml debug


   <fix>

   f-1. If the compilation fails here with message "sdk.dir is not defined" then use following command to define sdk.dir manually.

    

        ant -Dsdk.dir=$ANDROID_HOME -f build.xml debug


   f-2. With cygwin env, check all project folder including subdirectory set to readable and writable.

        $(PROJECT_HOME) chmod -R a+rw *

    </fix>


   [Otional 1] If you want to check whether generated apk is valid or not, run below command and see the   output message. Below shows an example.

   o-1. 

unzip -l bin/HelloGdbServer-debug.apk

Archive:  bin/HelloGdbServer-debug.apk

  Length      Date    Time    Name

---------  ---------- -----   ----

     2200  06-09-2012 17:25   res/drawable/icon.png

      864  06-09-2012 19:06   res/layout/main.xml

     1500  06-09-2012 19:06   AndroidManifest.xml

     1296  06-09-2012 19:06   resources.arsc

     3976  06-09-2012 19:06   classes.dex

   125208  04-24-2012 23:20   lib/armeabi/gdbserver

    10052  06-09-2012 18:52   lib/armeabi/libhello-gdbserver.so

   125208  04-24-2012 23:20   lib/armeabi-v7a/gdbserver

    10060  06-09-2012 18:52   lib/armeabi-v7a/libhello-gdbserver.so

   214328  04-24-2012 23:20   lib/x86/gdbserver

     2504  06-09-2012 18:52   lib/x86/libhello-gdbserver.so

      881  06-09-2012 19:06   META-INF/MANIFEST.MF

      934  06-09-2012 19:06   META-INF/CERT.SF

      776  06-09-2012 19:06   META-INF/CERT.RSA

---------                     -------

   499787                     14 files



Debugging NDK application


In the project folder, run below command.

  

$ ndk-gdb --force --start --verbose

Android NDK installation path: /cygdrive/c/NVPACK/android-ndk-r8/

Using default adb command: /cygdrive/c/NVPACK/android-sdk-windows/platform-tools/adb

ADB version found: Android Debug Bridge version 1.0.29

Using ADB flags:

Using auto-detected project path: .

Found package name: com.example.hellogdbserver

ABIs targetted by application: x86

Device API Level: 15

Device CPU ABI: x86

Compatible device ABI: x86

Using gdb setup init: ./libs/x86/gdb.setup

Using toolchain prefix: /cygdrive/c/NVPACK/android-ndk-r8//toolchains/x86-4.4.3/prebuilt/windows/bin/i686-android-linux-

Using app out directory: ./obj/local/x86

Found debuggable flag: true

Found device gdbserver: /data/data/com.example.hellogdbserver/lib/gdbserver

Found data directory: '/data/data/com.example.hellogdbserver'

Found first launchable activity: .HelloGdbServer

Launching activity: com.example.hellogdbserver/.HelloGdbServer

## COMMAND: /cygdrive/c/NVPACK/android-sdk-windows/platform-tools/adb shell am start -n com.example.hellogdbserver/.HelloGdbServer

Starting: Intent { cmp=com.example.hellogdbserver/.HelloGdbServer }


.....

Error while mapping shared library sections:

libOpenglSystemCommon.so: No such file or directory.

Error while mapping shared library sections:

gralloc.goldfish.so: No such file or directory.

warning: Unable to find dynamic linker breakpoint function.

GDB will be unable to debug shared library initializers

and track explicitly loaded dynamic code.

(gdb) list

1       /*

2        * Copyright (C) 2010 Max Vilimpoc


(gdb) Line number 31 out of range; jni/hello-gdbserver.c has 30 lines.

c

Continuing.

[New Thread 2259]


Program received signal SIGSEGV, Segmentation fault.

[Switching to Thread 2259]

0xad5bd4af in Java_com_example_hellogdbserver_HelloGdbServer_invokeCrash (

    env=0x8534500, clazz=0xb49b6c70) at jni/hello-gdbserver.c:29

29              *crasher = 0xdeaddead;

(gdb) bt

#0  0xad5bd4af in Java_com_example_hellogdbserver_HelloGdbServer_invokeCrash (

    env=0x8534500, clazz=0xb49b6c70) at jni/hello-gdbserver.c:29

#1  0xb72a3b80 in ?? ()

#2  0x08534500 in ?? ()



Error case #1. 

If you cannot see debug symbols, need to check gdb.debug file whether it has wrong line ending codes. If such case, then run below command to convert dos style line ending to Unix style so that gdb can parse it to display symbols correctly. After this conversion, restart ndk-gdb command above then you will see debug symbol.


$ tr -d '\012' < libs/x86/gdb.setup | tr '\015\015' '\012\012' > libs/x86/gdb.setup


Posted by kevino
,
If you are very poor developer who cannot afford to buy any cheep ARM evaluation kit, then qemu arm version including Google android emulator is a very good tool to experiment any embedded sw stuffs.

Here some instruction to run a basic C application to print "hello" message on Android emulator are shown.
All information listed here are all taken from the following very useful link and I modified source a little bit to support Android serial console out. 


So I will explain my modifications only which comes from the different serial port configuation used to stdio between versatilepb and android goldfish.

#define GOLDFISH_TTY_PUT_CHAR (*(volatile unsigned int *)0xff002000)

/*
 * This does not append a newline
 */
static void putc(int c)
{
GOLDFISH_TTY_PUT_CHAR = c;

void print_uart0(const char *s) {
 while(*s != '\0') { /* Loop until end of string */
 putc(*s); /* Transmit char */
 s++; /* Next char */
 }
}

Full source code can be downloaded here and compiling it will generate test.bin. It can be compiled with google arm tool chain version 4.2.1 included in Android NDK and include that into current PATH list.
mkdir baremetal
cd baremetal
unzip ../baremetal.zip
./bd.sh

To test this bare metal app, 

export ANDROID_SDK_ROOT={path to android sdk}

emulator @fry -kernel ./test.bin










Posted by kevino
,
I do most jobs on Windows for convenience and it makes me to find a way to port some useful linux applications. Here I introduce how to compile okl4_android_3.0 and emulator application runnable on Windows. If you want linux version, then see original link. http://ertos.nicta.com.au/software/okl4htcdream/


Compile android_emulator-ok using MinGW ( Edit: Do not use this. This windows version seems to have problem in dynamic translation from ARM code to x86 ).

1. Download emulator source. android-emulator-ok.tar.gz
2. Unrar it to {emulator_path}.
3. Apply the patch. 
4. Before running build-emulator.sh to build emulator, an sdl package should be compiled but the sdl source included in the above tar file has a compile error with mingw so I recommend to find different way.
5. Download qemu package included android froyo version. http://android.git.kernel.org/?p=platform/external/qemu.git;a=summary
6. Untar qemu package to {qemu_path}
7. cd {qemu_path}/distrib/sdl-1.2.12
8. ./android-rebuild.sh --sdl-config=$LOCAL/bin/sdl-config
9. Now ready to compile emulator
10. cd {emulator_path}/qemu
11. ./android-rebuild.sh --sdl-config=$LOCAL/bin/sdl-config --install=$CURDIR/emulator


Compile qemu included in latest android version using MinGW.

2. build SDL first
cd /d/work/qemu/distrib/sdl-1.2.12
./android-configure --prefix=/d/work/local
make
make install

3. Download below patch and apply it.
4. Build qemu
cd /d/work/qemu
./android-configure.sh --sdl-config=/d/work/local/bin/sdl-config
make



Compile okl4-android_3.0 using cygwin

Build okl4_android-3.0 binary using cygwin. Because python lower version 2.6 is required to compile okl4 source tree without any compile error, we need to install cygwin with python version 2.5 and it could not be done in MinGW. Please correct me if I am wrong.

1. For successful compile, setup build environment.
2. Download android-ndk package
3. Install it somewhere
4. export PATH={ndk_root}/build\prebuilt\windows\arm-eabi-4.2.1\bin:$PATH
5. Download soruce : okl4-android-3.0.tar.bz2
6. cd {okl4_path}
7. tar xfvj okl4-android_3.0.tar.bz2
8. Download and apply the patch. 
9. cd okl4-android_3.0
10. tools/build.py machine=androidsim project=examples example=hello PYFREEZE=False TOOLCHAIN=gnu_arm_eabi_toolchain
11. The above command will generate image.elf file successfully but failed to generate image.boot file. I don't know about python and someone will help me what is wrong?



Running emulator with okl4 test app under MinGW

1. Create an avd file(here froyo) required to run android emulator
2. Run emulator with okl4 example
cd /d/work/
./qemu/objs/emulator.exe @cupcake -os-type okl4 -show-kernel -verbose -kernel ../images/image.boot.bin




Posted by kevino
,

1. How to change file ownership

ex) adb  shell chown 0.2000 /system/bin/bluetoothd


2. android_filesystem_config.h contains predefined User and Group IDs

3. What you must check when kernel panic happens:

Brad Davis  
프로필 보기  
 추가 옵션 9월4일, 오전1시45분
And read all the other "Kernel panic" threads for all the other 
suggestions. 

Again (as a summary): 

1. You need a double buffering frame-buffer driver. 
2. You need MMAP() support on the /data file system. 
3. You need all the Android specific kernel code enabled in your 
kernel. 
4. You need enough RAM to run all the Android code (start with 
192meg). 
5. You need various other features of the Linux kernel enabled and 
running (see a config file from a running Android build). 
6. You may need specific support for your board (drivers and/or 
binding subsystems to drivers). 
7. You may need specific support for your processor architecture (and 
don't assume all architectures are equal). 
8. You need a working fake (if not real) power management driver. 

You also need to be able to use logcat to see the userland log 
messages to see where the system is really dieing. 



Posted by kevino
,

1. First download latest android SDK( any version older than R06 may not work properly )
2. Add path to the tool folder of android SDK
3. Run adb server as root.
sudo adb root

4. Edit android rule file as in this link: http://developer.android.com/guide/developing/device.html

5. Check if device is listed correctly.
Posted by kevino
,

1. NDK 컴파일 방법

2. NDK로 실행파일 만드는 방법 2가지

3. 실행 파일 이나 .so파일을 쉽게 설치하기 위한 bash script 예제

   % 일반적인 폰에서는 .so파일이 설치되는 /system/lib 폴더의 용량이 여유롭지 않아 다소 많은 용량을 설치하기가 어려운데 app2sdcard 기능이 설치되어 있는 경우 추가적으로 /system/sd/expstick/lib에도 설치가 가능해졌다. 이러한 환경에서 수작업으로 파일들을 설치하기가 번거로와 이를 자동으로 처리해 주는 bash script를 작성해 보았다.

#!/bin/bash
# bash for loop

VAR="test.so"
defpath=out/apps/$1/armeabi
target_lib_path=/system/sd/expstick/lib
target_bin_path=/data/tmp
cd $defpath
echo "Current path is "  "$(pwd)"

for f in $( ls . ); do
# echo $f
if  test -f $f ; then
    echo $f "is a file"
    # search ".so"
    if [[ "$f" =~ t*.so ]]
    then
#echo $f "is dynamic library"
echo $f " Install to " $target_lib_path
        adb push ./$f $target_lib_path
    else
if test -x $f ;
then
#echo $f "is executable"
echo $f " Install to " $target_bin_path
adb push ./$f $target_bin_path
adb shell chmod 4777 $target_bin_path/$f
fi
     fi
else
     echo $f "is not a file"
fi
done 


Posted by kevino
,

Original Link: http://betelco.blogspot.com/2010/01/buildingdebugging-android-native-c.html

Building/Debugging android native C applications

In this post I will explain how to compile, install and debug an Android native "C" application.
If you are reading this post just because you have googled the magic keywords ("android" + "native code") then you should know that there is an easier way to build native applications using android makefiles ("Android.mk" and "Application.mk").
The method I'm describing here is only useful if you want to understand how things work in order to create more complexstandard GNU makefiles. This is also useful if you would like to create your own GNU autotools wrappers to compile projects using GNU configure.
I'm using Windows Vista as host machine but any other supported platforms (e.g. linux-x86 or darwin-x86) should work.

I have tested both the NDK (1.6) and SDK (2.1) on:
  • Windows XP (32-bit) and Vista (64-bit)
  • Mac OS X Snow Leopard
  • Ubuntu Intrepid
Installing Android SDK

To download the latest Android SDK, visit this address http://developer.android.com/sdk/index.html.
If you need information on how to install the SDK, visit this address http://developer.android.com/sdk/installing.html.
If the "SDK setup" fail to update the installed packages you can change the remote site URL from https://dl-ssl.google.com/android/repository/repository.xml to http://dl-ssl.google.com/android/repository/repository.xml (change the URL scheme from HTTPS to HTTP) or try to disable your anti-virus or firewall.

I have installed the SDK version 2.1 under c:/android-sdk (a.r.a /cygdrive/c/android-sdk).
Add an environment variable named ANDROID_SDK_ROOT pointing to the SDK root directory.

Important: You should add "$ANDROID_SDK_ROOT/tools" directory to the $PATH environment variable.
Under *nix:

export PATH=$ANDROID_SDK_ROOT/tools:$PATH
Under Cygwin: Open C:\Cygwin\Cygwin.bat and add:

set PATH=%ANDROID_SDK_TOOLS%;%PATH%
Installing Cygwin

If you are using Windows XP or Vista as host machine then you MUST install Cygwin Devel package with GNU Make (3.81 or later) before installing the NDK.
It should also work with MinGW.

Installing the Android NDK

To download the latest Android NDK, visit this address http://developer.android.com/sdk/ndk/1.6_r1/index.html.
I have uncompressed the NDK version 1.6 under c:/android-ndk (a.r.a /cygdrive/c/android-ndk).
Add an environment variable named ANDROID_NDK_ROOT pointing to the NDK root directory.
To install the NDK:

cd $ANDROID_NDK_ROOT
build/host-setup.sh
If all is OK then the console will print Host setup complete.
To test that the toolchain has been correctly installed you can try to build the hello-jni sample which comes with the NDK by doing this:

cd $ANDROID_NDK_ROOT
make -APP=hello-jni
If all is OK then the console will print:

Android NDK: Building for application 'hello-jni'
Compile thumb : hello-jni <= sources/samples/hello-jni/hello-jni.c SharedLibrary : libhello-jni.so Install : libhello-jni.so => apps/hello-jni/project/libs/armeabi
This mean that your native shared library (libhello-jni.so) have been successfully generated under$ANDROID_NDK_ROOT/apps/hello-jni/project/libs/armeabi folder.

Creating an AVD

AVD stands for Android Virtual Device and can be seen as a device profile (keyboard, dialing pad, skin, screen dimensions, appearance ...) to load into your emulator. You can create as many AVDs as you need.
To create an AVD named "avdtest" targeting platform 2.1 (targetID=android-7):

android create avd -n avdtest -t android-7
If all is OK the console will print:

Created AVD 'avdtest' based on Android 2.1, with the following hardware config: hw.lcd.density=160
Create test.c

Here I will create a basic test.c file under C:\tmp with the following content:

#include <stdio.h>// printf

int main(int argc, char **argv)
{
int i = 1;
i+=2;

printf("Hello, world (i=%d)!\n", i);

return 0;
}
Create makefile

Just create an empty file named makefile (without any extension) under C:\tmp (which is the same directory as test.c).
Now We will fill the makefile step by step.

Add application name, $ROOT directory, install directory and the NDK platform version:

APP := test
ROOT:=/cygdrive/c
NDK_PLATFORM_VER := 1.5
INSTALL_DIR := /data/tm
Add useful environment vars:

ANDROID_NDK_ROOT:=$(ROOT)/android-ndk
ANDROID_NDK_HOST:=windows
ANDROID_SDK_ROOT:=$(ROOT)/android-sdk
PREBUILD:=$(ANDROID_NDK_ROOT)/build/prebuilt/$(ANDROID_NDK_HOST)/arm-eabi-4.2.1
BIN := $(PREBUILD)/bin
You MUST change ANDROID_NDK_HOST value from windows to linux-x86 if you are under *nix or darwin-x86 on MAC OS X.

Add GCC options:

CPP := $(BIN)/arm-eabi-g++
CC := $(BIN)/arm-eabi-gcc
CFLAGS :=
LDFLAGS := -Wl
Add targets

all: $(APP)

OBJS += $(APP).o

$(APP): $(OBJS)
$(CPP) $(LDFLAGS) -o $@ $^

%.o: %.c
$(CC) -c $(INCLUDE) $(CFLAGS) $< -o $@
install: $(APP)
$(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(INSTALL_DIR)/$(APP)
$(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)

shell:
$(ANDROID_SDK_ROOT)/tools/adb shell

run:
$(ANDROID_SDK_ROOT)/tools/adb shell $(INSTALL_DIR)/$(APP)

clean:
@rm -f $(APP).o $(APP)
Building the application

To build the application, switch to the directory where you have created both files and then:

make
At the output of the console you will get many errors saying that it's impossible to find stdlib.h, stdio.h etc etc.
To resolve this issue, add the Bionic header files to $CFLAGS variable like this:

CFLAGS := -I$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
If you retry (make) you will now get this link error:

rt0.o: No such file: No such file or directory
To avoid directly linking against the "C runtime" you must add "-nostdlib" flag to the link options like this:

LDFLAGS := -Wl -nostdlib
If you retry (make) you will now get these link errors:

test.c:(.text+0x34): undefined reference to `printf'
test.c:(.text+0x3c): undefined reference to `exit'
You get these errors because Bionic libc is missing. To add libc you MUST change $LDFLAGS like this:

LDFLAGS := -Wl -L$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
LDFLAGS += -nostdlib -lc

If you retry (make) you will now get this link error:

/cygdrive/c/android-ndk/build/platforms/android-1.5/arch-arm/usr/lib/libc.so: undefined reference to `dl_unwind_find_exidx'
To resolve this issue you MUST specify the first set of directories into which to search the system shared libraries (*.so) . This is done by adding the "-rpath-link" option to the link options like this:

LDFLAGS := -Wl,-rpath-link=$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib -L$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
If you retry (make) you will now get this warning:

/cygdrive/c/android-ndk/build/prebuilt/windows/arm-eabi-4.2.1/bin/../lib/gcc/arm
-eabi/4.2.1/../../../../arm-eabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 000082c8
This is an Android known issue. You have this warning because the linker search "_start" as entry point. You can resolve this issue by renaming your main function. But the elegant way to resolve this issue is to specify the entry point in the link options like this:

LDFLAGS := -Wl,--entry=main,-rpath-link=$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib -L$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
LDFLAGS += -nostdlib -lc
Now When you retry (make) your application will successfully build without any errors or warnings.

Testing your application

Before testing your application you MUST run the emulator like this:

emulator -avd avdtest
where "avdtest" is the name of the previously created avd (see "creating an avd" section).
To install the application on the emulator, open a new console and go to to directory where you have created test.c andmakefile. Install your application on the emulator like this:

make install
If all is OK the console will print:

/cygdrive/c/android-sdk/tools/adb push test /data/tmp/test
304 KB/s (2493 bytes in 0.008s)
/cygdrive/c/android-sdk/tools/adb shell chmod 777 /data/tmp/test
To run the application type:

make run
You will probably get an error message saying:

/cygdrive/c/android-sdk/tools/adb shell /data/tmp/test
/data/tmp/test: not found
This error message is a bit confusing because if you browse the /data/tmp directory you will notice that the executable is here. The question is why?
I spent hours searching and I found that this error happens because the loader fails to load the application because it cannot found a proper linker.
To specify a search directory for the dynamic linker (at run time) you MUST change the link options like this:

LDFLAGS := -Wl,--entry=main,-rpath-link=$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib,-dynamic-linker=/system/bin/linker -L$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
LDFLAGS += -nostdlib -lc
Now rebuild and install your application (make clean && make && make install) then run it again (make run).
The console will print the expected result ("hello, world (i=3)!") but just after we have an segmentation fault error("[1] Segmentation fault /data/tmp/test").
To resolve this issue you can exit the program (exit(0);) just before the main function returns (return 0;). You should also include <stdlib.h>.
If you retry the build&&run process (make clean && make && make install && make run) then you should have:

/cygdrive/c/android-sdk/tools/adb shell /data/tmp/test
Hello, world (i=3)!
which is the expected result.

Debugging your application
Before doing anything you MUST copy the gdbserver file to the emultor.
This file is under $BIN ($ANDROID_NDK_ROOT/build/prebuilt/$ANDROID_NDK_HOST/arm-eabi-4.2.1/bin).
Copy gdbserver to the emulator like this:

adb push gdbserver $INSTALL_DIR/gdbserver
adb shell chmod 777 $INSTALL_DIR/gdbserver
where $INSTALL_DIR is the directory where you have installed your application (it's not mandatory to copy it in this directory).
Before running the server on port 1234 you MUST redirect all tcp connection to this port like this:

adb forward tcp:1234: tcp:1234
it's not mandatory to forward connections to the same port number.
Now it's time to run the server:

adb shell $INSTALL_DIR/gdbserver :1234 $INSTALL_DIR/$APP
note that only the server port is specified (no host).
If all is OK the the server will print something like this:

Process /data/tmp/test created; pid = 246
Listening on port 1234
Now to debug our application we will change the makefile by adding a new debug target like this.

GDB_CLIENT := $(BIN)/arm-eabi-gdb

debug:
$(GDB_CLIENT) $(APP)

To launch the application in debug mode type "make debug" (after make clean && make && make install of course). If you do this, you will see a warning message saying that "no debugging symbols found". No symbols ==> no debug.
To generate debug symbols you MUST change the makefile like this (should not be hard coded like this):

DEBUG = -g
CFLAGS := $(DEBUG) -I$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
Now rebuild and install your application (make clean && make && make install) then run it again (make debug). This (make debug) should open gdb invite command((gdb)) on the same console.
Connect to the server (from the same console) like this:

target remote :1234
Set a breakpoint on the main function and execute step by step (commands above are informational and you can use any gdb commands):

b main
c
n
p i 
#$1 = 1
n
#9 printf("Hello, world (i=%d)!\n", i);
p i 
#$2 = 3
c
#Program exited normally.

The final makefile and test.c files are shown below:

makefile

APP := test
ROOT:=/cygdrive/c
INSTALL_DIR := /data/tmp
NDK_PLATFORM_VER := 1.5

ANDROID_NDK_ROOT:=$(ROOT)/android-ndk
ANDROID_NDK_HOST:=windows
ANDROID_SDK_ROOT:=$(ROOT)/android-sdk
PREBUILD:=$(ANDROID_NDK_ROOT)/build/prebuilt/$(ANDROID_NDK_HOST)/arm-eabi-4.2.1
BIN := $(PREBUILD)/bin
GDB_CLIENT := $(BIN)/arm-eabi-gdb

DEBUG = -g

CPP := $(BIN)/arm-eabi-g++
CC := $(BIN)/arm-eabi-gcc
CFLAGS := $(DEBUG) -I$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
LDFLAGS := -Wl,--entry=main,-rpath-link=$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib,-dynamic-linker=/system/bin/linker -L$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
LDFLAGS += -nostdlib -lc

all: $(APP)

OBJS += $(APP).o
$(APP): $(OBJS)
$(CPP) $(LDFLAGS) -o $@ $^
%.o: %.c
$(CC) -c $(INCLUDE) $(CFLAGS) $< -o $@
install: $(APP)
$(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(INSTALL_DIR)/$(APP)
$(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)
shell:
$(ANDROID_SDK_ROOT)/tools/adb shell
run:
$(ANDROID_SDK_ROOT)/tools/adb shell $(INSTALL_DIR)/$(APP)
debug:
$(GDB_CLIENT) $(APP)
clean:
@rm -f $(APP).o $(APP)


test.c

#include <stdio.h> // printf
#include <stdlib.h> //exit

int main(int argc, char **argv)
{
int i = 1;
i+=2;

printf("Hello, world (i=%d)!\n", i);

exit(0);
return 0;
}

Posted by kevino
,