본문 바로가기

Computer Engineering/Android

Webkit crash 분석하기

시간이 없으니 글은 나중에 차차 다듬기로

(+ 다듬고 올리려고 했는데, 다시 건드릴 일이 없을것 같아서 그냥 비공개만 품...... / 쓰다 만 부분은 다른곳에서 찾으시길... )


안드로이드 4.1.2 버전에서 크래시가 났을경우, 어느부분에서 났는지 찾는 과정을 적어보았다.

(사실, 크래시가 난곳에서 동적분석도 하고싶은데, 그것까진 실패했다. 아마 심볼때문에 그런듯 해서, 안드로이드 full 컴파일을 하고 그 라이브러리들을 안드로이드에 올리면 될수도 있지만, 시간이 너무 오래걸려서 그러진 않았다)


그리고, 사실 이 방법이 가장 효율적인지는 모르겠다.

근데, 아는방법이 이것밖에 없으니...


환경: 우분투 13.04 64bit, 갤럭시노트2(루팅)


1. 안드로이드 기본 소스 다운로드.


$ sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy main multiverse"

$ sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu hardy-updates main"

$ sudo apt-get update

$ sudo apt-get install sun-java6-jdk

$ sudo apt-get install python

$ sudo apt-get install git-core


$ wget http://dl.google.com/android/android-sdk_r22.0.5-linux.tgz

$ tar xzvf android-sdk_r22.0.5-linux.tgz 

$ mv android-sdk-linux android-sdk

$ export PATH=${PATH}:~/android-sdk/tools

$ export PATH=${PATH}:~/android-sdk/platform-tools

$ export PATH=${PATH}:~/bin

$ PATH="$HOME/android-sdk/tools:$HOME/android-sdk/platform-tools:$PATH"

$ android

Tools 전부 설치 (gui에서 해야한다.)


$ sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev libx11-dev:i386 libreadline6-dev:i386 libglapi-mesa:i386 libgl1-mesa-glx:i386 libgl1-mesa-dev g++-multilib mingw32 openjdk-6-jdk tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386

$ sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib/i386-linux-gnu/libGL.so


$ sudo vi /etc/udev/rules.d/51-android.rules

SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", MODE="0666"

( 갤노트라서 이렇게 했고, 각 폰 별로 lsusb를 통해 idVendor를 볼수있다. )


$ sudo chmod a+r /etc/udev/rules.d/51-android.rules


$ mkdir ~/bin

$ PATH=~/bin:$PATH

$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo

$ chmod a+x ~/bin/repo


$ sudo vi /etc/hosts

아래 내용 추가

# Google

74.125.128.82 google.com source.android.com android.googlesource.com

74.125.128.99 google.com source.android.com android.googlesource.com

74.125.128.139 google.com source.android.com android.googlesource.com


# github

207.97.227.239 github.com wiki.github.com gist.github.com assets0.github.com assets1.github.com assets2.github.com assets3.github.com



$ mkdir android

$ cd android

$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.1.1_r2

$ repo sync


안드로이드 다운로드가 시작되는데, 시간이 엄청 오래 걸린다.



2. 각 제조사에서 안드로이드 소스 다운로드

안드로이드는 오픈소스이기때문에, 각 핸드폰별로 안드로이드 소스를 공개하도록 되어있다.
(그렇다고 모든 기능이 추가된채로 오픈되는것은 아니다.)
삼성의 경우 http://opensource.samsung.com/ 에서 받을수 있다.

3. 안드로이드 소스에 적용.

다운받은 소스의 external 폴더를 기존 android 폴더에 덮어쓴다.

4. 디버그 심볼 설정.

기본적으로 strip되서 라이브러리르 만들기때문에, 심볼 설정을 해줘야한다.
build/buildspec.mk.default 를 안드로이드 폴더에 buildspec.mk로 복사한후,

DEBUG_MODULE_libwebcore:=true
DEBUG_MODULE_libxml2:=true
TARGET_CUSTOM_DEBUG_CFLAGS:=-O0 -mlong-calls
ADDITIONAL_BUILD_PROPERTIES += debug.db.uid=100000

를 추가해준다.

그리고
external/webkit/Android.mk 에
LOCAL_PRELINK_MODULE := false
에 주석이 있다면 해제한다.

(이부분은 http://haejung.egloos.com/1160033 분의 블로그 참고)

5. 빌드

$ make clean-libwebcore
$ make clean-libxml2
$ make libwebcore
$ make libxml2
$ make linker

첫번째 빌드라서 시간이 오래 걸린다.

6. 스크립트 

항상 "빌드 -> adb push -> remount /system -> cp" 를 반복해야 한다.

그러므로, 귀찮으니까 쉘 스크립트로 세팅해두자.


makepush.sh , command 라는 파일을 우분투에 만들어두었다.


우선 adb devices로 안드로이드가 연결이 되어있는지 확인하고,


http://pastebin.com/LbnfhdgD

  1. #/bin/sh
  2.  
  3. make libwebcore
  4. adb push out/target/product/generic/system/lib/libwebcore.so /data/local/tmp/libwebcore.so
  5. adb shell < command

makepush.sh 를 만들고

$ chmod 777 makepush.sh


command 도 만들어야하는데, 그 전에


adb shell

su 


로 안드로이드 루트로 접속한다.

그리고

root@android:/ # mount | grep /system

/dev/block/mmcblk0p13 /system ext4 rw,relatime,barrier=1,data=ordered 0 0

로, 나온 /dev/block/mmcblk0p13를 기억해둔다.


그리고 이제 command를 만드는데, 빨간 부분을 위에서 얻은 값으로 고쳐준다.

su

mount -o rw,remount /dev/block/mmcblk0p13 /system

cp /data/local/tmp/libwebcore.so /system/lib/libwebcore.so

exit

exit 


그러면 이제 앞으로, 소스를 수정하면 저 모든 과정을 다 할필요없이

./makepush.sh

만 쳐주면 된다.


7. 디버깅 준비.


$ adb shell setprop debug.db.uid 100000

이렇게 해두어야, 크래시가 났을때 멈춘다.


그리고 gdbserver를 안드로이드로 push 해둔다.


8. 크래시


$ adb shell logcat *:d

디버깅 메세지를 항상 확인하고,

크래시를 일으킨다.


그러면 그 메세지가 로그캣에 모두 보인다.




어느 소스의 몇번째 줄에서 크래시 되었는지가 나온다.