"Compressed vmlinux 압축 해제 과정 디버깅"의 두 판 사이의 차이

TRACE32
이동: 둘러보기, 검색
(새 문서: <h2><span style="font-size: large;">Introduction</span></h2> <h3><span style="font-size: large;">문서 소개</span></h3> <p>많은 업체에서 open OS인 Linux 를 이용해 제품...)
 
 
4번째 줄: 4번째 줄:
 
<h3>decompressed vmlinux 디버깅</h3>
 
<h3>decompressed vmlinux 디버깅</h3>
 
<p>① Bootloader 에서는 <strong>do_bootm_linux()</strong> 함수에서 kernel 압축 해제 코드로 jump 하도록 되어 있다. <strong>do_bootm_linux</strong><strong>()</strong> 까지 breakpoint 로 진행하여 확인한다.</p>
 
<p>① Bootloader 에서는 <strong>do_bootm_linux()</strong> 함수에서 kernel 압축 해제 코드로 jump 하도록 되어 있다. <strong>do_bootm_linux</strong><strong>()</strong> 까지 breakpoint 로 진행하여 확인한다.</p>
<p><img src="/data/wiki/2015-02-16/1424049610.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049610.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>②&nbsp;<strong>cleanup_before_linux()</strong> 함수에서 cache disable 등을 진행한다.</p>
 
<p>②&nbsp;<strong>cleanup_before_linux()</strong> 함수에서 cache disable 등을 진행한다.</p>
<p><img src="/data/wiki/2015-02-16/1424049619.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049619.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>③&nbsp;<strong>kernel_entry</strong> 로 jump 한다.</p>
 
<p>③&nbsp;<strong>kernel_entry</strong> 로 jump 한다.</p>
<p><img src="/data/wiki/2015-02-16/1424049626.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049626.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>④ compressed vmlinux가 load되는 주소를 확인하여 vmlinux 이미지를 load 한다. load 주소는 <strong>${kernel}\arch\&lt;core architecture&gt;\&lt;project name&gt;\Makefile.boot</strong> 에서 확인 하거나 <strong>boot_jump_linux()</strong> 함수 내의 <strong>kernel_entry</strong> 변수 값으로도 확인이 가능하다.</p>
 
<p>④ compressed vmlinux가 load되는 주소를 확인하여 vmlinux 이미지를 load 한다. load 주소는 <strong>${kernel}\arch\&lt;core architecture&gt;\&lt;project name&gt;\Makefile.boot</strong> 에서 확인 하거나 <strong>boot_jump_linux()</strong> 함수 내의 <strong>kernel_entry</strong> 변수 값으로도 확인이 가능하다.</p>
16번째 줄: 16번째 줄:
 
<p>⑤&nbsp;<strong>decompress_kernel()</strong> 함수에 breakpoint를 걸고 디버깅 할 수 있다.</p>
 
<p>⑤&nbsp;<strong>decompress_kernel()</strong> 함수에 breakpoint를 걸고 디버깅 할 수 있다.</p>
 
<p><strong> </strong></p>
 
<p><strong> </strong></p>
<p><img src="/data/wiki/2015-02-16/1424049636.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049636.jpg" alt="" width="650" /></p>
 
<h3>relocation 과정이 추가 되는 경우</h3>
 
<h3>relocation 과정이 추가 되는 경우</h3>
 
<p>CPU의 boot sequence 에 따라 relocation 과정이 추가될 수 있다.</p>
 
<p>CPU의 boot sequence 에 따라 relocation 과정이 추가될 수 있다.</p>
23번째 줄: 23번째 줄:
 
<p><strong>u-boot relocation </strong><strong>예제</strong></p>
 
<p><strong>u-boot relocation </strong><strong>예제</strong></p>
 
<p>①&nbsp;<strong>do_bootm_linux()</strong> 에 SW breakpoint를 설정한다.</p>
 
<p>①&nbsp;<strong>do_bootm_linux()</strong> 에 SW breakpoint를 설정한다.</p>
<p><img src="/data/wiki/2015-02-16/1424049646.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049646.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>②&nbsp;<strong>do_bootm_linux()</strong> 가 아닌 엉뚱한 위치에 breakpoint가 hit되면, Assembly가 <strong>bkpt #0x0</strong>으로 변경된다.</p>
 
