한동안 native debugging을 할 일이 별로 없어서 좋았는데 또 최근들어 디버깅 할 일이 빈번하게 생겼다. 예전에
안드로이드 Native 단에서 GDB로 디버그하기 를 통해 디버깅 방법에 대해 소개하긴 했지만 이것도 어지간히 귀찮아야지.... -_- 그래서 스크립트로 만들어버렸다;; 하하하...
단말 USB 디버깅으로 연결해 둔 상태에서 앱 실행시키고 안드로이드 풀소스 최상단 디렉토리에서 실행하면 된다. 아, 실행할 때는 앱 패키지 명을 인자로 입력해야 된다. 뭐 당연하겠지만 adb가 있는 디렉토리에 패쓰가 잡혀 있어야 됨.
긁어 붙이기 귀찮으시면 이걸 다우우우우ㅇ우우운~~
androidgdb.sh
(업데이트) 매번 target remote 쳐주는것도 귀찮아서 찾아보니 명령어도 자동으로 실행해 주는 옵션이 있더라. 그래서 이것저것 더 추가할 것 넣고 수정함. 이젠 그냥 명령어만 쳐 주면 알아서 자동으로 gdbserver에 접속까지 해 준다.
소스 보기 그만 볼래
#!/bin/sh
#DEFAULT_PKG=""
TARGET_PKG=""
DEFAULT_PORT="9999"
TARGET_PORT=""
TCVER_GB="4.4.3"
TCVER_ICS="4.4.x"
TCPREFIX_GB="arm-eabi-"
TCPREFIX_ICS="arm-linux-androideabi-"
TOOLCHAIN="prebuilt/linux-x86/toolchain"
TC_GB="$TOOLCHAIN/$TCPREFIX_GB$TCVER_GB"
TC_ICS="$TOOLCHAIN/$TCPREFIX_ICS$TCVER_ICS"
GDB="gdb"
GDB_CURRENT=""
PRODUCT_GENERIC="out/target/product/generic"
SYMBOLS="$PRODUCT_GENERIC/symbols"
SYS="$PRODUCT_GENERIC/system"
SYSBIN="$SYS/bin"
APPPROC="$SYSBIN/app_process"
GDBINIT_PREFIX="$PWD/$SYMBOLS"
GDBINIT_SRCHPATH="$GDBINIT_PREFIX/system/lib/"
PROC=""
SCRIPTNAME=""
step() {
if eval $*; then
return 0
else
echo $ERRORMSG
exit 1
fi
}
script_shortname() {
IFS='/'
set $*
eval SCRIPTNAME=\$$#
}
print_usage() {
script_shortname $0
echo "Usage : $SCRIPTNAME [OPTIONS] PACKAGE_NAME"
echo "Start native debugging session with gdb for Android package, PACKAGE_NAME."
echo ""
echo "Mandatory arguments to long options are mandatory for short options too."
echo " -p, --port=PORT set gdbserver port"
echo " --help display this help and exit"
echo
echo "If you got tired with typing target package name as an argument,"
echo "set environment variable \$DEFAULT_PKG as your package name or"
echo "uncomment/fill the DEFAULT_PKG="" line of this script"
echo
echo "Please report bugs to <doomsday@kldp.org>"
exit 1
}
check_arguments() {
ARGI=0
WATCHNEXT=
for var in $*;
do
OPT=`echo -n $var | grep -G "^-"`
if [ -n "$OPT" ]; then # option!
if [ -n "$WATCHNEXT" ]; then
print_usage
fi
LONGOPT=`echo -n $var | grep -G "^--" | awk -F '=' '{ print $1; }'`
if [ -n "$LONGOPT" ]; then
case $LONGOPT in
"--port")
PORT=`echo -n $var | grep -E "^(--port=)([0-9])+" | awk -F '=' '{ print $2; }'`
if [ -z "$PORT" ]; then
echo "Invalid port '$PORT'"
print_usage
fi
TARGET_PORT=$PORT
;;
"--help")
print_usage
;;
*)
echo "Invalid option '$LONGOPT'"
print_usage
;;
esac
continue
fi
case $OPT in
"-p")
WATCHNEXT="TARGET_PORT"
;;
*)
echo "Invalid option '$OPT'"
print_usage
;;
esac
else
if [ -n "$WATCHNEXT" ]; then
eval $WATCHNEXT=$var
WATCHNEXT=
continue
fi
TARGET_PKG="$var"
fi
done
if [ -z "$TARGET_PKG" ]; then
TARGET_PKG="$DEFAULT_PKG"
fi
if [ -z "$TARGET_PORT" ]; then
TARGET_PORT=$DEFAULT_PORT
fi
if [ -z "$TARGET_PKG" ]; then
print_usage
fi
echo "Debugging $TARGET_PKG package..."
}
check_sourcetree() {
echo -n "Checking Source tree..."
REQFILES="Makefile build/envsetup.sh"
REQDIRS="bionic bootable dalvik development external frameworks hardware packages prebuilt sdk system"
for var in $REQFILES
do
if [ ! -f "$var" ]; then
echo "fail"
ERRORMSG="Run this script in android source root"
return 1
fi
done
for var in $REQDIRS
do
if [ ! -d "$var" ]; then
echo "fail"
ERRORMSG="Run this script in android source root"
return 1
fi
done
echo "ok"
}
check_toolchain() {
echo -n "Checking Toolchain..."
if [ -d "$TC_ICS" ]; then
GDB_CURRENT="$TC_ICS/bin/$TCPREFIX_ICS$GDB"
if [ -f "$GDB_CURRENT" ]; then
echo "ok"
return 0
fi
fi
if [ -d "$TC_GB" ]; then
GDB_CURRENT="$TC_GB/bin/$TCPREFIX_GB$GDB"
if [ -f "$GDB_CURRENT" ]; then
echo "ok"
return 0
fi
fi
echo "fail"
ERRORMSG="No toolchain or gdb"
return 1
}
check_emul_running() {
echo -n "Check if android emulator/device is being attached..."
# check if emulator is already running
DEVS=`adb devices | sed 's/List of devices attached//g' | awk '{print $2}' | grep "device"`
if [ -z "$DEVS" ]; then
echo "fail"
ERRORMSG="Device/emulator is not being attached"
return 1
fi
echo "ok"
return 0
}
check_app_process() {
echo -n "Check if app_process has been retrieved..."
if [ -f $APPPROC ]; then
echo "ok"
return 0
else
if [ -d $SYS ]; then
mkdir -p $SYSBIN
adb pull /system/bin/app_process $SYSBIN/
if [ -f $APPPROC ]; then
echo "ok"
return 0;
fi
fi
echo "fail"
ERRORMSG="Unable to find/retrieve app_process"
return 1
fi
}
check_pkg_running() {
echo -n "Retriving process id for $TARGET_PKG..."
PROC=`adb shell ps | grep $TARGET_PKG | awk '{print $2;}'`
if [ -z "$PROC" ]; then
echo "fail"
ERRORMSG="Unable to find $TARGET_PKG running"
return 1
fi
echo "ok (pid:$PROC)"
return 0
}
run_gdbserver() {
echo "Starting gdbserver..."
WHOAMI=`whoami`
PREVRUN=`ps aux | grep adb\ shell\ gdbserver | grep $WHOAMI`
if [ -n "$PREVRUN" ]; then
kill -9 `echo $PREVRUN | awk '{ print $2; }'`
fi
adb forward tcp:$TARGET_PORT tcp:$TARGET_PORT
adb shell gdbserver :$TARGET_PORT --attach $PROC &
sleep 2
echo "";
}
run_gdb() {
echo "running gdb..."
echo ""
TMPFILE=`tempfile`
cat << END_OF_FILE > $TMPFILE
set solib-absolute-prefix $GDBINIT_PREFIX
set solib-search-path $GDBINIT_SRCHPATH
target remote :$TARGET_PORT
END_OF_FILE
eval $GDB_CURRENT --command="$TMPFILE" $APPPROC
rm -f "$TMPFILE"
}
step check_arguments $*
step check_sourcetree
step check_toolchain
step check_emul_running
step check_app_process
step check_pkg_running
step run_gdbserver
step run_gdb
그만 볼래