"Compressed vmlinux 압축 해제 과정 디버깅"의 두 판 사이의 차이
(새 문서: <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> </p> | <p> </p> | ||
<p>② <strong>cleanup_before_linux()</strong> 함수에서 cache disable 등을 진행한다.</p> | <p>② <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> </p> | <p> </p> | ||
<p>③ <strong>kernel_entry</strong> 로 jump 한다.</p> | <p>③ <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> </p> | <p> </p> | ||
<p>④ compressed vmlinux가 load되는 주소를 확인하여 vmlinux 이미지를 load 한다. load 주소는 <strong>${kernel}\arch\<core architecture>\<project name>\Makefile.boot</strong> 에서 확인 하거나 <strong>boot_jump_linux()</strong> 함수 내의 <strong>kernel_entry</strong> 변수 값으로도 확인이 가능하다.</p> | <p>④ compressed vmlinux가 load되는 주소를 확인하여 vmlinux 이미지를 load 한다. load 주소는 <strong>${kernel}\arch\<core architecture>\<project name>\Makefile.boot</strong> 에서 확인 하거나 <strong>boot_jump_linux()</strong> 함수 내의 <strong>kernel_entry</strong> 변수 값으로도 확인이 가능하다.</p> | ||
16번째 줄: | 16번째 줄: | ||
<p>⑤ <strong>decompress_kernel()</strong> 함수에 breakpoint를 걸고 디버깅 할 수 있다.</p> | <p>⑤ <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>① <strong>do_bootm_linux()</strong> 에 SW breakpoint를 설정한다.</p> | <p>① <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> </p> | <p> </p> | ||
<p>② <strong>do_bootm_linux()</strong> 가 아닌 엉뚱한 위치에 breakpoint가 hit되면, Assembly가 <strong>bkpt #0x0</strong>으로 변경된다.</p> | <p>② <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> </p> | <p> </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> </p> | <p> </p> | ||
<p>④ symbol relocation 진행</p> | <p>④ symbol relocation 진행</p> | ||
41번째 줄: | 41번째 줄: | ||
<p>(<strong>${kernel}\arch\<core architecture>\<project name>\Makefile.boot</strong>에서 확인 하거나 <strong>boot_jump_linux()</strong> 함수 내의 <strong>kernel_entry</strong> 변수 값으로도 확인이 가능)</p> | <p>(<strong>${kernel}\arch\<core architecture>\<project name>\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> </p> | <p> </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> </p> | <p> </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> </p> | <p> </p> | ||
<p>④ <strong>cpy pc, R0</strong> 명령에서 R0의 값이 0x40741208이고 restart label의 address가 0x400080A8 이므로 해당 address 를 relocation 시킨다.</p> | <p>④ <strong>cpy pc, R0</strong> 명령에서 R0의 값이 0x40741208이고 restart label의 address가 0x400080A8 이므로 해당 address 를 relocation 시킨다.</p> | ||
53번째 줄: | 53번째 줄: | ||
<p><strong> </strong></p> | <p><strong> </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> </p> | <p> </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 되지 않아 발생하는 경우 또는 압축 해제가 제대로 되지 않을 경우 위와 같은 과정을 통해 문제를 해결 할 수 있다.