<p>②&nbsp;<strong>do_bootm_linux()</strong> 가 아닌 엉뚱한 위치에 breakpoint가 hit되면, Assembly가 <strong>bkpt #0x0</strong>으로 변경된다.</p>
<p><img src="/data/wiki/2015-02-16/1424049656.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049656.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>③ symbol relocation 계산</p>
 
<p>③ symbol relocation 계산</p>
 
<p>u-boot relocation address = <strong>do_bootm_linux()</strong> hit address - <strong>do_bootm_linux()</strong> symbol address + u-boot entry address</p>
 
<p>u-boot relocation address = <strong>do_bootm_linux()</strong> hit address - <strong>do_bootm_linux()</strong> symbol address + u-boot entry address</p>
 
<p>ex) 0x7ff99000 = 0x7FF9AB10 - 0x43E01B10 + 0x43E00000</p>
 
<p>ex) 0x7ff99000 = 0x7FF9AB10 - 0x43E01B10 + 0x43E00000</p>
<p><img src="/data/wiki/2015-02-16/1424049671.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049671.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>④ symbol relocation 진행</p>
 
<p>④ symbol relocation 진행</p>
41번째 줄: 41번째 줄:
 
<p>(<strong>${kernel}\arch\&lt;core architecture&gt;\&lt;project name&gt;\Makefile.boot</strong>에서 확인 하거나 <strong>boot_jump_linux()</strong> 함수 내의 <strong>kernel_entry</strong> 변수 값으로도 확인이 가능)</p>
 
<p>(<strong>${kernel}\arch\&lt;core architecture&gt;\&lt;project name&gt;\Makefile.boot</strong>에서 확인 하거나 <strong>boot_jump_linux()</strong> 함수 내의 <strong>kernel_entry</strong> 변수 값으로도 확인이 가능)</p>
 
<p><strong>ex) Data.LOAD.ELF *\kernel\arch\arm\boot\compressed\vmlinux 0x40008000 /NOCODE /NOCLEAR</strong></p>
 
<p><strong>ex) Data.LOAD.ELF *\kernel\arch\arm\boot\compressed\vmlinux 0x40008000 /NOCODE /NOCLEAR</strong></p>
<p><img src="/data/wiki/2015-02-16/1424049691.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049691.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>② restart label을 수행한다.</p>
 
<p>② restart label을 수행한다.</p>
<p><img src="/data/wiki/2015-02-16/1424049704.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049704.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>③ vmlinux 코드를 진행하다 보면 restart label을 두 번 수행하게 된다.<br /> Head.s 의 Cache clean 이후 <strong>cpy pc, r0</strong> 명령을 만나면 symbol relocation 을 진행한다.</p>
 
<p>③ vmlinux 코드를 진행하다 보면 restart label을 두 번 수행하게 된다.<br /> Head.s 의 Cache clean 이후 <strong>cpy pc, r0</strong> 명령을 만나면 symbol relocation 을 진행한다.</p>
<p><img src="/data/wiki/2015-02-16/1424049715.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049715.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>④&nbsp;<strong>cpy pc, R0</strong> 명령에서 R0의 값이 0x40741208이고 restart label의 address가 0x400080A8 이므로 해당 address 를 relocation 시킨다.</p>
 
<p>④&nbsp;<strong>cpy pc, R0</strong> 명령에서 R0의 값이 0x40741208이고 restart label의 address가 0x400080A8 이므로 해당 address 를 relocation 시킨다.</p>
53번째 줄: 53번째 줄:
 
<p><strong>&nbsp;</strong></p>
 
<p><strong>&nbsp;</strong></p>
 
<p>⑤ Relocation 된 vmlinux 를 디버깅 할 수 있다</p>
 
<p>⑤ Relocation 된 vmlinux 를 디버깅 할 수 있다</p>
<p><img src="/data/wiki/2015-02-16/1424049726.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049726.jpg" alt="" width="650" /></p>
<p><img src="/data/wiki/2015-02-16/1424049745.jpg" alt="" /></p>
+
<p><img src="/data/wiki/2015-02-16/1424049745.jpg" alt="" width="650" /></p>
 
<p>&nbsp;</p>
 
