内核sys_call_table地址与system.map中指定的地址不匹配

我想刷C,所以我一直在玩Linux内核的系统调用表(在3.13.0-32-generics)。 我发现了一个在线资源,用以下函数search系统调用表,我在LKM中加载到内核中:

static uint64_t **aquire_sys_call_table(void) { uint64_t offset = PAGE_OFFSET; uint64_t **sct; while (offset < ULLONG_MAX) { sct = (uint64_t **)offset; if (sct[__NR_close] == (uint64_t *) sys_close) { printk("\nsys_call_table found at address: 0x%p\n", sys_call_table); return sct; } offset += sizeof(void *); } return NULL; } 

该function起作用。 我能够使用它返回的地址来操纵系统调用表。 我不明白为什么这个函数返回的地址与/boot/System.map-(KERNEL)中的地址不匹配

这是什么function打印:

 sys_call_table found at address: 0xffff880001801400 

这是我searchsystem.map时得到的

 $ sudo cat /boot/System.map-3.13.0-32-generic | grep sys_call_table ffffffff81801400 R sys_call_table ffffffff81809cc0 R ia32_sys_call_table 

为什么这两个地址不匹配? 我的理解是,模块运行在内核的地址空间中,所以系统调用表的地址应该是相同的。

这两个虚拟地址具有相同的物理地址。

Documentation/x86/x86_64/mm.txt

 <previous description obsolete, deleted> Virtual memory map with 4 level page tables: 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm hole caused by [48:63] sign extension ffff800000000000 - ffff87ffffffffff (=43 bits) guard hole, reserved for hypervisor ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB) ... unused hole ... ffffec0000000000 - fffffc0000000000 (=44 bits) kasan shadow memory (16TB) ... unused hole ... ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks ... unused hole ... ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0 ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole The direct mapping covers all memory in the system up to the highest memory address (this means in some cases it can also include PCI memory holes). vmalloc space is lazily synchronized into the different PML4 pages of the processes using the page fault handler, with init_level4_pgt as reference. Current X86-64 implementations only support 40 bits of address space, but we support up to 46 bits. This expands into MBZ space in the page tables. ->trampoline_pgd: We map EFI runtime services in the aforementioned PGD in the virtual range of 64Gb (arbitrarily set, can be raised if needed) 0xffffffef00000000 - 0xffffffff00000000 -Andi Kleen, Jul 2004 

我们知道虚拟地址空间ffff880000000000ffffc7ffffffffff是所有物理内存的直接映射。 当内核想要访问所有的物理内存时,它使用直接映射。 这也是你用来搜索的。

ffffffff80000000ffffffffa0000000是内核文本映射。 当内核代码执行时, rip寄存器使用内核文本映射。

arch/x86/include/asm/page_64.h ,我们可以得到虚拟地址和物理地址的关系。

 static inline unsigned long __phys_addr_nodebug(unsigned long x) { unsigned long y = x - __START_KERNEL_map; /* use the carry flag to determine if x was < __START_KERNEL_map */ x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET)); return x; } 

 // arch/x86/include/asm/page_types.h #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) // arch/x86/include/asm/page_64_types.h #define __START_KERNEL_map _AC(0xffffffff80000000, UL) #define __PAGE_OFFSET _AC(0xffff880000000000, UL) 

至于上面提到的地址,

什么功能打印,

 sys_call_table found at address: 0xffff880001801400 

什么system.map给,

 $ sudo cat /boot/System.map-3.13.0-32-generic | grep sys_call_table ffffffff81801400 R sys_call_table ffffffff81809cc0 R ia32_sys_call_table 

他们都解析为相同的物理地址。

virt-> phys转换发生在“直接”映射区域和“内核文本”映射区域中的相应地址解析为相同的物理地址。

通过虚拟内存映射的魔力,你使用的地址取决于你在哪里。 符号表文件System.map将帮助将gdb或崩溃实用程序附加到正在运行的系统。 在内核里面,在内核里面。

你可能还有一个/ proc / kallsym文件来获取更多的值:)