Linux 页 table 指针解除引用中到底发生了什么?
What is exactly happening in Linux page table pointers dereferencing?
我正在尝试调查页面 table walk in Linux 内核。我使用标准方式浏览页面 table 以查找 PFN(仅作为示例,并非实际代码):
pgd_t *pgd; pte_t *ptep; pte_t pte; pud_t *pud; pmd_t *pmd;
struct page *pagePtr = NULL;
struct mm_struct *mm = current->mm;
pgd = pgd_offset(mm, addr);
pud = getPud(pgd, addr);
pmd = pmd_offset(pud, addr);
ptep = pte_offset_map(pmd, addr);
size_t pfn = pte_pfn(pte);
系统是
CPU: Intel(R) Core(TM) i7-3770
CPU @ 3.40GHz
OS: Linux Fedora release 22 (Twenty Two) Kernel: 4.4.4-200.fc22.x86_64
我正在尝试了解 pgd 指针如何取消引用到 pud 指针。我将简单的代码放入 getPud 函数中:
noinline pud_t *getPud(pgd_t *pgdPtr, unsigned long addr).
{
return pud_offset(pgdPtr, addr);
}
并尝试通过objdump反汇编
00000000000000b0 <getPud>:
b0: e8 00 00 00 00 callq b5 <getPud+0x5>
b5: 55 push %rbp
b6: 48 8b 3f mov (%rdi),%rdi
b9: 48 89 e5 mov %rsp,%rbp
bc: ff 14 25 00 00 00 00 callq *0x0
c3: 48 c1 ee 1b shr [=14=]x1b,%rsi
c7: 48 ba 00 00 00 00 00 movabs [=14=]xffff880000000000,%rdx
ce: 88 ff ff
d1: 81 e6 f8 0f 00 00 and [=14=]xff8,%esi
d7: 48 01 d6 add %rdx,%rsi
da: 48 ba 00 f0 ff ff ff movabs [=14=]x3ffffffff000,%rdx
e1: 3f 00 00
e4: 48 21 d0 and %rdx,%rax
e7: 48 01 f0 add %rsi,%rax
ea: 5d pop %rbp
eb: c3 retq
ec: 0f 1f 40 00 nopl 0x0(%rax)
我的汇编知识不足以理解 callq *0x0
这样的结构
有人可以阐明 getPud 中发生的事情吗?
谢谢
谢尔盖
更新 1
我使用 objdump 反汇编了我创建的 LKM (cpes.ko) 模块以遍历页面 table。
>objdump -dr ./cpes.ko
./cpes.ko: file format elf64-x86-64
Disassembly of section .text:
00000000000000b0 <getPud>:
b0: e8 00 00 00 00 callq b5 <getPud+0x5>
b1: R_X86_64_PC32 __fentry__-0x4
b5: 55 push %rbp
b6: 48 8b 3f mov (%rdi),%rdi
b9: 48 89 e5 mov %rsp,%rbp
bc: ff 14 25 00 00 00 00 callq *0x0
bf: R_X86_64_32S pv_mmu_ops+0xf8
c3: 48 c1 ee 1b shr [=15=]x1b,%rsi
c7: 48 ba 00 00 00 00 00 movabs [=15=]xffff880000000000,%rdx
ce: 88 ff ff
d1: 81 e6 f8 0f 00 00 and [=15=]xff8,%esi
d7: 48 01 d6 add %rdx,%rsi
da: 48 ba 00 f0 ff ff ff movabs [=15=]x3ffffffff000,%rdx
e1: 3f 00 00
e4: 48 21 d0 and %rdx,%rax
e7: 48 01 f0 add %rsi,%rax
ea: 5d pop %rbp
eb: c3 retq
ec: 0f 1f 40 00 nopl 0x0(%rax)
最好查找来源code. As you can see, there is some platform-specific address 魔法。
您正在查看 .o
的反汇编,对吗?不是最终链接的二进制文件? 0x0
地址只是链接器将填充的占位符。(这是通过 static/global 函数指针进行的内存间接调用)。 pud_offset
正在内联到您的函数中。
尝试objdump -dr
或-dR
在反汇编输出中显示重定位条目。
或者更好的是,查看 gcc -S
输出以获得符号名称。 (-fverbose-asm
有时很有帮助)。找出 make
构建文件的命令行,并将其修改为使用 -S -o-
而不是 -c
我正在尝试调查页面 table walk in Linux 内核。我使用标准方式浏览页面 table 以查找 PFN(仅作为示例,并非实际代码):
pgd_t *pgd; pte_t *ptep; pte_t pte; pud_t *pud; pmd_t *pmd;
struct page *pagePtr = NULL;
struct mm_struct *mm = current->mm;
pgd = pgd_offset(mm, addr);
pud = getPud(pgd, addr);
pmd = pmd_offset(pud, addr);
ptep = pte_offset_map(pmd, addr);
size_t pfn = pte_pfn(pte);
系统是
CPU: Intel(R) Core(TM) i7-3770
CPU @ 3.40GHz
OS: Linux Fedora release 22 (Twenty Two) Kernel: 4.4.4-200.fc22.x86_64
我正在尝试了解 pgd 指针如何取消引用到 pud 指针。我将简单的代码放入 getPud 函数中:
noinline pud_t *getPud(pgd_t *pgdPtr, unsigned long addr).
{
return pud_offset(pgdPtr, addr);
}
并尝试通过objdump反汇编
00000000000000b0 <getPud>:
b0: e8 00 00 00 00 callq b5 <getPud+0x5>
b5: 55 push %rbp
b6: 48 8b 3f mov (%rdi),%rdi
b9: 48 89 e5 mov %rsp,%rbp
bc: ff 14 25 00 00 00 00 callq *0x0
c3: 48 c1 ee 1b shr [=14=]x1b,%rsi
c7: 48 ba 00 00 00 00 00 movabs [=14=]xffff880000000000,%rdx
ce: 88 ff ff
d1: 81 e6 f8 0f 00 00 and [=14=]xff8,%esi
d7: 48 01 d6 add %rdx,%rsi
da: 48 ba 00 f0 ff ff ff movabs [=14=]x3ffffffff000,%rdx
e1: 3f 00 00
e4: 48 21 d0 and %rdx,%rax
e7: 48 01 f0 add %rsi,%rax
ea: 5d pop %rbp
eb: c3 retq
ec: 0f 1f 40 00 nopl 0x0(%rax)
我的汇编知识不足以理解 callq *0x0
有人可以阐明 getPud 中发生的事情吗?
谢谢
谢尔盖
更新 1
我使用 objdump 反汇编了我创建的 LKM (cpes.ko) 模块以遍历页面 table。
>objdump -dr ./cpes.ko
./cpes.ko: file format elf64-x86-64
Disassembly of section .text:
00000000000000b0 <getPud>:
b0: e8 00 00 00 00 callq b5 <getPud+0x5>
b1: R_X86_64_PC32 __fentry__-0x4
b5: 55 push %rbp
b6: 48 8b 3f mov (%rdi),%rdi
b9: 48 89 e5 mov %rsp,%rbp
bc: ff 14 25 00 00 00 00 callq *0x0
bf: R_X86_64_32S pv_mmu_ops+0xf8
c3: 48 c1 ee 1b shr [=15=]x1b,%rsi
c7: 48 ba 00 00 00 00 00 movabs [=15=]xffff880000000000,%rdx
ce: 88 ff ff
d1: 81 e6 f8 0f 00 00 and [=15=]xff8,%esi
d7: 48 01 d6 add %rdx,%rsi
da: 48 ba 00 f0 ff ff ff movabs [=15=]x3ffffffff000,%rdx
e1: 3f 00 00
e4: 48 21 d0 and %rdx,%rax
e7: 48 01 f0 add %rsi,%rax
ea: 5d pop %rbp
eb: c3 retq
ec: 0f 1f 40 00 nopl 0x0(%rax)
最好查找来源code. As you can see, there is some platform-specific address 魔法。
您正在查看 .o
的反汇编,对吗?不是最终链接的二进制文件? 0x0
地址只是链接器将填充的占位符。(这是通过 static/global 函数指针进行的内存间接调用)。 pud_offset
正在内联到您的函数中。
尝试objdump -dr
或-dR
在反汇编输出中显示重定位条目。
或者更好的是,查看 gcc -S
输出以获得符号名称。 (-fverbose-asm
有时很有帮助)。找出 make
构建文件的命令行,并将其修改为使用 -S -o-
而不是 -c