<p>&nbsp;</p>
 
<p>Kernel 이미지(zImage or uImage)가 제대로 load 되지 않아 발생하는 경우 또는 압축 해제가 제대로 되지 않을 경우 위와 같은 과정을 통해 문제를 해결 할 수 있다.</p>
 
<p>Kernel 이미지(zImage or uImage)가 제대로 load 되지 않아 발생하는 경우 또는 압축 해제가 제대로 되지 않을 경우 위와 같은 과정을 통해 문제를 해결 할 수 있다.</p>

2015년 4월 23일 (목) 15:14 기준 최신판

Introduction

문서 소개

많은 업체에서 open OS인 Linux 를 이용해 제품 개발을 하고 있다. 일반적인 u-boot, kernel, application이 아닌 bootloader에서 kernel 로 넘어가는 과정에 압축 해제가 문제가 있을 경우 해당 부분을 어떻게 디버깅 해야 할지 확인하도록 한다.

decompressed vmlinux 디버깅

① Bootloader 에서는 do_bootm_linux() 함수에서 kernel 압축 해제 코드로 jump 하도록 되어 있다. do_bootm_linux() 까지 breakpoint 로 진행하여 확인한다.

 

② cleanup_before_linux() 함수에서 cache disable 등을 진행한다.

 

③ kernel_entry 로 jump 한다.

 

④ compressed vmlinux가 load되는 주소를 확인하여 vmlinux 이미지를 load 한다. load 주소는 ${kernel}\arch\<core architecture>\<project name>\Makefile.boot 에서 확인 하거나 boot_jump_linux() 함수 내의 kernel_entry 변수 값으로도 확인이 가능하다.

 

⑤ decompress_kernel() 함수에 breakpoint를 걸고 디버깅 할 수 있다.

relocation 과정이 추가 되는 경우

CPU의 boot sequence 에 따라 relocation 과정이 추가될 수 있다.

일반적으로는 bootloader 진행 시에 relocation 과정이 추가된다. do_bootm_linux() 에 on-chip breakpoint가 hit되지 않거나 SW breakpoint 가 hit된 후 assembly code가 bkpt #0x0 으로 변경되는 경우 symbol relocation을 진행해야 한다.

 

u-boot relocation 예제

① do_bootm_linux() 에 SW breakpoint를 설정한다.

 

② do_bootm_linux() 가 아닌 엉뚱한 위치에 breakpoint가 hit되면, Assembly가 bkpt #0x0으로 변경된다.

 

③ symbol relocation 계산

u-boot relocation address = do_bootm_linux() hit address - do_bootm_linux() symbol address + u-boot entry address

ex) 0x7ff99000 = 0x7FF9AB10 - 0x43E01B10 + 0x43E00000

 

④ symbol relocation 진행

-u-boot entry address+u-boot relocation address 에 relocation 하도록 한다.

ex) Data.LOAD.ELF  *\u-boot -0x43e00000+0x7ff99000 /Nocode

 

compress vmlinux 의 경우 relocation 예제

① vmlinux 파일 load 주소 확인 후 symbol load 합니다.

(${kernel}\arch\<core architecture>\<project name>\Makefile.boot에서 확인 하거나 boot_jump_linux() 함수 내의 kernel_entry 변수 값으로도 확인이 가능)

ex) Data.LOAD.ELF *\kernel\arch\arm\boot\compressed\vmlinux 0x40008000 /NOCODE /NOCLEAR

 

② restart label을 수행한다.

 

③ vmlinux 코드를 진행하다 보면 restart label을 두 번 수행하게 된다.
Head.s 의 Cache clean 이후 cpy pc, r0 명령을 만나면 symbol relocation 을 진행한다.

 

④ cpy pc, R0 명령에서 R0의 값이 0x40741208이고 restart label의 address가 0x400080A8 이므로 해당 address 를 relocation 시킨다.

Y.Reloc.Shift 0x40741208-0x400080A8

 

⑤ Relocation 된 vmlinux 를 디버깅 할 수 있다

 

Kernel 이미지(zImage or uImage)가 제대로 load 되지 않아 발생하는 경우 또는 압축 해제가 제대로 되지 않을 경우 위와 같은 과정을 통해 문제를 해결 할 수 있다.