使用crash跟踪linux内核(二)- 页表(虚拟地址到物理地址转换)
一、 页表
Linux 64位内核采用4级页表实现虚拟地址到物理地址的转换,4级页表分别是:PGD -> PUD -> PMD -> PTE
1、PGD、PUD、PMD、PTE分别占9位,page offset占12位,合计48位。
2、页面大小为4KB
3、页表项为8B
4、页表可映射的地址空间为:512*512*512*512*4K=256TB

二、 地址空间
Linux内核64位地址空间时将0x0000,0000,0000,0000 – 0x0000,7fff,ffff,f000这128T地址用于用户空间,而0xffff,8000,0000,0000以上为内核地址空间。内核空间起始存在空洞,真正的系统空间的起始地址,是从0xffff,8800,0000,0000开始。即:#define __PAGE_OFFSET _AC(0xffff,8800,0000,0000, UL)
物理地址=虚拟地址- __PAGE_OFFSET

注意:一些高版本系统对内核基地址进行随机化处理,放在page_offset_base中,如下:
crash> !uname -a
Linux sword 4.15.0-52-generic #56-Ubuntu SMP Tue Jun 4 22:49:08 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
crash> px page_offset_base
page_offset_base = $9 = 0xffff942d80000000
crash> p -x kcore_text
kcore_text = $2 = {
list = {
next = 0xffffffff946e4400,
prev = 0xffffffff9453b700
},
addr = 0xffffffff92c00000,
size = 0x1b6a000,
type = 0x0
}
crash> p -x kcore_vmalloc
kcore_vmalloc = $3 = {
list = {
next = 0xffffffff946e4380,
prev = 0xffffffff946e43c0
},
addr = 0xffffb1c380000000,
size = 0x1fffffffffff,
type = 0x1
}
crash> p -x kcore_modules
kcore_modules = $4 = {
list = {
next = 0xffff942f93fcfe00,
prev = 0xffffffff946e4400
},
addr = 0xffffffffc0000000,
size = 0x3f000000,
type = 0x1
}
三、 举例
1、 测试程序pagetable_test
#include <stdio.h>
#include <unistd.h>
int main(int argc,char **argv)
{
const char * str = "kongu106";
printf("%s --- %p\n",str,str);
pause();
}
2、 编译和运行程序
[root@kongu pagetable_test]# gcc -o pagetable_test main.cpp
[root@kongu pagetable_test]# ./pagetable_test
kongu106 --- 0x4006ac
分析虚拟地址0x4006ac,从低位向高位看
page offset占12位:0x6ac
PTE占9位:0x00
PMD占9位:0x02
PUD占9位:0x00
PGD占9位:0x00
3、 跟踪pagetable_test
[root@kongu test]# cd pagetable_test/
[root@kongu pagetable_test]# crash /usr/lib/debug/lib/modules/2.6.32-431.el6.x86_64/vmlinux /boot/System.map-2.6.32-431.el6.x86_64
crash 6.1.0-5.el6
Copyright (C) 2002-2012 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.
GNU gdb (GDB) 7.3.1
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...
SYSTEM MAP: /boot/System.map-2.6.32-431.el6.x86_64
DEBUG KERNEL: /usr/lib/debug/lib/modules/2.6.32-431.el6.x86_64/vmlinux (2.6.32-431.el6.x86_64)
DUMPFILE: /dev/crash
CPUS: 2
DATE: Wed Jul 12 01:58:37 2017
UPTIME: 04:09:00
LOAD AVERAGE: 0.14, 0.03, 0.01
TASKS: 287
NODENAME: kongu
RELEASE: 2.6.32-431.el6.x86_64
VERSION: #1 SMP Sun Nov 10 22:19:54 EST 2013
MACHINE: x86_64 (2294 Mhz)
MEMORY: 2 GB
PID: 21054
COMMAND: "crash"
TASK: ffff880037555500 [THREAD_INFO: ffff880016996000]
CPU: 1
STATE: TASK_RUNNING (ACTIVE)
crash> !ps -ef | grep pagetable
root 21017 9721 0 01:52 pts/2 00:00:00 ./pagetable_test
root 21066 21054 0 01:59 pts/0 00:00:00 sh -c ps -ef | grep pagetable
root 21068 21066 0 01:59 pts/0 00:00:00 grep pagetable
crash> set 21017
PID: 21017
COMMAND: "pagetable_test"
TASK: ffff8800168be040 [THREAD_INFO: ffff88007cd12000]
CPU: 0
STATE: TASK_INTERRUPTIBLE
crash> px ((struct task_struct*)0xffff8800168be040)->mm->pgd //PGD虚拟地址
$3 = (pgd_t *) 0xffff88003a1e2000
crash> px 0xffff88003a1e2000-0xffff880000000000 //虚拟地址转为物理地址
$4 = 0x3a1e2000 //物理地址,运行时放在CR3
crash> rd -p 0x3a1e2000 //PGD中第0项
3a1e2000: 0000000016946067 g`......
crash> pte 0000000016946067
PTE PHYSICAL FLAGS
16946067 16946000 (PRESENT|RW|USER|ACCESSED|DIRTY)
crash> px 0x16946000
$5 = 0x16946000
crash> rd -p 0x16946000 //PUD中第0项
16946000: 00000000169c3067 g0......
crash> pte 00000000169c3067
PTE PHYSICAL FLAGS
169c3067 169c3000 (PRESENT|RW|USER|ACCESSED|DIRTY)
crash> px 0x169c3000+0x2*8 //PMD中第2项
$6 = 0x169c3010
crash> rd -p 0x169c3010
169c3010: 000000007c0bc067 g..|....
crash> pte 000000007c0bc067
PTE PHYSICAL FLAGS
7c0bc067 7c0bc000 (PRESENT|RW|USER|ACCESSED|DIRTY)
crash> rd -p 7c0bc000 //PTE中第0项
7c0bc000: 000000003acc9025 %..:....
crash> pte 000000003acc9025
PTE PHYSICAL FLAGS
3acc9025 3acc9000 (PRESENT|USER|ACCESSED)
crash> px 0x3acc9000+0x6ac //page中加偏移0x6ac
$7 = 0x3acc96ac
crash> rd -p 0x3acc96ac 4 //显示字符串
3acc96ac: 36303175676e6f6b 202d2d2d20732500 kongu106.%s ---
3acc96bc: 3b031b01000a7025 000000040000002c %p.....;,.......
crash> vtop 0x4006ac //单条命令实现转换
VIRTUAL PHYSICAL
4006ac 3acc96ac
PML: 3a1e2000 => 16946067
PUD: 16946000 => 169c3067
PMD: 169c3010 => 7c0bc067
PTE: 7c0bc000 => 3acc9025
PAGE: 3acc9000
PTE PHYSICAL FLAGS
3acc9025 3acc9000 (PRESENT|USER|ACCESSED)
VMA START END FLAGS FILE
ffff88007c6cf850 400000 401000 8001875 /test/pagetable_test/pagetable_test
PAGE PHYSICAL MAPPING INDEX CNT FLAGS
ffffea0000cdcbf8 3acc9000 ffff88006a5905d8 0 3 2000000000086c
浙公网安备 33010602011771号