x86 32位CPU采用了段页式地址映射模型。进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存。
段页式机制如下图。
虚拟内存地址 通过CPU特殊组件 还有页表进行映射到物理内存地址上
下面是页表功能, 以前我学习过页表 可以参考
Linux 64 页表,进程内存,大页
Linux_x86_64BIT内存管理与分布
64位进程后来没有了逻辑地址,下面学习BIN的技术小屋的时候,发现个疑问
那就是 进程的虚拟地址有规划代码段起始地址是: 0X000 000 0040 0000
内核地址空间也有地址规划!
什么问题呢? 就是 页表必须按规划的地址进行分配 比如说:
0X000 000 0040 0000 16进制变成2进制48位
0x000000000,000000000,000000100,000000000,00000000000
PMD 页目录偏移=100 换成10进制=4 前面3个位置被谁占了?
内存本来就精贵的资源,而且页表也占用内存,页表现在就变成了稀疏数组了.
相对于来说就是浪费了很多内存,前面3个数组下标 64位占用8个字节,就24个字节单位.
我们程序运行过程中打印的变量地址, 函数地址,指针地址. 这些都是什么呢? 以前叫逻辑地址,现在被说成了虚拟地址.
那么这个地址是哪个部分? 还是两种不一样的东西,还是一样的东西不同的叫法, 确实让人着迷一段时间,期间访问很多大佬,视乎也没有个明确的说法.
继续深入学习LINUX内核文章时候,视乎感觉LINUX系统 不按程序的要求进行地址安排,0X000 000 0040 0000 这个地址虚拟化 不一定是 0040.
因为64位就一个段地址,基地址都是0!
进程自己的虚拟内存空间还有个边界, 分配的虚拟地址在边界范围之内,那么如何鉴定地址越界呢? 如果说地址是连续的,那么就好比较.
可虚拟地址格式 4个9位 是按照页表目录索引数字.
要么按照规划来分配页表, 就造成稀疏页表,浪费很多内存.
如果按照节约内存方式,搞紧凑页表,就得先来先分配,先来的在低地址 ,后来的就在高地址. 那边界感怎么搞?
所以这个事比较困惑! 虽然无关紧要, 可是用GCC语言开发非常容易地址越界,非法存取,野指针.
#include
#include
#include
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int g=78;
int main(int argc, char *argv[])
{
int i;
printf("变量i的定义时地址是:%p\n", &i);
i=32;
printf("变量i赋值后的地址是:%p\n", &i);
printf("全局静态变量G的地址: %p\n",&g);
char *pChar;
printf("pChar内存变量本身地址: %p\n",&pChar);
pChar=(char*)malloc(10);
printf("动态分配地址: %p\n",pChar);
strcpy(pChar,"123456iii");
printf("使用动态分配地址: %p\n",pChar);
char cExit;
printf("是否退出? Y/N");
scanf("%c",&cExit);
if (cExit=='Y')
return 0;
}
上面这段C语言可以完整在CENTOS 编译通过,运行效果如下
[root@dsmart=>OTHER_C]$./Vmaddres.exe
变量i的定义时地址是:0x7fffffffe04c
变量i赋值后的地址是:0x7fffffffe04c
全局静态变量G的地址: 0x601050
pChar内存变量本身地址: 0x7fffffffe040
动态分配地址: 0x602010
使用动态分配地址: 0x602010
是否退出? Y/Ny
变量i 的地址一直没有发生改变,按照虚拟内存假分配,通过实际使用中发生缺页中断来分配实际的物理内存
虚拟内存地址 低12位 也就是0:12位是实际物理内存地址...
011111111,111111111,111111111,111111110,000001001100
因此小仙认为 在64位 程序里面看到的地址叫逻辑地址(兼容32位叫法),或者叫程序地址.
程序地址 <==>进程虚拟地址 有个映射关系 或者数组来1:1对应.
静态读取可执行文件,发现有虚拟地址,物理地址,偏移量,文件大小,内存大小,权限,对齐等信息.
[root@dsmart=>OTHER_C]$readelf -h Vmaddres.exe
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x4004f0
Start of program headers: 64 (bytes into file)
Start of section headers: 6560 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 28
[root@dsmart=>OTHER_C]$readelf -l Vmaddres.exe
Elf file type is EXEC (Executable file)
Entry point 0x4004f0
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x000000000000097c 0x000000000000097c R E 200000
LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x0000000000000244 0x0000000000000248 RW 200000
DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28 0x00000000000001d0 0x00000000000001d0 RW 8
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 0x0000000000000020 0x0000000000000020 R 4
GNU_EH_FRAME 0x0000000000000850 0x0000000000400850 0x0000000000400850 0x0000000000000034 0x0000000000000034 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x00000000000001f0 0x00000000000001f0 R 1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
[root@dsmart=>OTHER_C]$readelf -S Vmaddres.exe
There are 29 section headers, starting at offset 0x19a0:
Section Headers:
[Nr] Name Type Address Offset Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254 0000000000000020 0000000000000000 A 0 0 4
[ 3] .hash HASH 0000000000400278 00000278 000000000000002c 0000000000000004 A 4 0 8
[ 4] .dynsym DYNSYM 00000000004002a8 000002a8 0000000000000090 0000000000000018 A 5 1 8
[ 5] .dynstr STRTAB 0000000000400338 00000338 000000000000005f 0000000000000000 A 0 0 1
[ 6] .gnu.version VERSYM 0000000000400398 00000398 000000000000000c 0000000000000002 A 4 0 2
[ 7] .gnu.version_r VERNEED 00000000004003a8 000003a8 0000000000000030 0000000000000000 A 5 1 8
[ 8] .rela.dyn RELA 00000000004003d8 000003d8 0000000000000018 0000000000000018 A 4 0 8
[ 9] .rela.plt RELA 00000000004003f0 000003f0 0000000000000078 0000000000000018 AI 4 22 8
[10] .init PROGBITS 0000000000400468 00000468 000000000000001a 0000000000000000 AX 0 0 4
[11] .plt PROGBITS 0000000000400490 00000490 0000000000000060 0000000000000010 AX 0 0 16
[12] .text PROGBITS 00000000004004f0 000004f0 0000000000000262 0000000000000000 AX 0 0 16
[13] .fini PROGBITS 0000000000400754 00000754 0000000000000009 0000000000000000 AX 0 0 4
[14] .rodata PROGBITS 0000000000400760 00000760 00000000000000ee 0000000000000000 A 0 0 8
[15] .eh_frame_hdr PROGBITS 0000000000400850 00000850 0000000000000034 0000000000000000 A 0 0 4
[16] .eh_frame PROGBITS 0000000000400888 00000888 00000000000000f4 0000000000000000 A 0 0 8
[17] .init_array INIT_ARRAY 0000000000600e10 00000e10 0000000000000008 0000000000000008 WA 0 0 8
[18] .fini_array FINI_ARRAY 0000000000600e18 00000e18 0000000000000008 0000000000000008 WA 0 0 8
[19] .jcr PROGBITS 0000000000600e20 00000e20 0000000000000008 0000000000000000 WA 0 0 8
[20] .dynamic DYNAMIC 0000000000600e28 00000e28 00000000000001d0 0000000000000010 WA 5 0 8
[21] .got PROGBITS 0000000000600ff8 00000ff8 0000000000000008 0000000000000008 WA 0 0 8
[22] .got.plt PROGBITS 0000000000601000 00001000 0000000000000040 0000000000000008 WA 0 0 8
[23] .data PROGBITS 0000000000601040 00001040 0000000000000014 0000000000000000 WA 0 0 8
[24] .bss NOBITS 0000000000601054 00001054 0000000000000004 0000000000000000 WA 0 0 1
[25] .comment PROGBITS 0000000000000000 00001054 000000000000003e 0000000000000001 MS 0 0 1
[26] .symtab SYMTAB 0000000000000000 00001098 0000000000000618 0000000000000018 27 45 8
[27] .strtab STRTAB 0000000000000000 000016b0 00000000000001ff 0000000000000000 0 0 1
[28] .shstrtab STRTAB 0000000000000000 000018af 00000000000000f1 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
上面列出的信息,搞不懂,基本是说把程序里面某些节,加载到指定内存上
linux中,nm用来列出目标文件的符号清单。
[root@dsmart=>OTHER_C]$nm -n Vmaddres.exe
w __gmon_start__
U __isoc99_scanf@@GLIBC_2.7
U __libc_start_main@@GLIBC_2.2.5
U malloc@@GLIBC_2.2.5
U printf@@GLIBC_2.2.5
0000000000400468 T _init
00000000004004f0 T _start
0000000000400520 t deregister_tm_clones
0000000000400560 t register_tm_clones
00000000004005a0 t __do_global_dtors_aux
00000000004005c0 t frame_dummy
00000000004005e6 T main
00000000004006e0 T __libc_csu_init
0000000000400750 T __libc_csu_fini
0000000000400754 T _fini
0000000000400760 R _IO_stdin_used
0000000000400850 r __GNU_EH_FRAME_HDR
0000000000400978 r __FRAME_END__
0000000000600e10 t __frame_dummy_init_array_entry
0000000000600e10 t __init_array_start
0000000000600e18 t __do_global_dtors_aux_fini_array_entry
0000000000600e18 t __init_array_end
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
0000000000600e28 d _DYNAMIC
0000000000601000 d _GLOBAL_OFFSET_TABLE_
0000000000601040 D __data_start
0000000000601040 W data_start
0000000000601048 D __dso_handle
0000000000601050 D g
0000000000601054 B __bss_start
0000000000601054 b completed.6904
0000000000601054 D _edata
0000000000601058 B _end
0000000000601058 D __TMC_END__
使用静态反汇编查看,代码段400468,
[root@dsmart=>OTHER_C]$objdump -d Vmaddres.exe
Vmaddres.exe: file format elf64-x86-64
Disassembly of section .init:
0000000000400468 <_init>:
400468: 48 83 ec 08 sub $0x8,%rsp
40046c: 48 8b 05 85 0b 20 00 mov 0x200b85(%rip),%rax # 600ff8 <__gmon_start__>
400473: 48 85 c0 test %rax,%rax
400476: 74 05 je 40047d <_init+0x15>
400478: e8 43 00 00 00 callq 4004c0 <__gmon_start__@plt>
40047d: 48 83 c4 08 add $0x8,%rsp
400481: c3 retq
Disassembly of section .plt:
0000000000400490 <.plt>:
400490: ff 35 72 0b 20 00 pushq 0x200b72(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
400496: ff 25 74 0b 20 00 jmpq *0x200b74(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
40049c: 0f 1f 40 00 nopl 0x0(%rax)
00000000004004a0 :
4004a0: ff 25 72 0b 20 00 jmpq *0x200b72(%rip) # 601018
4004a6: 68 00 00 00 00 pushq $0x0
4004ab: e9 e0 ff ff ff jmpq 400490 <.plt>
00000000004004b0 <__libc_start_main@plt>:
4004b0: ff 25 6a 0b 20 00 jmpq *0x200b6a(%rip) # 601020 <__libc_start_main@GLIBC_2.2.5>
4004b6: 68 01 00 00 00 pushq $0x1
4004bb: e9 d0 ff ff ff jmpq 400490 <.plt>
00000000004004c0 <__gmon_start__@plt>:
4004c0: ff 25 62 0b 20 00 jmpq *0x200b62(%rip) # 601028 <__gmon_start__>
4004c6: 68 02 00 00 00 pushq $0x2
4004cb: e9 c0 ff ff ff jmpq 400490 <.plt>
00000000004004d0 :
4004d0: ff 25 5a 0b 20 00 jmpq *0x200b5a(%rip) # 601030
4004d6: 68 03 00 00 00 pushq $0x3
4004db: e9 b0 ff ff ff jmpq 400490 <.plt>
00000000004004e0 <__isoc99_scanf@plt>:
4004e0: ff 25 52 0b 20 00 jmpq *0x200b52(%rip) # 601038 <__isoc99_scanf@GLIBC_2.7>
4004e6: 68 04 00 00 00 pushq $0x4
4004eb: e9 a0 ff ff ff jmpq 400490 <.plt>
Disassembly of section .text:
00000000004004f0 <_start>:
4004f0: 31 ed xor %ebp,%ebp
4004f2: 49 89 d1 mov %rdx,%r9
4004f5: 5e pop %rsi
4004f6: 48 89 e2 mov %rsp,%rdx
4004f9: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
4004fd: 50 push %rax
4004fe: 54 push %rsp
4004ff: 49 c7 c0 50 07 40 00 mov $0x400750,%r8
400506: 48 c7 c1 e0 06 40 00 mov $0x4006e0,%rcx
40050d: 48 c7 c7 e6 05 40 00 mov $0x4005e6,%rdi
400514: e8 97 ff ff ff callq 4004b0 <__libc_start_main@plt>
400519: f4 hlt
40051a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400520 :
400520: b8 5f 10 60 00 mov $0x60105f,%eax
400525: 55 push %rbp
400526: 48 2d 58 10 60 00 sub $0x601058,%rax
40052c: 48 83 f8 0e cmp $0xe,%rax
400530: 48 89 e5 mov %rsp,%rbp
400533: 76 1b jbe 400550
400535: b8 00 00 00 00 mov $0x0,%eax
40053a: 48 85 c0 test %rax,%rax
40053d: 74 11 je 400550
40053f: 5d pop %rbp
400540: bf 58 10 60 00 mov $0x601058,%edi
400545: ff e0 jmpq *%rax
400547: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
40054e: 00 00
400550: 5d pop %rbp
400551: c3 retq
400552: 0f 1f 40 00 nopl 0x0(%rax)
400556: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40055d: 00 00 00
0000000000400560 :
400560: be 58 10 60 00 mov $0x601058,%esi
400565: 55 push %rbp
400566: 48 81 ee 58 10 60 00 sub $0x601058,%rsi
40056d: 48 c1 fe 03 sar $0x3,%rsi
400571: 48 89 e5 mov %rsp,%rbp
400574: 48 89 f0 mov %rsi,%rax
400577: 48 c1 e8 3f shr $0x3f,%rax
40057b: 48 01 c6 add %rax,%rsi
40057e: 48 d1 fe sar %rsi
400581: 74 15 je 400598
400583: b8 00 00 00 00 mov $0x0,%eax
400588: 48 85 c0 test %rax,%rax
40058b: 74 0b je 400598
40058d: 5d pop %rbp
40058e: bf 58 10 60 00 mov $0x601058,%edi
400593: ff e0 jmpq *%rax
400595: 0f 1f 00 nopl (%rax)
400598: 5d pop %rbp
400599: c3 retq
40059a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
00000000004005a0 <__do_global_dtors_aux>:
4005a0: 80 3d ad 0a 20 00 00 cmpb $0x0,0x200aad(%rip) # 601054 <_edata>
4005a7: 75 11 jne 4005ba <__do_global_dtors_aux+0x1a>
4005a9: 55 push %rbp
4005aa: 48 89 e5 mov %rsp,%rbp
4005ad: e8 6e ff ff ff callq 400520
4005b2: 5d pop %rbp
4005b3: c6 05 9a 0a 20 00 01 movb $0x1,0x200a9a(%rip) # 601054 <_edata>
4005ba: f3 c3 repz retq
4005bc: 0f 1f 40 00 nopl 0x0(%rax)
00000000004005c0 :
4005c0: bf 20 0e 60 00 mov $0x600e20,%edi
4005c5: 48 83 3f 00 cmpq $0x0,(%rdi)
4005c9: 75 05 jne 4005d0
4005cb: eb 93 jmp 400560
4005cd: 0f 1f 00 nopl (%rax)
4005d0: b8 00 00 00 00 mov $0x0,%eax
4005d5: 48 85 c0 test %rax,%rax
4005d8: 74 f1 je 4005cb
4005da: 55 push %rbp
4005db: 48 89 e5 mov %rsp,%rbp
4005de: ff d0 callq *%rax
4005e0: 5d pop %rbp
4005e1: e9 7a ff ff ff jmpq 400560
00000000004005e6 :
4005e6: 55 push %rbp
4005e7: 48 89 e5 mov %rsp,%rbp
4005ea: 48 83 ec 30 sub $0x30,%rsp
4005ee: 89 7d dc mov %edi,-0x24(%rbp)
4005f1: 48 89 75 d0 mov %rsi,-0x30(%rbp)
4005f5: 48 8d 45 fc lea -0x4(%rbp),%rax
4005f9: 48 89 c6 mov %rax,%rsi
4005fc: bf 68 07 40 00 mov $0x400768,%edi
400601: b8 00 00 00 00 mov $0x0,%eax
400606: e8 95 fe ff ff callq 4004a0
40060b: c7 45 fc 20 00 00 00 movl $0x20,-0x4(%rbp)
400612: 48 8d 45 fc lea -0x4(%rbp),%rax
400616: 48 89 c6 mov %rax,%rsi
400619: bf 90 07 40 00 mov $0x400790,%edi
40061e: b8 00 00 00 00 mov $0x0,%eax
400623: e8 78 fe ff ff callq 4004a0
400628: be 50 10 60 00 mov $0x601050,%esi
40062d: bf b8 07 40 00 mov $0x4007b8,%edi
400632: b8 00 00 00 00 mov $0x0,%eax
400637: e8 64 fe ff ff callq 4004a0
40063c: 48 8d 45 f0 lea -0x10(%rbp),%rax
400640: 48 89 c6 mov %rax,%rsi
400643: bf e0 07 40 00 mov $0x4007e0,%edi
400648: b8 00 00 00 00 mov $0x0,%eax
40064d: e8 4e fe ff ff callq 4004a0
400652: bf 0a 00 00 00 mov $0xa,%edi
400657: e8 74 fe ff ff callq 4004d0
40065c: 48 89 45 f0 mov %rax,-0x10(%rbp)
400660: 48 8b 45 f0 mov -0x10(%rbp),%rax
400664: 48 89 c6 mov %rax,%rsi
400667: bf 03 08 40 00 mov $0x400803,%edi
40066c: b8 00 00 00 00 mov $0x0,%eax
400671: e8 2a fe ff ff callq 4004a0
400676: 48 8b 45 f0 mov -0x10(%rbp),%rax
40067a: 48 ba 31 32 33 34 35 movabs $0x6969363534333231,%rdx
400681: 36 69 69
400684: 48 89 10 mov %rdx,(%rax)
400687: 66 c7 40 08 69 00 movw $0x69,0x8(%rax)
40068d: 48 8b 45 f0 mov -0x10(%rbp),%rax
400691: 48 89 c6 mov %rax,%rsi
400694: bf 1b 08 40 00 mov $0x40081b,%edi
400699: b8 00 00 00 00 mov $0x0,%eax
40069e: e8 fd fd ff ff callq 4004a0
4006a3: bf 39 08 40 00 mov $0x400839,%edi
4006a8: b8 00 00 00 00 mov $0x0,%eax
4006ad: e8 ee fd ff ff callq 4004a0
4006b2: 48 8d 45 ef lea -0x11(%rbp),%rax
4006b6: 48 89 c6 mov %rax,%rsi
4006b9: bf 4b 08 40 00 mov $0x40084b,%edi
4006be: b8 00 00 00 00 mov $0x0,%eax
4006c3: e8 18 fe ff ff callq 4004e0 <__isoc99_scanf@plt>
4006c8: 0f b6 45 ef movzbl -0x11(%rbp),%eax
4006cc: 3c 59 cmp $0x59,%al
4006ce: 75 07 jne 4006d7
4006d0: b8 00 00 00 00 mov $0x0,%eax
4006d5: eb 05 jmp 4006dc
4006d7: b8 00 00 00 00 mov $0x0,%eax
4006dc: c9 leaveq
4006dd: c3 retq
4006de: 66 90 xchg %ax,%ax
00000000004006e0 <__libc_csu_init>:
4006e0: 41 57 push %r15
4006e2: 41 89 ff mov %edi,%r15d
4006e5: 41 56 push %r14
4006e7: 49 89 f6 mov %rsi,%r14
4006ea: 41 55 push %r13
4006ec: 49 89 d5 mov %rdx,%r13
4006ef: 41 54 push %r12
4006f1: 4c 8d 25 18 07 20 00 lea 0x200718(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry>
4006f8: 55 push %rbp
4006f9: 48 8d 2d 18 07 20 00 lea 0x200718(%rip),%rbp # 600e18 <__init_array_end>
400700: 53 push %rbx
400701: 4c 29 e5 sub %r12,%rbp
400704: 31 db xor %ebx,%ebx
400706: 48 c1 fd 03 sar $0x3,%rbp
40070a: 48 83 ec 08 sub $0x8,%rsp
40070e: e8 55 fd ff ff callq 400468 <_init>
400713: 48 85 ed test %rbp,%rbp
400716: 74 1e je 400736 <__libc_csu_init+0x56>
400718: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
40071f: 00
400720: 4c 89 ea mov %r13,%rdx
400723: 4c 89 f6 mov %r14,%rsi
400726: 44 89 ff mov %r15d,%edi
400729: 41 ff 14 dc callq *(%r12,%rbx,8)
40072d: 48 83 c3 01 add $0x1,%rbx
400731: 48 39 eb cmp %rbp,%rbx
400734: 75 ea jne 400720 <__libc_csu_init+0x40>
400736: 48 83 c4 08 add $0x8,%rsp
40073a: 5b pop %rbx
40073b: 5d pop %rbp
40073c: 41 5c pop %r12
40073e: 41 5d pop %r13
400740: 41 5e pop %r14
400742: 41 5f pop %r15
400744: c3 retq
400745: 90 nop
400746: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40074d: 00 00 00
0000000000400750 <__libc_csu_fini>:
400750: f3 c3 repz retq
Disassembly of section .fini:
0000000000400754 <_fini>:
400754: 48 83 ec 08 sub $0x8,%rsp
400758: 48 83 c4 08 add $0x8,%rsp
40075c: c3 retq
运行过程不退出,查看程序运行中的虚拟内存
[root@dsmart=>OTHER_C]$./Vmaddres.exe
变量i的定义时地址是:0x7fffffffe04c
变量i赋值后的地址是:0x7fffffffe04c
全局静态变量G的地址: 0x601050
pChar内存变量本身地址: 0x7fffffffe040
动态分配地址: 0x602010
使用动态分配地址: 0x602010
是否退出? Y/N
另外个SSH窗口
[root@dsmart=>~]$ps -ef | grep Vmaddres.exe
root 9743 12107 0 15:27 pts/3 00:00:00 ./Vmaddres.exe
root 9771 31251 0 15:28 pts/1 00:00:00 grep --color Vmaddres.exe
查看进程MAPS
[root@dsmart=>~]$cat /proc/9743/maps
00400000-00401000 r-xp 00000000 fd:02 16520679 /home/Project/OTHER_C/Vmaddres.exe
00600000-00601000 r--p 00000000 fd:02 16520679 /home/Project/OTHER_C/Vmaddres.exe
00601000-00602000 rw-p 00001000 fd:02 16520679 /home/Project/OTHER_C/Vmaddres.exe
00602000-00623000 rw-p 00000000 00:00 0 [heap]
7ffff7a0d000-7ffff7bd1000 r-xp 00000000 fd:00 37765873 /usr/lib64/libc-2.17.so
7ffff7bd1000-7ffff7dd0000 ---p 001c4000 fd:00 37765873 /usr/lib64/libc-2.17.so
7ffff7dd0000-7ffff7dd4000 r--p 001c3000 fd:00 37765873 /usr/lib64/libc-2.17.so
7ffff7dd4000-7ffff7dd6000 rw-p 001c7000 fd:00 37765873 /usr/lib64/libc-2.17.so
7ffff7dd6000-7ffff7ddb000 rw-p 00000000 00:00 0
7ffff7ddb000-7ffff7dfd000 r-xp 00000000 fd:00 37765866 /usr/lib64/ld-2.17.so
7ffff7fea000-7ffff7fed000 rw-p 00000000 00:00 0
7ffff7ff7000-7ffff7ffa000 rw-p 00000000 00:00 0
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00021000 fd:00 37765866 /usr/lib64/ld-2.17.so
7ffff7ffd000-7ffff7ffe000 rw-p 00022000 fd:00 37765866 /usr/lib64/ld-2.17.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
变量i的定义时地址是:0x7fffffffe04c 居然在上面最后地址范围内.
7ffffffde000-7ffffffff000 rw-p 0000000000:000 [stack]
意思如下:
开始-结束 00400000-00401000
访问权限 r-xp
偏移 00000000
主设备号:次设备号 fd:02
i节点 16520679
文件 /home/Project/OTHER_C/Vmaddres.exe
前三段虚拟内存地址范围,跟静态地址一样!
使用GDB 运行反汇编
对C程序添加调试信息 -g 进行编译
[root@dsmart=>OTHER_C]$gdb vmaddres.exe
下面这行表示读到额调试信息
Reading symbols from /home/Project/OTHER_C/vmaddres.exe...done.
查看源码
(gdb) list
1 #include
2 #include
3 #include
4 /* run this program using the console pauser or add your own getch, system("pause") or input loop */
5 int g=78;
6
7 int main(int argc, char *argv[])
8 {
9 int i;
10 printf("变量i的定义时地址是:%p\n", &i);
在第一行打上断点,然后运行
(gdb) b 1
Breakpoint 1 at 0x4005f5: file VmAddres.c, line 1.
(gdb) run
Starting program: /home/Project/OTHER_C/vmaddres.exe
Breakpoint 1, main (argc=1, argv=0x7fffffffe128) at VmAddres.c:10
10 printf("变量i的定义时地址是:%p\n", &i);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64
输入反汇编命令
(gdb) disas
Dump of assembler code for function main:
0x00000000004005e6 <+0>: push %rbp
0x00000000004005e7 <+1>: mov %rsp,%rbp
0x00000000004005ea <+4>: sub $0x30,%rsp
0x00000000004005ee <+8>: mov %edi,-0x24(%rbp)
0x00000000004005f1 <+11>: mov %rsi,-0x30(%rbp)
=> 0x00000000004005f5 <+15>: lea -0x4(%rbp),%rax
0x00000000004005f9 <+19>: mov %rax,%rsi
0x00000000004005fc <+22>: mov $0x400768,%edi
0x0000000000400601 <+27>: mov $0x0,%eax
0x0000000000400606 <+32>: callq 0x4004a0
0x000000000040060b <+37>: movl $0x20,-0x4(%rbp)
0x0000000000400612 <+44>: lea -0x4(%rbp),%rax
0x0000000000400616 <+48>: mov %rax,%rsi
0x0000000000400619 <+51>: mov $0x400790,%edi
0x000000000040061e <+56>: mov $0x0,%eax
0x0000000000400623 <+61>: callq 0x4004a0
0x0000000000400628 <+66>: mov $0x601050,%esi
0x000000000040062d <+71>: mov $0x4007b8,%edi
0x0000000000400632 <+76>: mov $0x0,%eax
0x0000000000400637 <+81>: callq 0x4004a0
0x000000000040063c <+86>: lea -0x10(%rbp),%rax
0x0000000000400640 <+90>: mov %rax,%rsi
0x0000000000400643 <+93>: mov $0x4007e0,%edi
0x0000000000400648 <+98>: mov $0x0,%eax
0x000000000040064d <+103>: callq 0x4004a0
0x0000000000400652 <+108>: mov $0xa,%edi
0x0000000000400657 <+113>: callq 0x4004d0
0x000000000040065c <+118>: mov %rax,-0x10(%rbp)
0x0000000000400660 <+122>: mov -0x10(%rbp),%rax
0x0000000000400664 <+126>: mov %rax,%rsi
0x0000000000400667 <+129>: mov $0x400803,%edi
0x000000000040066c <+134>: mov $0x0,%eax
0x0000000000400671 <+139>: callq 0x4004a0
0x0000000000400676 <+144>: mov -0x10(%rbp),%rax
0x000000000040067a <+148>: movabs $0x6969363534333231,%rdx
0x0000000000400684 <+158>: mov %rdx,(%rax)
0x0000000000400687 <+161>: movw $0x69,0x8(%rax)
0x000000000040068d <+167>: mov -0x10(%rbp),%rax
0x0000000000400691 <+171>: mov %rax,%rsi
0x0000000000400694 <+174>: mov $0x40081b,%edi
0x0000000000400699 <+179>: mov $0x0,%eax
0x000000000040069e <+184>: callq 0x4004a0
0x00000000004006a3 <+189>: mov $0x400839,%edi
0x00000000004006a8 <+194>: mov $0x0,%eax
0x00000000004006ad <+199>: callq 0x4004a0
0x00000000004006b2 <+204>: lea -0x11(%rbp),%rax
0x00000000004006b6 <+208>: mov %rax,%rsi
0x00000000004006b9 <+211>: mov $0x40084b,%edi
0x00000000004006be <+216>: mov $0x0,%eax
0x00000000004006c3 <+221>: callq 0x4004e0 <__isoc99_scanf@plt>
0x00000000004006c8 <+226>: movzbl -0x11(%rbp),%eax
0x00000000004006cc <+230>: cmp $0x59,%al
0x00000000004006ce <+232>: jne 0x4006d7
0x00000000004006d0 <+234>: mov $0x0,%eax
0x00000000004006d5 <+239>: jmp 0x4006dc
0x00000000004006d7 <+241>: mov $0x0,%eax
0x00000000004006dc <+246>: leaveq
0x00000000004006dd <+247>: retq
End of assembler dump.
跟静态反汇编OBJDUMP 0x00000000004005e6 一致!
最后很大可能是 64程序逻辑地址,就是虚拟地址,也是进程虚拟地址,也是按照页表格式构成的虚拟地址. 那么物理地址偏移量,可能大概率是虚拟地址4K页,页内偏移量.
很大可能页表是稀疏的,存在很多空洞PTE 这类浪费内存的现象.
本文没有得出精准的答案,只是看了那么多公号文,问了些大佬,大佬也没有给出明确的答案
我讲东,他们讲西,不在一个频道上. 他们不理解我的疑惑, 也许只能去看,去调试LINUX 内核代码,看LINUX如何加载可执行文件,给它分配虚拟内存地址空间!
喜欢可以扫描上面的公众号二维码,优先观看