test.S
.text .global _start _start: mov $0xa, %rdx mov $0xb, %rdx mov $0xc, %rdx mov _head(%rip), %rcx mov $_head, %rcx mov $_ehead, %rcx
TEST 1 :: AT(ADDR(.text)) 사용
test.ld
SECTIONS { . = 0x100; .text : AT(ADDR(.text)){ _head = . ; *(.text) _ehead = . ; } .data : { *(.data) } .bss : { *(.bss) *(COMMON) } }
result of ./as test.S -o test.o && ld -T test.ld test.o && objdump -d a.out
a.out: file format elf64-x86-64 Disassembly of section .text: 0000000000000100 <_head>: 100: 48 c7 c2 0a 00 00 00 mov $0xa,%rdx 107: 48 c7 c2 0b 00 00 00 mov $0xb,%rdx 10e: 48 c7 c2 0c 00 00 00 mov $0xc,%rdx 115: 48 8b 0d e4 ff ff ff mov -0x1c(%rip),%rcx # 100 <_head> 11c: 48 c7 c1 00 01 00 00 mov $0x100,%rcx 123: 48 c7 c1 2a 01 00 00 mov $0x12a,%rcx
Test 2 :: AT(ADDR(.text) + 10)
test.ld
SECTIONS { . = 0x100; .text : AT(ADDR(.text) + 10){ _head = . ; *(.text) _ehead = . ; } .data : { *(.data) } .bss : { *(.bss) *(COMMON) } }
result of ./as test.S -o test.o && ld -T test.ld test.o && objdump -d a.out
a.out: file format elf64-x86-64 Disassembly of section .text: 0000000000000100 <_head>: 100: 48 c7 c2 0a 00 00 00 mov $0xa,%rdx 107: 48 c7 c2 0b 00 00 00 mov $0xb,%rdx 10e: 48 c7 c2 0c 00 00 00 mov $0xc,%rdx 115: 48 8b 0d e4 ff ff ff mov -0x1c(%rip),%rcx # 100 <_head> 11c: 48 c7 c1 00 01 00 00 mov $0x100,%rcx 123: 48 c7 c1 2a 01 00 00 mov $0x12a,%rcx
AT 안에 있는 두가지 $head, $_ehead가 두가지 다른 AT에 대해서 같은 결과를 내는 것 같아요..
댓글 12
-
도영주
2013.11.10 19:56
-
이경욱
2013.11.11 20:54
넵 저도 제가 생각하는 선에서 말씀드린거에요!
이게 스터디를 진행하면서 계속 오락가락 하던 부분이라
저도 또 나중에 생각이 바뀔수도 있으니 일단 좀 더 살펴보고
주말에 다시한번 이야기해 보아요! ㅋㅋ
-
도영주
2013.11.11 20:46
네 제가 틀렸을 수도 있어요.
그런데 중간에 점프한 부분이 없는지 다시 확인해보고 싶은 마음이 들어서,
다시 한번 태클을 걸어본 것입니다.
이 부분이 아시다시피 중요한 부분이라고 생각하니까, 더 잘 이해해보고자 하는 마음이니
이해해 주시길 바랍니다. ^^;
-
이경욱
2013.11.11 20:37
early_dynamic_pgts는 leaq _text(%rip), %rdi 로 실제 물리주소를 구해서 쉬프트연산 등을 통해
값을 넣어 주기 때문에 %rbp를 더해줄 필요가 없습니다
즉, 하위 페이지의 확실한 물리 주소값을 알고 있는거죠
그치만 early_level4_pgt(맨 마지막 엔트리), level3_kernel_pgt, level2_kernel_pgt, level2_fixmap_pgt는
이미 고정된 값이 들어가 있는 상태라 relocate된 경우의 값을 더해주는 것 같습니다
relocate된 경우 하위 페이지의 물리 주소가 바뀌겠죠
%rbp를 더해주는 부분은 모두 코드에서 미리 고정된 값을 넣어준 테이블들 뿐이거든요
그리고 말씀하신대로 pgt의 엔트리는 address가 맞습니다
-
도영주
2013.11.11 20:22
early_dynamic_pgts[0,1]은 rbp를 더 해주지 않습니다.
그 때 얘기한 바로는 저 부분에서 rbp에 START_KERNEL_map 값이 들어가도 이상하지 않습니다.
그리고 pgt의 내부 entry의 값은 index가 아니라 address 아닌가 생각이네요.
논의가 좀 이상한것 같은데, 좀 더 확인해보고 다음주에 명확하게 답을 할 수 있도록 최대한 노력해보겠습니다.
-
이경욱
2013.11.11 20:04
addq %rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
addq %rbp, level3_kernel_pgt + (510*8)(%rip)
addq %rbp, level3_kernel_pgt + (511*8)(%rip)
addq %rbp, level2_fixmap_pgt + (506*8)(%rip)
모든 레벨에 다 더해주고 있습니다!
-
도영주
2013.11.11 19:52
네 경욱씨가 하는 이야기가 무슨 이야기인지는 압니다.
해당하는 코드 영역은 밑에 이 부분인 것 같은데요.
193 leaq level2_kernel_pgt(%rip), %rdi
194 leaq 4096(%rdi), %r8
195 /* See if it is a valid page table entry */
196 1: testq $1, 0(%rdi)
197 jz 2f
198 addq %rbp, 0(%rdi)
만약, 모든 레벨의 페이지 테이블 엔트리마다 rbp 가 더 해진다면 존재하지 않는 주소값이겠지만,
전체 영역을 더하는 것이 아니라, level2_kernel_pgt입니다.
그리고 해당 값이 0인 경우에 더 해줘야 하는 이유가 좀 불분명 한 것 같기도 하고요.
시간이 날지는 모르겠지만, 조금 더 고민해보도록 하겠습니다.
확실하지 않은 돌을 밟고 가다가 멘붕되는 건 좀 더 줄여봐야죠^^;
-
이경욱
2013.11.11 09:29
확실한 건 subq $_text - __START_KERNEL_map, %rbp 에는 0이 들어가는 것 같습니다.
저번시간에 이광철 선생님 말씀처럼 페이지 테이블의 엔트리는 항상 다음에 가리킬 테이블의 물리 주소가 들어가 있어야 하는데 아래에서 모든 레벨의 페이지 테이블 엔트리마다 %rbp값을 더해줍니다.
그런데 만약 0xFFFFFFFF80000000값을 더해주게 돼버리면 존재하지 않는 물리주소값이 들어가게 됩니다.
페이지 테이블의 엔트리는 물리주소를 가지고 있고
가상 주소는 index로 사용한다는 걸 생각하면 %rbp는 큰 값을 가질 수 없는 것 같습니다
-
pororo
2013.11.14 13:59
정확히 어떤 것에 대해서 논의하시는지 모르겠지만
AT의 변화는 VMA보다 objdump -h로 LMA 쪽을 보셔야 합니다.
LMA가 변하면 decompress 될 때 커널의 로드 주소가 바뀌게 됩니다.
rbp는 컴파일<->현재 로드된 주소의 차이가 들어가게 될 것 같습니다.
16M로 컴파일 되었는데 커널이 48M에 로드되었으면 주소 차이가 발생하기 때문에 이를 보정해주기 위해 32M의 보정 값이 rbp에 들어갈 것입니다. -
도영주
2013.11.14 17:27
네네 감사합니다.
_text는 16M, $_text는 __START_KERNEL_map + 16M 이렇게 된다고 말씀하시는거죠?
이게 맞는 것 같은데, 확인을 못해서 한참 논의가 돌고 돌았습니다.
여러모로 도움을 주셔서 다시 한번 감사드립니다.
-
pororo
2013.11.14 17:08
페이지 테이블에 들어가는 값은 물리주소라서 START_KERNEL_map이 들어가지는 않을겁니다.
이 소스를 말씀하시는 건가요?
leaq _text(%rip), %rbp
subq $_text - __START_KERNEL_map, %rbp
윗 라인을 보면 메모리맵은 4G 영역에 걸쳐 물리-가상 주소가 1:1 매핑하고 있기 때문에
유효주소와 상대주소로 얻어온 값은 커널이 압축풀린 주소인 16M가 들어갈 겁니다.
아랫 라인은 심볼들은 가상주소이고 _text도 보통은 __START_KERNEL_map + 16M 이니
둘을 빼면 16M이 나오겠네요. 16M - 16M로 결론은 rbp는 0이 됩니다.
다만 컴파일이 16M 주소로 되어있지만 커널이 48M에 로드되는 경우를 생각해보면 rbp에는 32M가 대입될 겁니다.
윗 라인에서 48M이 들어가고 아랫 라인에서는 16M가 들어가서
rbp에는 48M(커널이 위치한 주소) - 16M(컴파일된 주소) 로 둘의 차이인 32M가 들어갑니다. -
도영주
2013.11.14 16:07
저희가 지금 rbp때문에 고민하는 이유는 arch/x86/kernel/head_64.S에서
rbp에 START_KERNEL_map이라는 값 때문입니다. ( START_KERNEL_map (0xffffffff80000000))
중간에 rbp를 더하는 값에서 page tabe의 물리 주소가 달라지게 됩니다.
rbp가 0x0인가 START_KERNEL_map인가.
이거 때문에 한 2주간 진도를 못 빼고 헤매고 있습니다.
중간에 rbp 가 START_KERNEL_map이라는 큰 값이 들어가면,
제대로 그림이 제대로 안그려지는 것 같아서요.
.
계속해서 이 부분이 마음에 걸리는데, 맞는 것인지 아닌지 정확하게 모르겠습니다.
토요일에 동현씨가 맞다고 생각한 부분이 오늘보니 아닌 것 같다는 느낌이 드네요.
왜 그런가하면 예상한 code의 진행으로는 Test1과 Test2의 시작 주소가 서로 달라야 합니다.
하지만, Test1과 Test2의 시작주소가 같아서, 결국 AT(ADDR(.text) + 10)이라는 문법이 제대로 적용이 안됐다고 볼 수 밖에 없을 것 같아요.
이 부분에 대해서는 좀 더 고민한 다음에 Test code한번 만들어볼께요.