CodeViser Technical Document aesop S5PC100 안드로이드디버깅가이드 CS Team Rev.1 2010.09.13 J&D Tech Co., Ltd. Copyright @2010 J&D Tech Co., Ltd.
Revision History Date Update Author 2010.09.13 최초작성김성곤 aesop S5PC100 안드로이드디버깅가이드 : TEL : +82-70-7547-7125 FAX : +82-31-211-0859 cs@jndtech.com www.jndtech.com Address : 경기도수원시영통구매탄동 1276번지레몬스포렉스 306-2호 Zip Code : 443-848 이후로언급된회사명및제품명은각회사의고유상표또는등록된상표입니다. 이문서의내용은 제이앤디테크의허락없이무단으로복제, 출판되는것을금합니다. Printed in Korea
목차 1. Android 플랫폼개요... 6 1.1. Android 주요기능... 6 1.2. 안드로이드구조... 6 1.2.1. Applications... 6 1.2.2. Application Framework... 6 1.2.3. Libraries... 7 1.2.4. Android Runtime... 8 1.2.5. Linux Kernel... 9 1.3. Android Boot-up Sequence... 9 2. 환경설정... 12 2.1. 소스코드준비... 12 2.2. 스크립트작성... 12 2.3. 스크립트실행... 16 3. Android 시스템디버깅... 18 3.1. Device Driver 디버깅... 18 3.1.1. USB 드라이버... 18 3.1.2. Frame Buffer 초기화... 19 3.1.3. Audio 드라이버... 20 3.2. init 프로세스디버깅... 21 3.3. Daemon 디버깅... 23 3.3.1. 디버거데몬 (debuggerd)... 23 3.3.2. 볼륨데몬 (vold)... 26 3.4. App_process 디버깅... 27 3.5. HAL 디버깅... 29 3.6. JNI 디버깅... 34
전제조건 본문서에서는 CodeViser TM 와 CVD TM 를이용하여 aesop S5PC100 공동제작보드를기반으로 Android TM 시스템을디버깅하는방법에대해서다룹니다. Android 시스템을빌드및빌드를위한환경구축과, aesop S5PC100 보드에서동작시키는방법에대해서는아래링크의공동제작보드프로젝트포럼을참고하시기바랍니다. http://www.aesop.or.kr/?vid=aesopc100 Android 시스템자체의동작과관련된내용은관련사이트및문서를참고하시기바랍니다. CodeViser를이용한 aesop S5PC100 리눅스디버깅방법은 aesop S5PC100 리눅스디버깅가이드를참고하시기바랍니다. 본문서는 CVD v2.3 을기준으로작성되었습니다. [ 참고자료 ] http://developer.android.com 인사이드안드로이드 ( 위키북스 ) 4
표기방식 다음은본문서에서사용하는표기방식입니다. 진하게본문내용중특별히강조해야할부분을표기할때사용합니다. 예 ) 새로운버전의 CVD를설치하신후에는반드시펌웨어업데이트를수행하시기바랍니다. Courier New 소스코드또는스크립트의내용을표기할때, 파일명이나경로명을표기할때사용합니다. 예 ) void call2(void) { printf("in call2 function\n"); } Courier New Bold Command Line 등과같이사용자가직접어떤값을입력해야하는경우사용합니다. 예 ) SELectBREAK %PROGRAM %HW Italic 참고문서등에대한자료명을표기할때사용합니다. 예 ) 리눅스디버깅가이드 (Linux_Deubgging_Guide.pdf) 문서를참고하시기바랍니다. 텍스트상자주의사항이나참고사항등본문과관련있는추가정보를표시합니다. 예 ) 리눅스 Library Debugging 기능사용시직접 Breakpoint를설정하는것보다다소동작속도가느려질수있습니다. 5
1. Android 플랫폼개요 Android 는운영체제, 미들웨어, 주요어플리케이션을포함하고있는모바일디바이스를위한소프트웨어스택으로서 Android SDK를통해어플리케이션개발에필요한 API와관련도구들을제공합니다. Android 플랫폼은 Java 프로그래밍언어를사용합니다. 1.1. Android 주요기능 Android 의주요기능은다음과같습니다. Application Framework : 컴포넌트들의재사용및대체 Dalvik virtual machine : 모바일디바이스에최적화된 VM, Sun의 VM을사용하지않아라이선스로부터자유로움 Integrated browser : 오픈소스 Webkit 기반의내장웹브라우저 Optimized graphics : Custom 2D 그래픽, OpenGL ES 1.0 기반의 3D 그래픽 SQLite Media support : 오디오, 비디오및다양한이미지포맷지원 GSM Telephony Bluetooth, EDGE, 3G, and WiFi Camera, GPS, compass, and accelerometer Rich development environment : Eclipse 통합개발환경플러그인형태로의에뮬레이터, 디버깅툴, 퍼포먼스프로파일링등다양한개발도구지원 1.2. 안드로이드구조 [ 그림 1-1] 은 Android 플랫폼의주요컴포넌트를보여주는다이어그램입니다. 1.2.1. Applications Android 플랫폼은기본적으로 E-Mail 클라이언트, SMS, 달력, 지도, 웹브라우저, 주소록등의다양한어플리케이션을기본적으로탑재하고있습니다. 모든어플리케이션은 Java 프로그래밍언어로작성되어집니다. 1.2.2. Application Framework 어플리케이션구동을위한다양한서비스및시스템을제공합니다. 6
[ 그림 1-1] Android Architecture 1.2.3. Libraries Android 는다음과같은 C/C++ 라이브러리를제공합니다. System C library Android는임베디드리눅스기반시스템에최적화된 BSD 라이선스의표준 C 라이브러리 (libc) 를제공합니다. EABI로빌드되었으며, 자바의 JNI를통해연결되어야하므로크기는줄이고, 효율은강화한라이브러리로서 BSD 라이선스를적용하여소스코드에대한공개의무가없으며경량 pthread가구현되어있습니다. Media Libraries PacketVideo의 OpenCORE 기반으로서다양한오디오및비디오포맷을플레이하거나레코딩할수있습니다. 이미지, MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 등의포맷을지원합니다. Surface Manager 디스플레이서브시스템을위한접근제어와 2D / 3D 그래픽처리를담당합 7
니다. LibWebCore 오픈소스기반의웹브라우저엔진으로속도가매우빠릅니다. SGL 2D 그래픽엔진라이브러리입니다. 3D Libraries OpenGL ES 1.0 API 기반으로하드웨어 3D 가속기를사용하며, 최적화된 3D 소프트웨어래스터라이저입니다. Free Type 비트맵및벡터폰트처리를담당합니다. SQLite 모든어플리케이션에서사용할수있는강력하고작은관계형데이터베이스 엔진입니다. 1.2.4. Android Runtime Android 는대부분의 Java 프로그래밍언어의핵심라이브러리기능을제공하는핵심 라이브러리를포함하고있습니다. [ 그림 1-2] JNI 인터페이스동작 모든 Android 어플리케이션은고유한프로세스와 Dalvik VM 의인스턴스로동작합니 8
다. Android 는라이선스문제로인해기존 Sun 의 Java 가상머신을사용하지않고 Dalvik 가상머신을사용하는데, 임베디드프로세서상에서 Sun 의가상머신보다높은 성능을보여줍니다. 자바로작성되어진어플리케이션에서 C++ 로작성되어진드라이버라이브러리를호출하기위해서 JNI라는인터페이스를사용합니다. JNI는자바코드에서 C 또는 C++ 라이브러리를호출하거나반대로 C 또는 C++ 로작성된코드에서자바메서드를호출할수있도록해줍니다. 1.2.5. Linux Kernel Android는보안, 메모리관리, 프로세스관리, 네트워크프로토콜스택, 디바이스드라이버와같은핵심시스템서비스를위해리눅스커널 2.6을사용합니다. 커널은하드웨어와소프트웨어사이의추상계층으로도동작합니다. Android에서사용하는커널은순수리눅스커널을안드로이드용으로패치한것입니다. 기존의리눅스커널과는다르게 GLIBC를사용하지않고 EABI와 Binder를사용하는것이특징입니다. 그리고커널기능향상을위해 Alarm, Ashamem( 공유메모리 ), Low memory killer, debugger, logger 등의컴포넌트가추가되었습니다. 1.3. Android Boot-up Sequence Android 시스템의부팅과정은기본적으로리눅스와유사한데, [ 그림 1-4] 는 Android 시스템의부팅과정을보여주고있습니다. 커널이부팅하면서기본적인초기화작업을수행한후, init 프로세스를생성하고, 이후의부팅과정은 init 프로세스가담당하는데, init 프로세스는 init.rc 파일의설정에따라동작합니다. 일반적으로파일시스템마운팅, 디렉토리권한설정, 캐시삭제, 시작프로그램의동작등을수행합니다. 가장먼저, 백그라운드서비스로동작하는데몬프로세스들을실행하고, Zygote를실행하면 Zygote에의해서 Dalvik VM과상위서비스들이실행됩니다. 이후 Runtime을통해서기본라이브러리등이실행됩니다. [ 그림 1-4] 는 Zygote 의실행과정을보여줍니다. 9
[ 그림 1-3] Android 부팅과정 [ 그림 1-4] Zygote 실행과정 10
부팅이완료되고난후의각프로세스들의상태는 [ 그림 1-6] 과같습니다. [ 그림 1-5] 부팅완료후프로세스상태 11
2. 환경설정 2.1. 소스코드준비 Android 시스템의디버깅을위해서는빌드한전체패키지가필요합니다. CVD는 Windows 용으로만제공되기때문에, 전체 Android 패키지를 Windows 시스템으로복사하거나, SAMBA를이용하여접근할수있어야합니다. 일반적으로 VirtualBox TM 와같은가상 PC를이용해서개발환경을구축하고빌드한경우에해당가상머신으로 SAMBA 공유접속을할수있도록설정하면됩니다. 이때가능하다면공유설정은시스템의최상위경로인 root(/) 로설정하시는것이좋습니다. - smb.conf [Ubuntu] comment = Ubuntu 8.10 System read only = no locking = no path = / guest ok = yes browseable = yes 가상머신을사용하지않고별도의리눅스머신에서빌드한경우보안적인이슈등으로인해 root(/) 공유가힘든경우또는 Windows 시스템으로전체소스패키지를복사한경우에는 2.2 스크립트작성절을참고하시기바랍니다. 2.2. 스크립트작성 디버깅의편의를위해서타겟의초기화를수행하고커널의심볼을로딩한후리눅스커널의시작함수인 start_kernel() 함수의시작위치까지만실행한후멈추도록하는스크립트를다음과같이작성해보겠습니다. - aesop_c100_kernel.csf AREA AREA.Clear 12
; 1. System Setting print "Start aesop-c100 Initialization and Connection" DisConnect wait 100.ms OPTION.JTAGCLOCK OPTION.EnReset OPTION.CR OPTION.BigEndian OPTION.TRST OPTION.DACR OPTION.ResetWait OPTION.RegisterInit OPTION.RTCK OPTION.BE OPTION.DevName CPUTYPE 10mhz ON OFF OFF ON ON OFF OFF OFF OFF aesop_s5pc100 CortexA8 MULtiCore.IRPOST 0 MULtiCore.DRPOST 0 MULtiCore.IRPRE 0 MULTiCore.DRPRE 0 MULTiCore.DEBUGACCESSPORT 1 MULTiCore.COREBASE 0x80005000 ;Terminal Setting PROC.TERM.Method PROC.TERM.MODE Serial VT100 ;Serialport Setting PROC.SERialport COM1 115200 8 NONE 1STOP NONE VIEW.TERMinal 13
unload DELeteBreak Connect if isconnect() ( if debug() if debugstate()==0xb print "Target connection is Success" ) else print "Target Connection is Failed" ; 2. Download Kernel Symbol print "Start load vmlinux..." cd..\android-2.6.29-aesop-rtm10 LoadImage vmlinux %keep %multi %symbol %trim 6 SetBREAK start_kernel %hw go wait!isrun() print "vmlinux loading complete..." END 스크립트의내용중커널의경로와 vmlinux 이미지로딩시의옵션은현재환경에따라적절하게수정해주셔야합니다. 커널소스경로커널이있는디렉토리로이동하기위해서 cd 명령어를사용합니다. 절대경 14
로로커널이있는위치를지정하시거나, 현재위치를기준으로상대경로로 지정해줍니다. 현재의위치는스크립트파일이있는위치입니다. 이미지로딩커널소스로이동한후심볼이미지를포함하고있는이미지파일인 vmlinux를로딩합니다. 이미지로딩을위해사용한옵션은다음과같습니다. - %keep : 이미지다운로드후 PC의값을변경하지않습니다. - %symbol : 이미지의심볼만로딩합니다. - %multi : 기존에로딩되어있던심볼을그대로둡니다. - %trim : 이미지내의소스코드경로를지정한단계만큼삭제해줍니다. 리눅스에서빌드된이미지를로딩하여디버깅할때경로가맞지않아소스코드가보이지않을수있습니다. [Config]-[Source Path] 메뉴를이용하여소스코드가있는위치를지정해줄수있지만, 소스코드가위치하는경로가많을경우일일이지정해주기가쉽지않습니다. 소스코드가위치하는최상위디렉토리를지정하고하위디렉토리까지검색하도록설정할수있지만, 리눅스커널처럼같은이름을가진소스코드가먼저검색되는경우엉뚱한소스코드가보일수도있습니다. 정확한소스코드를보기위해서다음과같은방법을사용할수있습니다. 루트 (/) 디렉토리부터 SAMBA 공유앞에서도언급되었듯이리눅스시스템의루트 (/) 디렉토리부터 SAMBA 공유할경우별도의설정을할필요없이정확한소스코드를보실수있습니다. Windows에서경로단계동일하게설정 Windows로전체패키지를복사한경우 Windows에서의경로단계를리눅스에서빌드할당시와동일하게맞추어주는방법입니다. 예를들어빌드한경로가 /home/user/android 였다면 c:\home\user\android 와같이경로명및단계를리눅스와동일하게맞추어주는방법입니다. %trim 옵션사용위의두가지방법을사용할수없는경우이미지를로드할때옵션을사용하여경로를조절해주는방법입니다. 15
- 리눅스빌드경로 : /root/development/kernel/linux-2.6.33 위와같은환경일때커널이원래빌드된경로는 5단계입니다. 실제디렉토리는 4단계이지만 root(/) 디렉토리까지포함해서 5단계로봅니다. 따라서이미지를로드할때 %trim 5 와같이설정해주면이미지내의소스경로중 /root/development/kernel/linux-2.6.33 만큼을제거해주기때문에별도의소스코드경로를지정해주지않아도됩니다. 따라서위와같은환경이라면스크립트를다음과같이수정하시면됩니다. cd d:\linux\kernel\linux-2.6.33 LoadIMAGE vmlinux %keep %symbol %multi %trim 5 전체패키지를 Windows로복사하지않고리눅스시스템경로의중간부터 SAMBA 공유를한경우에도동일하게사용하시면됩니다. 2.3. 스크립트실행 [Program]-[Run Script File] 메뉴에서작성한스크립트파일을선택해서스크립트를실행합니다. 실행결과는다음과같이 Start_Kernel() 함수에서멈추게됩니다. [ 그림 2-1] Start_Kernel() 함수에멈춘모습 스크립트를 User 메뉴에등록해두면편리하게실행할수있습니다. 등록방법은다 16
음과같습니다. (CVD v2.3 신규기능 ) 1) [User]-[Add] 메뉴를실행한후 Title을입력하고, 스크립트파일을선택합니다. Run 항목의체크여부에따라 Open / Run 동작이선택됩니다. [ 그림 2-2] 스크립트정보입력 2) Add 버튼을누른후 User 메뉴에스크립트가추가되었는지확인합니다. 현재예에서는 3번에등록된것을확인할수있습니다. 해당메뉴를선택하면스크립트를바로실행할수있습니다. [ 그림 2-3] User 메뉴에등록된모습 이후의커널디버깅은일반적인리눅스커널디버깅방법과동일합니다. 3. Android 시스템디버깅의각단계는가급적스크립트를실행하여 start_kernel() 함수에서멈춘상태에서수행하시기바랍니다. 17
3. Android 시스템디버깅 3.1. Device Driver 디버깅 대부분의디바이스드라이버는리눅스커널에포함되어있기때문에 vmlinux 이미 지만로딩되어있다면디버깅이가능합니다. 3.1.1. USB 드라이버 1) aesop_c100_kernel.csf 파일을실행시켜커널이미지를로딩한후 [Symbol]- [Symbol by Name]-[Symbol] 을선택해 Symbol Browse View 창을엽니다. [ 그림 3-1] Symbol Browser 실행 2) 심볼검색창에 usb_init 을입력하여 usb_init() 함수를찾은후 H/W breakpoint 를설정합니다. [ 그림 3-2] usb_init() 함수에 breakpoint 설정 18
3) [Run]-[Go] 를실행합니다. 잠시후 usb_init() 함수에멈춥니다. [ 그림 3-3] usb_init() 함수에멈춘모습 3.1.2. Frame Buffer 초기화 1) 동일한방법으로 fb_console_init() 함수에 H/W Breakpoint 를설정합니다. [ 그림 3-4] fb_console_init() 함수에 breakpoint 설정 19
2) [Run]-[Go] 를실행하면, 잠시후 fb_console_init() 함수에멈춥니다. [ 그림 3-5] fb_console_init() 함수에멈춘모습 3.1.3. Audio 드라이버 1) 동일한방법으로 smdk_audio_init() 함수에 H/W Breakpoint 를설정합니다. [ 그림 3-6] smdk_audiio_init() 함수에 breakpoint 설정 2) [Run]-[Go] 를실행하면, 잠시후 smdk_audio_init() 함수에멈춥니다. 20
그림 3-7 smdk_audio_init() 함수에멈춘모습 3.2. init 프로세스디버깅 커널이부팅하면서기본적인초기화를수행한후가장먼저생성하는프로세스인 init 프로세스를디버깅해보겠습니다. 1. Android 플랫폼개요에서살펴보았습니다. 실질적인 Android의부팅은 init프로세스로부터시작된다고보아도됩니다. 리눅스의 start_kernel() 함수에서멈춘상태에서 CVD의리눅스 App 디버깅기능을이용해서 init 프로세스의디버깅을수행해보겠습니다. 1) [Linux]-[App. Debugging] 메뉴를실행하고 App Symbol Path에서 init 프로세스의이미지를선택합니다. init 프로세스의이미지가위치하는경로는다음과같습니다. - android_eclair_aesopc100\out\target\product\smdkc100\symbols [ 그림 3-8] init 프로세스디버깅 21
CVD 의메인메뉴중 Linux 메뉴가없는경우에는 [Config]-[RTOS Customize] 메뉴를 실행후 Linux 를선택해주시기바랍니다. 2) Debug Start를클릭하면 Target이실행하다가 init 프로세스가실행될때 init 프로세스의심볼을로딩하고 main() 함수에멈추어줍니다. [ 그림 3-9] init 프로세스의 main() 함수에멈춘모습 이제부터는 Step by Step 또는원하는위치에 Breakpoint를설정하여 init프로세스의동작에대한디버깅을수행하실수있습니다. [ 그림 3-3] 은 init 프로세스가부팅에필요한디렉토리를생성하고마운트하는과정을보여줍니다. 그림 3-10 디렉토리생성및마운트 22
3.3. Daemon 디버깅 init 프로세스에의해실행되는백그라운드서비스를위한데몬프로세스를디버깅해보도록하겠습니다. 데몬프로세스의 main() 함수부터디버깅하는방법은 init 프로세스디버깅방법과거의동일합니다. 3.3.1. 디버거데몬 (debuggerd) Android 시스템의디버그시스템을시작시키는디버거데몬인 debuggerd 를 main() 함 수부터디버깅해보겠습니다. 1) aesop_c100_kernel.csf를실행하여 start_kernel() 에서멈춘상태에서 [Linux]-[App Debugging] 를실행하고, debuggerd 데몬의이미지를선택합니다. Debuggerd 데몬의이미지가위치하는경로는다음과같습니다. android_eclair_aesopc100\out\target\product\smdkc100\symbols\s ystem\bin [ 그림 3-11] debuggerd 프로세스디버깅 2) Debug Start를클릭하면 Target이실행되다가 debuggerd 프로세스가실행될때 debuggerd의심볼을로딩하고 main() 함수에멈추어줍니다. 이제 main() 함수의시작부터 Step by Step으로디버깅하실수있습니다. Debuggerd가사용하는공유라이브러리에대해서디버깅하시려면 3) 이후의내용을수행하시면됩니다. 23
[ 그림 3-12] debuggerd 의 main() 에멈춘모습 3) [Linux]-[Task List] 메뉴를실행한후 debuggerd 프로세스를선택하고, 팝업메뉴의 [Show Library] 를선택합니다. COMMAND 필드를클릭하면프로세스이름을기준 으로오름차순 / 내림차순으로정렬할수있습니다. [ 그림 3-13] debuggerd 가사용하는라이브러리확인 4) Library 리스트에서 libc.so (EX RD) 를선택하고팝업메뉴 [Load Symbol] 을실행하 여 libc.so 의이미지를로드합니다. libc.so 의이미지가있는경로는다음과 같습니다. 24
android_eclair_aesopc100\out\target\product\smdkc100\symbols\s ystem\bin [ 그림 3-14] libc.so 이미지로드 5) [Symbol]-[Symbol by Name]-[Symbol] (Shift + Alt + Y) 를실행합니다. libc 의 malloc() 함수를검색한후 H/W Breakpoint 를설정합니다. [ 그림 3-15] malloc() 함수에 breakpoint 설정 25
6) [Run]-[Go] 를실행하여 malloc() 함수에멈추는지확인후해당라이브러리를 디버깅하실수있습니다. [ 그림 3-16] malloc() 함수에멈춘모습 3.3.2. 볼륨데몬 (vold) USB 저장장치또는 SD카드등의장치를마운트하고관리하는볼륨데몬을디버깅해보겠습니다. 기본적인디버깅방법은 3.3.2 디버거데몬과동일합니다. 그외의나머지데몬프로세스를디버깅할때도동일한방법으로진행하시면됩니다. 1) aesop_c100_kernel.csf를실행하여 start_kernel() 에서멈춘상태에서 [Linux]-[App Debugging] 를실행하고, vold 데몬의이미지를선택합니다. vold 데몬의이미지가위치하는경로는다음과같습니다. android_eclair_aesopc100\out\target\product\smdkc100\symbols\s ystem\bin [ 그림 3-17] vold 프로세스디버깅 26
2) Debug Start 를클릭하면 Target 이실행되다가 vold 프로세스가실행될때 vold 의 심볼을로딩하고 main() 함수에멈추어줍니다. 이제 main() 함수의시작부터 Step by Step 으로디버깅하실수있습니다. [ 그림 3-18] vold 의 main() 에멈춘모습 그외의 daemon 프로세스도동일한방법으로디버깅하실수있습니다. 3.4. App_process 디버깅 [ 그림 1-3] Android 부팅과정을살펴보면 init프로세스가 daemon 프로세스들을초기화한후 Zygote프로세스를생성하는것을볼수있습니다. Zygote 프로세스는 init 프로세스에의해생성된 app_process에의해서생성됩니다. App_process는 init.rc에기술된내용에따라 Zygote 프로세스를실행합니다. Zygote는안드로이드어플리케이션의로딩시간을단축시키기위한프로세스로서자바로작성되어있어 app_process에서 Zygote를실행시키는부분까지만확인할수있습니다. 1) [Linux]-[App Debugging] 를실행하고, app_process의이미지를선택합니다. app_process 프로세스의이미지가위치하는경로는다음과같습니다. android_eclair_aesopc100\out\target\product\smdkc100\symbols\s ystem\bin 27
[ 그림 3-19] app_process 디버깅 2) Debug Start를클릭하면 Target이실행되다가 app_process 프로세스가실행될때 app_process의심볼을로딩하고 main() 함수에멈추어줍니다. [ 그림 3-20] app_process 의 main() 에멈춘모습 3) 소스코드의 158~159번에걸쳐있는 runtime.start() 함수호출을통해 Zygote 프로세스를실행하는것을확인할수있습니다. 28
[ 그림 3-21] Zygote 프로세스를실행하는부분 3.5. HAL 디버깅 HAL 디버깅을위해서는 libhardware.so 심볼을먼저로딩한후진행을해야합니다. 이를위해서 system_server 프로세스가실행될때까지부팅을진행합니다. HAL 디버깅은다음과같은방법으로진행하실수있습니다. 1) [Linux]-[Show Task List] 를실행합니다. [ 그림 3-22] system_server 프로세스 2) Linux Task List 에서 system_server 프로세스를선택하고팝업메뉴 [Show Library] 를실행해서 system_server 프로세스가사용하는라이브러리리스트를출력시킵니다. 29
[ 그림 3-23] libhardware.so 라이브러리 3) System_server 프로세스의라이브러리중 libhardware.so(ex RD) 의심볼을로딩합니다. [ 그림 3-24] libhardware.so 로딩 4) Symbol browse 창에서 libhardware 라이브러리의함수중 load() 함수를찾아 Breakpoint를설정합니다. Symbol Browse 창우측상단의드롭다운박스를통해특정이미지를선택할수있습니다. 30
[ 그림 3-25] libhardware load() 함수에 Breakpoint 설정 5) [Run]-[Go] 메뉴를실행하여타겟을실행시킨후 Breakpoint를설정한 load() 함수에멈추는지확인합니다. [ 그림 3-26] libhardware 의 load 함수에멈춘모습 6) 소스코드에서동적라이브러리를로드하는 dlopen() 함수호출부분다음라인 31
에 BP 를설정하고타겟을실행시킵니다. [ 그림 3-27] dlopen 함수호출후멈춘모습 7) [Symbol]-[Callstack] 을실행하여 load() 함수의지역변수중 path 를확인합니다. Path 변수를확인하기위해서 format 은 string 으로설정해야합니다. [ 그림 3-28] 현재로드된라이브러리확인 8) [Linux]-[Show Task List] 를실행한후 system_server 프로세스를선택하고팝업메뉴 Show Library를실행하여해당라이브러리의심볼을로딩합니다. 32
[ 그림 3-29] lights.smdkc100.so 라이브러리 9) 로딩한라이브러리의다음함수에 Breakpoint 를설정합니다. - 함수명 : open_lights() [ 그림 3-30] open_lights() 함수에 breakpoint 설정 33
10) [Run]-[Go] 를실행하여타겟을실행시킨후해당함수에멈추는지확인합니다. [ 그림 3-31] open_lights 함수에멈춘모습 3.6. JNI 디버깅 JNI 디버깅도 HAL 디버깅방법과유사하게, Dalvik VM의라이브러리심볼을먼저로딩한후 VM에서로딩하는라이브러리를찾아디버깅해야합니다. 이를위해 system_server 프로세스가실행될때까지부팅을진행합니다. 1) system_server 프로세스가사용하는 library 중 libdvm.so(ex RD) 의심볼을로딩합니다. [ 그림 3-32] libdvm.so 심볼로딩 34
2) 로딩한 libdvm 라이브러리의함수중 dvmloadnativecode() 함수에 Breakpoint 를설정합니다. [ 그림 3-33] dvmloadnativecode() 함수에 breakpoint 설정 3) [Run]-[Go] 를실행하여해당함수에멈추는지확인합니다. [ 그림 3-34] dvmloadnativecode() 함수에멈춘모습 35
4) dvmloadnativecode() 함수에서 dlopen(pathname, RTLD_LAZY); 다음라 인에 Breakpoint 를설정하고타겟을실행합니다. [ 그림 3-35] dlopen() 함수호출이후에멈춘모습 5) 이후 Callstack 창을열어이전함수의 filename 변수를통해현재로드되는라이브러리의이름과경로를확인합니다. [ 그림 3-36] 로드되는라이브러리확인 36
6) Linux Task List 에서 system_server 프로세스가사용하는라이브러리목록중확인 한라이브러리의이미지를로딩합니다. 그림 3-37 libsoundpool.so 라이브러리로드 7) 로드한라이브러리심볼중다음의함수에 Breakpoint를설정하고타겟을실행시켜해당함수에서멈추는지확인합니다. - 함수명 : android::soundpoolthread::messagequeue::read() [ 그림 3-38] SoundPoolThread::MessageQueue::read() 함수에 breakpoint 설정 37
8) [Run]-[Go] 를실행하여타겟을실행시킨후해당함수에멈추는지확인합다. 이 후해당함수를디버깅할수있습니다. [ 그림 3-39] SoundPoolThread::MessageQueue::read() 함수에멈춘모습 위에서살펴본 libsoundpool.so 뿐만아니라다른 Native 함수들도같은방법으 로디버깅하실수있습니다. 38