SlideShare a Scribd company logo
1 of 49
:restart
linux/arch/arm/boot/compressed/head.S
Jaewon Choi
jwchoi.do@gmail.com
Background
• restart label
• 커널 압축 해제를 위한 준비 작업
• 현재 실행 중인 Image(head.o + misc.o + piggy.gz)와 압축 해제할 공
간이 겹치는지 확인
• 겹친다면 relocate 작업 후 restart label 다시 실행
Assumption
• 커널 시작 위치는 0x8000 번지
• 압축 풀 위치도 0x8000 번지
• bcm_2709의 경우 arch/arm/mach-bcm2709에 아래와 같이 정의 함
• zreladdr-y := 0x00008000
• 아래 코드는 분석에서 제외
• #define에 포함되지 않는 코드
• #ifndef CONFIG_ZBOOT_ROM (not defined)
• DTB
• #ifdef CONFIG_ARM_APPENDED_DTB
• Virtualization Extension
• #define CONFIG_ARM_VIRT_EXT
Notation
• Memory address는 위쪽 방향으로 증가
• Memory layout 왼쪽은 address
• Memory layout 오른쪽은 label or register
• 현재 실행 하는 line은 붉은색으로 표기
Initial state
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
# 1
restart: adr r0, LC0
ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
ldr sp, [r0, #28]
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
# 1
restart: adr r0, LC0
ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
ldr sp, [r0, #28]
LC0의 pc 상대 주소를 r0에 저장
즉, 0x8000+LC0 label의 위치
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
LC0(r0)
# 1
restart: adr r0, LC0
ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
ldr sp, [r0, #28]
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
r0(LC0)의 주소를 시작으로 차례로
R1, r2, r3, r6, r10, r11, r12에 저장
LC0(r0)
# 1
restart: adr r0, LC0
ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
ldr sp, [r0, #28]
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
r0(LC0)+28번 위치의 값(user_stack_end)을 sp에 저장
LC0(r0)
# 2
sub r0, r0, r1 @ calculate the delta offset
add r6, r6, r0 @ _edata
add r10, r10, r0 @ inflated kernel size location
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
LC0(r0)
# 2
sub r0, r0, r1 @ calculate the delta offset
add r6, r6, r0 @ _edata
add r10, r10, r0 @ inflated kernel size location
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
실제 메모리에 올라와 있는 LC0(r0)와
링커스크립트에 의해 배치된 LC0(r1) label 위치의 offset 계산
LC0(r0)
# 2
sub r0, r0, r1 @ calculate the delta offset
add r6, r6, r0 @ _edata
add r10, r10, r0 @ inflated kernel size location
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
LC0(r0)
_edata(r6)
_edata에 offset 추가
vmlinux_lds.S를 참고하면 _edata는 piggydata+padding 이후에 배치
# 2
sub r0, r0, r1 @ calculate the delta offset
add r6, r6, r0 @ _edata
add r10, r10, r0 @ inflated kernel size location
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
LC0(r0)
압축하기 전의 원본 커널 Image의 크기가 저장된 위치(r10)에
offset 추가
_edata(r6)
r10
(piggy.gz
의 마지막
4bytes)
참고 : gzip으로 압축할 경우 압축 하기 전의 데이터 크기가 마지막 4bytes에
little-endian 방식으로 저장됨
https://tools.ietf.org/html/rfc1952
# 3
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
LC0(r0)
_edata(r6)
r10
(piggy.gz
의 마지막
4bytes)
ldrb r9, [r10, #0]
ldrb lr, [r10, #1]
orr r9, r9, lr, lsl #8
ldrb lr, [r10, #2]
ldrb r10, [r10, #3]
orr r9, r9, lr, lsl #16
orr r9, r9, r10, lsl #24
# 3
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
LC0(r0)
_edata(r6)
r10
(piggy.gz
의 마지막
4bytes)
Little-endian으로 표현되어 있는 piggy.gz의 압축 하기 이전 크기(r10)를
이후 계산에 사용하기 위해 big-endian으로 변환해서 r9에 저장
ldrb r9, [r10, #0]
ldrb lr, [r10, #1]
orr r9, r9, lr, lsl #8
ldrb lr, [r10, #2]
ldrb r10, [r10, #3]
orr r9, r9, lr, lsl #16
orr r9, r9, r10, lsl #24
r9 = decompressed kernel size
# 4
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
LC0(r0)
_edata(r6)
r10
(piggy.gz
의 마지막
4bytes)
add sp, sp, r0
add r10, sp, #0x10000
r9 = decompressed kernel size
# 4
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
r10
(piggy.gz
의 마지막
4bytes)
add sp, sp, r0
add r10, sp, #0x10000
sp(user_stack_end)에 offset 추가
vmlinux_lds.S를 참고하면 stack 영역은 piggydata 이후에 배치 됨
user_stack(4k)은 head.S 맨 아래 stack section에 있음
r9 = decompressed kernel size
# 4
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add sp, sp, r0
add r10, sp, #0x10000
sp 이후 64k를 heap을 위한 공간으로 확보
r10
64k
r9 = decompressed kernel size
# 5
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
r10
64k
r9 = decompressed kernel size
# 5
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
r10
64k
r10 위치 위에 추가로 16k 공간 확보
16k
r9 = decompressed kernel size
# 5
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
r10
64k
압축을 풀 위치(r4(0x8000))와 r10 비교
r4가 r10보다 크거나 같으면(hs) wont_overwrite로 branch
즉, 현재 메모리에 있는 piggy+stack+heap 영역 끝보다
압축 풀 위치가 더 높은 곳에 있으면 압축 해제하면서 겹치지 않음
(wont_overwrite)
하지만, r4가 더 낮은 주소에 있으므로 압축 풀면서 현재 메모리를
overwrite 할 가능성이 있음
16k
r9 = decompressed kernel size
# 5
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
64k
압축을 풀 위치(r4(0x8000))에 압축 해제한 커널 크기를 추가해
서 r10에 저장
즉, 압축 해제 했을 때의 메모리 주소 upper boundary 계산
16k
r9 = decompressed kernel size
r9
r10
(0x8000에서
압축 풀었을
경우 차지하는
공간)
# 5
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
64k
wont_overwrite label의 pc 상대 주소를 r9에 저장
head.o의 시작부터가 아닌 wont_overwrite의 위치로 이후에 비
교하는 이유는 현재까지 사용한 코드는 겹쳐도 상관없기 때문
16k
r9 = decompressed kernel size
r9
(:wont_overwrite)
r10
(0x8000에서
압축 풀었을
경우 차지하는
공간)
# 5
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #16384
cmp r4, r10
bhs wont_overwrite
add r10, r4, r9
adr r9, wont_overwrite
cmp r10, r9
bls wont_overwrite
64k
압축 해제한 메모리 상한(r10)과 겹쳐도 상관없는 메모리(r9) 비교
즉, 압축을 해제하더라도 현재 실행중인 코드가 메모리 위쪽에 있어
서 겹치지 않는지 확인
하지만, r10이 위에 있으므로 overwrite 발생하기에 branch 하지 않음
16k
r9
(:wont_overwrite)
r10
(0x8000에서
압축 풀었을
경우 차지하는
공간)
# 6
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #((reloc_code_end - restart + 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
64k
16k
r9
(:wont_overwrite)
r10
(0x8000에서
압축 풀었을
경우 차지하는
공간)
# 6
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #((reloc_code_end - restart + 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
64k
16k
r9
(:wont_overwrite)
0x8000에서
압축 풀었을
경우 차지하는
공간
r10에 256 bytes align 시킨 restart~reloc_code_end 크기만큼 추가
이후, r10을 다시 256 bytes align
r10
256 byte aligned
restart~reloc_code_end
# 6
0x8000
head.o
piggy.gz
misc.o
r5(:restart)
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #((reloc_code_end - restart + 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
64k
16k
r9
(:wont_overwrite)
0x8000에서
압축 풀었을
경우 차지하는
공간
r5에 restart label의 pc 상대 주소 저장
r10
256 byte aligned
restart~reloc_code_end
# 6
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
add r10, r10, #((reloc_code_end - restart + 256) & ~255)
bic r10, r10, #255
adr r5, restart
bic r5, r5, #31
64k
16k
r9
(:wont_overwrite)
0x8000에서
압축 풀었을
경우 차지하는
공간
r5의 하위 31비트 clear
즉, 32 bytes align
r5는 실제 restart label보다 조금 아래쪽일 수 있다. (최대 31 bytes)
r10
256 byte aligned
restart~reloc_code_end
# 7
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
sub r9, r6, r5 @ size to copy
add r9, r9, #31 @ rounded up to a multiple
bic r9, r9, #31 @ ... of 32 bytes
add r6, r9, r5
add r9, r9, r10
64k
16k
r9
(:wont_overwrite)
0x8000에서
압축 풀었을
경우 차지하는
공간
r10
256 byte aligned
restart~reloc_code_end
# 7
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
sub r9, r6, r5 @ size to copy
add r9, r9, #31 @ rounded up to a multiple
bic r9, r9, #31 @ ... of 32 bytes
add r6, r9, r5
add r9, r9, r10
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r10
256 byte aligned
restart~reloc_code_end
재배치할 크기 계산
restart label부터 _edata(piggydata+padding)까지 재 배치
그 위에 있는 4k, 64k 16k의 stack, heap은 재배치후 다시 확보 하면 됨
r9
r9 = size to copy (재배치할 영역 크기)
# 7
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata(r6)
sub r9, r6, r5 @ size to copy
add r9, r9, #31 @ rounded up to a multiple
bic r9, r9, #31 @ ... Of 32 bytes
add r6, r9, r5
add r9, r9, r10
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r10
256 byte aligned
restart~reloc_code_end
재배치할 크기(r9)를 32의 배수가 되도록 올림(rounded up)
조금 더(최대 31 bytes) copy 한다고 해서 문제 될 건 없음
r9
r9 = size to copy (재배치할 영역 크기)
# 7
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
sub r9, r6, r5 @ size to copy
add r9, r9, #31 @ rounded up to a multiple
bic r9, r9, #31 @ ... Of 32 bytes
add r6, r9, r5
add r9, r9, r10
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r10
256 byte aligned
restart~reloc_code_end
restart label부터 재배치할 영역 크기만큼 더한 값을 r6에 저장
r6은 앞에서 32 bytes 반올림 했기 때문에 _edata보다 약간 위가 될 수 있음
r6은 이후 asm memcopy 연산에서 src 주소로 사용
r9
r9 = size to copy (재배치할 영역 크기)
r6
# 7
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
sub r9, r6, r5 @ size to copy
add r9, r9, #31 @ rounded up to a multiple
bic r9, r9, #31 @ ... Of 32 bytes
add r6, r9, r5
add r9, r9, r10
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
256 byte aligned
restart~reloc_code_end
r10에 재배치할 영역 크기(r9)만큼 더해서 r9에 저장
r9는 이후 asm memcopy 연산에서 dst 주소로 사용
r9
r9 = size to copy (재배치할 영역 크기)
r6
r9
r9
참고 : Memory layout에서 r9가 가리키는 재배치 공간(r9)과
r6가 가리키는 재배치 공간(r9)은 동일한 크기!
r10
# 8
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
# 8
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
1: ldmdb r6!, {r0 - r3, r10 - r12, lr}
cmp r6, r5
stmdb r9!, {r0 - r3, r10 - r12, lr}
bhi 1b
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
r6(src)를 시작으로 주소를 감소 시키면서 4byte씩 32bytes를 읽어서
r0-r3, r10-r12, lr에 저장
# 8
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
1: ldmdb r6!, {r0 – r3, r10 – r12, lr}
cmp r6, r5
stmdb r9!, {r0 – r3, r10 – r12, lr}
bhi 1b
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
r6와 r5를 비교해서 r6 > r5 인지 (hi) 검사
# 8
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
1: ldmdb r6!, {r0 – r3, r10 – r12, lr}
cmp r6, r5
stmdb r9!, {r0 – r3, r10 – r12, lr}
bhi 1b
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
r9(dst)를 시작으로 주소를 감소 시키면서 r0-r3, r10-r12, lr 에 있는 값
을 4byte씩 32bytes를 저장
# 8
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
1: ldmdb r6!, {r0 – r3, r10 – r12, lr}
cmp r6, r5
stmdb r9!, {r0 – r3, r10 – r12, lr}
bhi 1b
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
앞의 비교연산(cmp)에서 r6가 더 크기 때문에 (hi) 1b로 branch
이 과정을 r6가 r5보다 작아질 때 까지 반복
즉, asm의 memcopy로 재배치 하는 코드
# 8
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
1: ldmdb r6!, {r0 – r3, r10 – r12, lr}
cmp r6, r5
stmdb r9!, {r0 – r3, r10 – r12, lr}
bhi 1b
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
head.o(restart label 부터 시작), misc.o, piggy.gz를 모두 재배치 완료
하면 branch 종료
head.o, misc.o, piggy.gz
# 9
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
sub r6, r9, r6
add sp, sp, r6
bl cache_clean_flush
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
head.o, misc.o, piggy.gz
# 9
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)4k
LC0(r0)
_edata
sub r6, r9, r6
add sp, sp, r6
bl cache_clean_flush
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
head.o, misc.o, piggy.gz
재배치 전/후 사이의 offset 계산해서 r6에 저장
r6 = 재배치 전/후 사이의 offset
r6
# 9
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)
4k
LC0(r0)
_edata
sub r6, r9, r6
add sp, sp, r6
bl cache_clean_flush
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
head.o, misc.o, piggy.gz
현재 sp에 재배치 offset을 추가해서 sp 재조정
r6 = 재배치 전/후 사이의 offset
4k stack area
# 9
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)
4k
LC0(r0)
_edata
sub r6, r9, r6
add sp, sp, r6
bl cache_clean_flush
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
head.o, misc.o, piggy.gz
재배치한 곳에서 코드를 다시 수행 하기 위해 cache flush
r6 = 재배치 전/후 사이의 offset
4k stack area
# 10
0x8000
head.o
piggy.gz
misc.o
r5 ≒ :restart
:reloc_code_end
16k page table
user_stack_end
(sp)
4k
LC0(r0)
_edata
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
head.o, misc.o, piggy.gz
r6 = 재배치 전/후 사이의 offset
4k stack area
# 10
0x8000
head.o
piggy.gz
misc.o
r0(:restart)
:reloc_code_end
16k page table
user_stack_end
(sp)
4k
_edata
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
64k
16k
:wont_overwrite
0x8000에서
압축 풀었을
경우 차지하는
공간
r6
r9
r10
head.o, misc.o, piggy.gz
r6 = 재배치 전/후 사이의 offset
4k stack area
참고 : BSYM macro는 badr macro로 대체 되었음
e.g. badr r0, restart
https://github.com/torvalds/linux/commit/14327c662822e5e874cb971a716
2067519300ca8
restart label의 pc 상대 주소를 r0에 저장
# 10
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)
4k
_edata
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
64k
16k
:wont_overwrite
r6
r9
r10
head.o, misc.o, piggy.gz
r6 = 재배치 전/후 사이의 offset
4k stack area
r0에 재배치 offset을 추가
즉, 재배치 한 위치의 restart label이 있는 위치를 r0에 저장
r0
(재배치된
restart
label이
있는 위치)
# 10
0x8000
head.o
piggy.gz
misc.o
:restart
:reloc_code_end
16k page table
user_stack_end
(sp)
4k
_edata
adr r0, BSYM(restart)
add r0, r0, r6
mov pc, r0
64k
16k
:wont_overwrite
r6
r9
r10
head.o, misc.o, piggy.gz
r6 = 재배치 전/후 사이의 offset
4k stack area
pc를 r0로 설정
즉, 재배치된 restart label이 있는곳 부터 다시 코드를 실행
결과적으로 stack, heap을 다시 확보하고 wont_overwrite label로
branch하여 이후 코드(압축해제)를 실행
r0
(재배치된
restart
label이
있는 위치)
References
• https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/head.S
• https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/vmlinux.lds.
S
• https://github.com/torvalds/linux/commit/14327c662822e5e874cb971a7162067519300
ca8
• https://tools.ietf.org/html/rfc1952
• http://www.onicos.com/staff/iz/formats/gzip.html
Done !!

More Related Content

Recently uploaded

데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법JMP Korea
 
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP Korea
 
JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP Korea
 
공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화JMP Korea
 
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석JMP Korea
 
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP Korea
 
JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP Korea
 
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?Jay Park
 

Recently uploaded (8)

데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법
 
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
 
JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례
 
공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화
 
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
 
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
 
JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!
 
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
 

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Linux kernel head.S restart label

  • 2. Background • restart label • 커널 압축 해제를 위한 준비 작업 • 현재 실행 중인 Image(head.o + misc.o + piggy.gz)와 압축 해제할 공 간이 겹치는지 확인 • 겹친다면 relocate 작업 후 restart label 다시 실행
  • 3. Assumption • 커널 시작 위치는 0x8000 번지 • 압축 풀 위치도 0x8000 번지 • bcm_2709의 경우 arch/arm/mach-bcm2709에 아래와 같이 정의 함 • zreladdr-y := 0x00008000 • 아래 코드는 분석에서 제외 • #define에 포함되지 않는 코드 • #ifndef CONFIG_ZBOOT_ROM (not defined) • DTB • #ifdef CONFIG_ARM_APPENDED_DTB • Virtualization Extension • #define CONFIG_ARM_VIRT_EXT
  • 4. Notation • Memory address는 위쪽 방향으로 증가 • Memory layout 왼쪽은 address • Memory layout 오른쪽은 label or register • 현재 실행 하는 line은 붉은색으로 표기
  • 6. # 1 restart: adr r0, LC0 ldmia r0, {r1, r2, r3, r6, r10, r11, r12} ldr sp, [r0, #28] 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table
  • 7. # 1 restart: adr r0, LC0 ldmia r0, {r1, r2, r3, r6, r10, r11, r12} ldr sp, [r0, #28] LC0의 pc 상대 주소를 r0에 저장 즉, 0x8000+LC0 label의 위치 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table LC0(r0)
  • 8. # 1 restart: adr r0, LC0 ldmia r0, {r1, r2, r3, r6, r10, r11, r12} ldr sp, [r0, #28] 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table r0(LC0)의 주소를 시작으로 차례로 R1, r2, r3, r6, r10, r11, r12에 저장 LC0(r0)
  • 9. # 1 restart: adr r0, LC0 ldmia r0, {r1, r2, r3, r6, r10, r11, r12} ldr sp, [r0, #28] 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table r0(LC0)+28번 위치의 값(user_stack_end)을 sp에 저장 LC0(r0)
  • 10. # 2 sub r0, r0, r1 @ calculate the delta offset add r6, r6, r0 @ _edata add r10, r10, r0 @ inflated kernel size location 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table LC0(r0)
  • 11. # 2 sub r0, r0, r1 @ calculate the delta offset add r6, r6, r0 @ _edata add r10, r10, r0 @ inflated kernel size location 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table 실제 메모리에 올라와 있는 LC0(r0)와 링커스크립트에 의해 배치된 LC0(r1) label 위치의 offset 계산 LC0(r0)
  • 12. # 2 sub r0, r0, r1 @ calculate the delta offset add r6, r6, r0 @ _edata add r10, r10, r0 @ inflated kernel size location 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table LC0(r0) _edata(r6) _edata에 offset 추가 vmlinux_lds.S를 참고하면 _edata는 piggydata+padding 이후에 배치
  • 13. # 2 sub r0, r0, r1 @ calculate the delta offset add r6, r6, r0 @ _edata add r10, r10, r0 @ inflated kernel size location 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table LC0(r0) 압축하기 전의 원본 커널 Image의 크기가 저장된 위치(r10)에 offset 추가 _edata(r6) r10 (piggy.gz 의 마지막 4bytes) 참고 : gzip으로 압축할 경우 압축 하기 전의 데이터 크기가 마지막 4bytes에 little-endian 방식으로 저장됨 https://tools.ietf.org/html/rfc1952
  • 14. # 3 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table LC0(r0) _edata(r6) r10 (piggy.gz 의 마지막 4bytes) ldrb r9, [r10, #0] ldrb lr, [r10, #1] orr r9, r9, lr, lsl #8 ldrb lr, [r10, #2] ldrb r10, [r10, #3] orr r9, r9, lr, lsl #16 orr r9, r9, r10, lsl #24
  • 15. # 3 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table LC0(r0) _edata(r6) r10 (piggy.gz 의 마지막 4bytes) Little-endian으로 표현되어 있는 piggy.gz의 압축 하기 이전 크기(r10)를 이후 계산에 사용하기 위해 big-endian으로 변환해서 r9에 저장 ldrb r9, [r10, #0] ldrb lr, [r10, #1] orr r9, r9, lr, lsl #8 ldrb lr, [r10, #2] ldrb r10, [r10, #3] orr r9, r9, lr, lsl #16 orr r9, r9, r10, lsl #24 r9 = decompressed kernel size
  • 16. # 4 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table LC0(r0) _edata(r6) r10 (piggy.gz 의 마지막 4bytes) add sp, sp, r0 add r10, sp, #0x10000 r9 = decompressed kernel size
  • 17. # 4 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) r10 (piggy.gz 의 마지막 4bytes) add sp, sp, r0 add r10, sp, #0x10000 sp(user_stack_end)에 offset 추가 vmlinux_lds.S를 참고하면 stack 영역은 piggydata 이후에 배치 됨 user_stack(4k)은 head.S 맨 아래 stack section에 있음 r9 = decompressed kernel size
  • 18. # 4 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add sp, sp, r0 add r10, sp, #0x10000 sp 이후 64k를 heap을 위한 공간으로 확보 r10 64k r9 = decompressed kernel size
  • 19. # 5 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite r10 64k r9 = decompressed kernel size
  • 20. # 5 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite r10 64k r10 위치 위에 추가로 16k 공간 확보 16k r9 = decompressed kernel size
  • 21. # 5 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite r10 64k 압축을 풀 위치(r4(0x8000))와 r10 비교 r4가 r10보다 크거나 같으면(hs) wont_overwrite로 branch 즉, 현재 메모리에 있는 piggy+stack+heap 영역 끝보다 압축 풀 위치가 더 높은 곳에 있으면 압축 해제하면서 겹치지 않음 (wont_overwrite) 하지만, r4가 더 낮은 주소에 있으므로 압축 풀면서 현재 메모리를 overwrite 할 가능성이 있음 16k r9 = decompressed kernel size
  • 22. # 5 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite 64k 압축을 풀 위치(r4(0x8000))에 압축 해제한 커널 크기를 추가해 서 r10에 저장 즉, 압축 해제 했을 때의 메모리 주소 upper boundary 계산 16k r9 = decompressed kernel size r9 r10 (0x8000에서 압축 풀었을 경우 차지하는 공간)
  • 23. # 5 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite 64k wont_overwrite label의 pc 상대 주소를 r9에 저장 head.o의 시작부터가 아닌 wont_overwrite의 위치로 이후에 비 교하는 이유는 현재까지 사용한 코드는 겹쳐도 상관없기 때문 16k r9 = decompressed kernel size r9 (:wont_overwrite) r10 (0x8000에서 압축 풀었을 경우 차지하는 공간)
  • 24. # 5 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 adr r9, wont_overwrite cmp r10, r9 bls wont_overwrite 64k 압축 해제한 메모리 상한(r10)과 겹쳐도 상관없는 메모리(r9) 비교 즉, 압축을 해제하더라도 현재 실행중인 코드가 메모리 위쪽에 있어 서 겹치지 않는지 확인 하지만, r10이 위에 있으므로 overwrite 발생하기에 branch 하지 않음 16k r9 (:wont_overwrite) r10 (0x8000에서 압축 풀었을 경우 차지하는 공간)
  • 25. # 6 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 64k 16k r9 (:wont_overwrite) r10 (0x8000에서 압축 풀었을 경우 차지하는 공간)
  • 26. # 6 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 64k 16k r9 (:wont_overwrite) 0x8000에서 압축 풀었을 경우 차지하는 공간 r10에 256 bytes align 시킨 restart~reloc_code_end 크기만큼 추가 이후, r10을 다시 256 bytes align r10 256 byte aligned restart~reloc_code_end
  • 27. # 6 0x8000 head.o piggy.gz misc.o r5(:restart) :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 64k 16k r9 (:wont_overwrite) 0x8000에서 압축 풀었을 경우 차지하는 공간 r5에 restart label의 pc 상대 주소 저장 r10 256 byte aligned restart~reloc_code_end
  • 28. # 6 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 adr r5, restart bic r5, r5, #31 64k 16k r9 (:wont_overwrite) 0x8000에서 압축 풀었을 경우 차지하는 공간 r5의 하위 31비트 clear 즉, 32 bytes align r5는 실제 restart label보다 조금 아래쪽일 수 있다. (최대 31 bytes) r10 256 byte aligned restart~reloc_code_end
  • 29. # 7 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) sub r9, r6, r5 @ size to copy add r9, r9, #31 @ rounded up to a multiple bic r9, r9, #31 @ ... of 32 bytes add r6, r9, r5 add r9, r9, r10 64k 16k r9 (:wont_overwrite) 0x8000에서 압축 풀었을 경우 차지하는 공간 r10 256 byte aligned restart~reloc_code_end
  • 30. # 7 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) sub r9, r6, r5 @ size to copy add r9, r9, #31 @ rounded up to a multiple bic r9, r9, #31 @ ... of 32 bytes add r6, r9, r5 add r9, r9, r10 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r10 256 byte aligned restart~reloc_code_end 재배치할 크기 계산 restart label부터 _edata(piggydata+padding)까지 재 배치 그 위에 있는 4k, 64k 16k의 stack, heap은 재배치후 다시 확보 하면 됨 r9 r9 = size to copy (재배치할 영역 크기)
  • 31. # 7 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata(r6) sub r9, r6, r5 @ size to copy add r9, r9, #31 @ rounded up to a multiple bic r9, r9, #31 @ ... Of 32 bytes add r6, r9, r5 add r9, r9, r10 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r10 256 byte aligned restart~reloc_code_end 재배치할 크기(r9)를 32의 배수가 되도록 올림(rounded up) 조금 더(최대 31 bytes) copy 한다고 해서 문제 될 건 없음 r9 r9 = size to copy (재배치할 영역 크기)
  • 32. # 7 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata sub r9, r6, r5 @ size to copy add r9, r9, #31 @ rounded up to a multiple bic r9, r9, #31 @ ... Of 32 bytes add r6, r9, r5 add r9, r9, r10 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r10 256 byte aligned restart~reloc_code_end restart label부터 재배치할 영역 크기만큼 더한 값을 r6에 저장 r6은 앞에서 32 bytes 반올림 했기 때문에 _edata보다 약간 위가 될 수 있음 r6은 이후 asm memcopy 연산에서 src 주소로 사용 r9 r9 = size to copy (재배치할 영역 크기) r6
  • 33. # 7 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata sub r9, r6, r5 @ size to copy add r9, r9, #31 @ rounded up to a multiple bic r9, r9, #31 @ ... Of 32 bytes add r6, r9, r5 add r9, r9, r10 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 256 byte aligned restart~reloc_code_end r10에 재배치할 영역 크기(r9)만큼 더해서 r9에 저장 r9는 이후 asm memcopy 연산에서 dst 주소로 사용 r9 r9 = size to copy (재배치할 영역 크기) r6 r9 r9 참고 : Memory layout에서 r9가 가리키는 재배치 공간(r9)과 r6가 가리키는 재배치 공간(r9)은 동일한 크기! r10
  • 34. # 8 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10
  • 35. # 8 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata 1: ldmdb r6!, {r0 - r3, r10 - r12, lr} cmp r6, r5 stmdb r9!, {r0 - r3, r10 - r12, lr} bhi 1b 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 r6(src)를 시작으로 주소를 감소 시키면서 4byte씩 32bytes를 읽어서 r0-r3, r10-r12, lr에 저장
  • 36. # 8 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata 1: ldmdb r6!, {r0 – r3, r10 – r12, lr} cmp r6, r5 stmdb r9!, {r0 – r3, r10 – r12, lr} bhi 1b 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 r6와 r5를 비교해서 r6 > r5 인지 (hi) 검사
  • 37. # 8 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata 1: ldmdb r6!, {r0 – r3, r10 – r12, lr} cmp r6, r5 stmdb r9!, {r0 – r3, r10 – r12, lr} bhi 1b 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 r9(dst)를 시작으로 주소를 감소 시키면서 r0-r3, r10-r12, lr 에 있는 값 을 4byte씩 32bytes를 저장
  • 38. # 8 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata 1: ldmdb r6!, {r0 – r3, r10 – r12, lr} cmp r6, r5 stmdb r9!, {r0 – r3, r10 – r12, lr} bhi 1b 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 앞의 비교연산(cmp)에서 r6가 더 크기 때문에 (hi) 1b로 branch 이 과정을 r6가 r5보다 작아질 때 까지 반복 즉, asm의 memcopy로 재배치 하는 코드
  • 39. # 8 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata 1: ldmdb r6!, {r0 – r3, r10 – r12, lr} cmp r6, r5 stmdb r9!, {r0 – r3, r10 – r12, lr} bhi 1b 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 head.o(restart label 부터 시작), misc.o, piggy.gz를 모두 재배치 완료 하면 branch 종료 head.o, misc.o, piggy.gz
  • 40. # 9 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata sub r6, r9, r6 add sp, sp, r6 bl cache_clean_flush 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 head.o, misc.o, piggy.gz
  • 41. # 9 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp)4k LC0(r0) _edata sub r6, r9, r6 add sp, sp, r6 bl cache_clean_flush 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 head.o, misc.o, piggy.gz 재배치 전/후 사이의 offset 계산해서 r6에 저장 r6 = 재배치 전/후 사이의 offset r6
  • 42. # 9 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp) 4k LC0(r0) _edata sub r6, r9, r6 add sp, sp, r6 bl cache_clean_flush 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 head.o, misc.o, piggy.gz 현재 sp에 재배치 offset을 추가해서 sp 재조정 r6 = 재배치 전/후 사이의 offset 4k stack area
  • 43. # 9 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp) 4k LC0(r0) _edata sub r6, r9, r6 add sp, sp, r6 bl cache_clean_flush 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 head.o, misc.o, piggy.gz 재배치한 곳에서 코드를 다시 수행 하기 위해 cache flush r6 = 재배치 전/후 사이의 offset 4k stack area
  • 44. # 10 0x8000 head.o piggy.gz misc.o r5 ≒ :restart :reloc_code_end 16k page table user_stack_end (sp) 4k LC0(r0) _edata adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 head.o, misc.o, piggy.gz r6 = 재배치 전/후 사이의 offset 4k stack area
  • 45. # 10 0x8000 head.o piggy.gz misc.o r0(:restart) :reloc_code_end 16k page table user_stack_end (sp) 4k _edata adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 64k 16k :wont_overwrite 0x8000에서 압축 풀었을 경우 차지하는 공간 r6 r9 r10 head.o, misc.o, piggy.gz r6 = 재배치 전/후 사이의 offset 4k stack area 참고 : BSYM macro는 badr macro로 대체 되었음 e.g. badr r0, restart https://github.com/torvalds/linux/commit/14327c662822e5e874cb971a716 2067519300ca8 restart label의 pc 상대 주소를 r0에 저장
  • 46. # 10 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp) 4k _edata adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 64k 16k :wont_overwrite r6 r9 r10 head.o, misc.o, piggy.gz r6 = 재배치 전/후 사이의 offset 4k stack area r0에 재배치 offset을 추가 즉, 재배치 한 위치의 restart label이 있는 위치를 r0에 저장 r0 (재배치된 restart label이 있는 위치)
  • 47. # 10 0x8000 head.o piggy.gz misc.o :restart :reloc_code_end 16k page table user_stack_end (sp) 4k _edata adr r0, BSYM(restart) add r0, r0, r6 mov pc, r0 64k 16k :wont_overwrite r6 r9 r10 head.o, misc.o, piggy.gz r6 = 재배치 전/후 사이의 offset 4k stack area pc를 r0로 설정 즉, 재배치된 restart label이 있는곳 부터 다시 코드를 실행 결과적으로 stack, heap을 다시 확보하고 wont_overwrite label로 branch하여 이후 코드(압축해제)를 실행 r0 (재배치된 restart label이 있는 위치)
  • 48. References • https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/head.S • https://github.com/torvalds/linux/blob/master/arch/arm/boot/compressed/vmlinux.lds. S • https://github.com/torvalds/linux/commit/14327c662822e5e874cb971a7162067519300 ca8 • https://tools.ietf.org/html/rfc1952 • http://www.onicos.com/staff/iz/formats/gzip.html