形成过程
---------------------------------------------------------------------------
./scripts/kallsyms.c负责生成System.map
./kernel/kallsyms.c负责生成/proc/kallsyms
./scripts/kallsyms.c解析vmlinux(.tmp_vmlinux)生kallsyms.S(.tmp_kallsyms.S),然后内核编译过程中将kallsyms.S(内核符号表)编入内核镜像uImage
内核启动后./kernel/kallsyms.c解析uImage形成/proc/kallsyms
/proc/kallsyms包含了内核中的函数符号(包括没有EXPORT_SYMBOL)、全局变量(用EXPORT_SYMBOL导出的全局变量)
将内核中的函数、全局变量、静态变量导出到/proc/kallsyms
---------------------------------------------------------------------------
./scripts/kallsyms
staticint all_symbols = 0;
==>
static intall_symbols = 1;
引入kallsyms
------------------------------------------------------------------------
在2.6内核中,为了更好地调试内核,引入了kallsyms。kallsyms抽取了内核用到的所有函数地址(全局的、静态的)和非栈数据变量地址,生成一个数据块,作为只读数据链接进kernel image,相当于内核中存了一个System.map。需要配置CONFIG_KALLSYMS.config
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y符号表中包括所有的变量(包括没有用EXPORT_SYMBOL导出的变量)
CONFIG_KALLSYMS_EXTRA_PASS=y
makemenuconfig
General setup --->
[*] Configure standard kernel features (for smallsystems) --->
[*] Load allsymbols for debugging/ksymoops
[*] Include all symbols in kallsyms
[*] Do an extra kallsymspass
配置CONFIG_KALLSYMS_ALL之后,就不需要修改all_symbol静态变量为1了
32bit addr |--------------------|
| |
| |
~ ~
| |
| |
0xc05d 1dc0|--------------------| _end
| |
| |
| BSS |
| |
| |
0xc05a 4500|--------------------| __bss_start
| |
0xc05a 44e8|--------------------| _edata
| |
| |
| DATA |
| |
| |
0xc058 2000|--------------------| __data_start init_thread_union
| |
0xc058 1000|--------------------| _etext
| |
|rodata |
| |
0xc056 d000|--------------------| __start_rodata
| |
| |
| Real text |
| |
| |
0xc02a 6000|--------------------| _text __init_end TEXT
| |
|Exit code and data | 这个section在内核完成初始化后
| | 会被释放掉
0xc002 30d4|--------------------| _einittext
| |
|Init code and data |
| |
0xc000 8000|--------------------|<------------ __init_begin _stext
| |
0xc0000000|--------------------|
arch/arm/kernel/vmlinux.lds.S
kallsyms中間字母的意義 :
T The symbol is in the text(code) section
D The symbol is in theinitialized data section
R The sysbol is in a read onlydata section
t static
d static
R const
r static const
注:
1. 文本段中的只读段均为变量
2. 文本段中的INIT断,可视为变量,因为命令中不会调用初始化函数,另外该区域在内核启动完成后,已经被bootmem释放了,所以该区域可能会被另作它用
64bit addr的例子
0000000000000000 Dirq_stack_union
0000000000000000 D__per_cpu_start
0000000000004000 Dgdt_page
0000000000005000 dexception_stacks
000000000000b000 dtlb_vector_offset
000000000000b080 Dxen_vcpu_info
000000000000b0c0 Dxen_vcpu
000000000000b0c8 didt_desc
000000000000b0d8 dxen_cr0_value
000000000000b0e0 Dxen_mc_irq_flags
000000000000b100 dmc_buffer
............
ffffffff81000000 Tstartup_64
ffffffff81000000 T_text
ffffffff810000b7 tident_complete
ffffffff81000100 Tsecondary_startup_64
ffffffff8100018a tbad_address
ffffffff81000190 T_stext
ffffffff81001000 Thypercall_page
ffffffff81002000 Tdo_one_initcall
ffffffff81002180 tdevt_from_partuuid
ffffffff81002260 tmatch_dev_by_uuid
ffffffff810022a0 Tname_to_dev_t
ffffffff81002570 Tpopulate_rootfs_wait
ffffffff81003000 tnative_read_cr4
ffffffff81003010 tnative_read_cr4_safe
ffffffff81003020 tnative_wbinvd
ffffffff81003030 tnative_read_msr_safe
ffffffff81003060 tnative_read_pmc
ffffffff81003080 tnative_store_gdt
ffffffff81003090 tnative_store_idt
ffffffff810030a0 txen_cpuid
.............
ffffffffa0001780 Tspi_print_msg [scsi_transport_spi]
ffffffffa0005560 d__this_module [scsi_transport_spi]
ffffffffa0000020 tspi_populate_sync_msg [scsi_transport_spi]
ffffffffa0003558 tcleanup_module [scsi_transport_spi]
ffffffffa0001cc0 Tspi_display_xfer_agreement [scsi_transport_spi]
ffffffffa0001470 Tspi_release_transport [scsi_transport_spi]
ffffffffa0000000 tspi_populate_width_msg [scsi_transport_spi]
ffffffffa00004d0 Tspi_schedule_dv_device [scsi_transport_spi]
ffffffffa0000050 tspi_populate_ppr_msg [scsi_transport_spi]
ffffffffa0003490 Tspi_attach_transport [scsi_transport_spi]
ffffffffa0001d20 Tspi_dv_device [scsi_transport_spi]
另外64位Linux系統只用了40位尋址空間
內存不足或內存中不活躍的數據 用到swap
虛擬地址空間:32位OS為每個進程都分配了一個4GB的虛擬地址空間