我正在尝试研究 Linux 内核中的页表遍历。我使用标准方法遍历页表来查找 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 $0x1b,%rsi
c7: 48 ba 00 00 00 00 00 movabs $0xffff880000000000,%rdx
ce: 88 ff ff
d1: 81 e6 f8 0f 00 00 and $0xff8,%esi
d7: 48 01 d6 add %rdx,%rsi
da: 48 ba 00 f0 ff ff ff movabs $0x3ffffffff000,%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) 模块。
>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 $0x1b,%rsi
c7: 48 ba 00 00 00 00 00 movabs $0xffff880000000000,%rdx
ce: 88 ff ff
d1: 81 e6 f8 0f 00 00 and $0xff8,%esi
d7: 48 01 d6 add %rdx,%rsi
da: 48 ba 00 f0 ff ff ff movabs $0x3ffffffff000,%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)
最佳答案
您正在查看 .o
的反汇编,对吧?不是最终链接的二进制文件? 0x0
地址只是链接器将填充的占位符。(这是通过静态/全局函数指针进行的内存间接调用)。 pud_offset
正在内联到您的函数中。
尝试使用 objdump -dr
或 -dR
在反汇编输出中显示重定位条目。
或者更好的是,查看 gcc -S
输出以获得符号名称。 (-fverbose-asm
有时很有用)。找出 make
用来构建文件的命令行,并将其修改为使用 -S -o-
而不是 -c
关于linux - Linux 页表指针取消引用到底发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36213723/