C函数运行时地址

竹影半墙 2018-09-14 05:39:29
/*
* gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)
*/

#include <stdio.h>

int main(void)
{
return printf("main=%p\n", main);
}


gcc main.c -o main
./main
main=0x55e780f1164a

./main
main=0x55cf8b90c64a

./main
main=0x56484d6e864a


各位路过的大神:
为什么main在不同的运行中 地址会不一样呢

附:
[1]
----------------------------------------------------------------------
ld --verbose
GNU ld (GNU Binutils for Ubuntu) 2.30
......
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;


[2] /* 这里表达 跟0x400000 无关?*/
-------------------------------------------------------------
readelf -h main
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: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x540
Start of program headers: 64 (bytes into file)
Start of section headers: 6440 (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

objdump -ds main
000000000000064a <main>:
64a: 55 push %rbp
64b: 48 89 e5 mov %rsp,%rbp
64e: 48 8d 35 f5 ff ff ff lea -0xb(%rip),%rsi # 64a <main>
655: 48 8d 3d 98 00 00 00 lea 0x98(%rip),%rdi # 6f4 <_IO_stdin_used+0x4>
65c: b8 00 00 00 00 mov $0x0,%eax
661: e8 ba fe ff ff callq 520 <printf@plt>
666: 5d pop %rbp
667: c3 retq
668: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
66f: 00


[3]
_________________________________________________
addr2line -e main 0x55e780f1164a -f
??
??:0
addr2line -e main 64a -f
main
??:?
...全文
776 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
短笛小魔王 2018-10-01
  • 打赏
  • 举报
回复
引用 6 楼 zxc024000 的回复:
Ubuntun gcc5.4,尝试了一下上述程序。输出的main地址,以及objdump出的地址,都是统一的。

这类东西,应该跟编译器(g++/gcc)自身有关。比如clang和gcc/g++,对c++的优化就有很多差别。

建议看看gcc7列出的改动的地方吧。
https://gcc.gnu.org/gcc-7/changes.html

挺好的,不错可以看看。
竹影半墙 2018-09-27
  • 打赏
  • 举报
回复
引用 6 楼 zxc024000 的回复:
Ubuntun gcc5.4,尝试了一下上述程序。输出的main地址,以及objdump出的地址,都是统一的。

这类东西,应该跟编译器(g++/gcc)自身有关。比如clang和gcc/g++,对c++的优化就有很多差别。

建议看看gcc7列出的改动的地方吧。
https://gcc.gnu.org/gcc-7/changes.html
附加的链接资源不错
  • 打赏
  • 举报
回复
跟操作系统有关,较新的操作系统普遍使用一种安全技术,称之为 Address Space Layout Randomization (ASLR),每次加载可执行文件(.exe、.dll之类的)都放在一个随机起始地址,甚至操作系统核心,每次启动时也加载到随机地址(都是一个范围,不是任意的),而不是固定地址。这样做是为了防止恶意程序针对缺陷代码进行攻击。
林多 2018-09-26
  • 打赏
  • 举报
回复
Ubuntun gcc5.4,尝试了一下上述程序。输出的main地址,以及objdump出的地址,都是统一的。

这类东西,应该跟编译器(g++/gcc)自身有关。比如clang和gcc/g++,对c++的优化就有很多差别。

建议看看gcc7列出的改动的地方吧。
https://gcc.gnu.org/gcc-7/changes.html
竹影半墙 2018-09-26
  • 打赏
  • 举报
回复
引用 7 楼 DelphiGuy 的回复:
跟操作系统有关,较新的操作系统普遍使用一种安全技术,称之为 Address Space Layout Randomization (ASLR),每次加载可执行文件(.exe、.dll之类的)都放在一个随机起始地址,甚至操作系统核心,每次启动时也加载到随机地址(都是一个范围,不是任意的),而不是固定地址。这样做是为了防止恶意程序针对缺陷代码进行攻击。

addr2line版本没跟上?
赵4老师 2018-09-26
  • 打赏
  • 举报
回复
引用 7 楼 DelphiGuy 的回复:
跟操作系统有关,较新的操作系统普遍使用一种安全技术,称之为 Address Space Layout Randomization (ASLR),每次加载可执行文件(.exe、.dll之类的)都放在一个随机起始地址,甚至操作系统核心,每次启动时也加载到随机地址(都是一个范围,不是任意的),而不是固定地址。这样做是为了防止恶意程序针对缺陷代码进行攻击。

防君子防不了小人;
防菜鸟防不了大神。
六道佩恩 2018-09-25
  • 打赏
  • 举报
回复
可以了解下虚拟地址
竹影半墙 2018-09-16
  • 打赏
  • 举报
回复
引用 3 楼 misskissC 的回复:
[quote=引用 2 楼 misskissC 的回复:]
[quote=引用 1 楼 sdsszk 的回复:]
这种地址是随机的
我的疑问:
[1] 跟 附 中的内容还是有关系的哈。虚拟地址是随机的完全可以被理解,问题在于 跟其配套的addr2line没法使用该随机地址。
[2] 期待您给结论附个原因

另外,比如在centos上,就不存在这个问题。
/* gcc version 4.8.5 (Red Hat 4.8.5-28) */
#include <stdio.h>

int main(void)
{
return printf("main=%p\n", main);
}


gcc main.c -o main
./main
0x40051d

./main
0x40051d

./main
0x40051d

objdump -ds main
000000000040051d <main>:
....

addr2line -e main 0x40051d -f
main
??:?

[/quote]

Linux下查看 进程 虚拟地址空间:

#include <stdio.h>

int main(void)
{
printf("main=%p\n", main);
while (1);
return 0;
}


gcc vaddr.c -o vaddr
./vaddr &
main=0x55be8d47264a
[1] 1798

cat /proc/1798/maps
55be8d472000-55be8d473000 r-xp 00000000 08:01 264241 /home/lgt/workspace/vaddr/vaddr
55be8d672000-55be8d673000 r--p 00000000 08:01 264241 /home/lgt/workspace/vaddr/vaddr
55be8d673000-55be8d674000 rw-p 00001000 08:01 264241 /home/lgt/workspace/vaddr/vaddr
55be8d963000-55be8d984000 rw-p 00000000 00:00 0 [heap]
7f1c8e21e000-7f1c8e405000 r-xp 00000000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e405000-7f1c8e605000 ---p 001e7000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e605000-7f1c8e609000 r--p 001e7000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e609000-7f1c8e60b000 rw-p 001eb000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e60b000-7f1c8e60f000 rw-p 00000000 00:00 0
7f1c8e60f000-7f1c8e636000 r-xp 00000000 08:01 1185732 /lib/x86_64-linux-gnu/ld-2.27.so
7f1c8e822000-7f1c8e824000 rw-p 00000000 00:00 0
7f1c8e836000-7f1c8e837000 r--p 00027000 08:01 1185732 /lib/x86_64-linux-gnu/ld-2.27.so
7f1c8e837000-7f1c8e838000 rw-p 00028000 08:01 1185732 /lib/x86_64-linux-gnu/ld-2.27.so
7f1c8e838000-7f1c8e839000 rw-p 00000000 00:00 0
7ffe47da3000-7ffe47dc4000 rw-p 00000000 00:00 0 [stack]
7ffe47dd7000-7ffe47dda000 r--p 00000000 00:00 0 [vvar]
7ffe47dda000-7ffe47ddc000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

killall -9 vaddr[/quote]

自己根据/proc/pid/maps写一个 根据虚拟地址 得到进程 在该地址上函数名吧
竹影半墙 2018-09-16
  • 打赏
  • 举报
回复
引用 2 楼 misskissC 的回复:
[quote=引用 1 楼 sdsszk 的回复:]
这种地址是随机的
我的疑问:
[1] 跟 附 中的内容还是有关系的哈。虚拟地址是随机的完全可以被理解,问题在于 跟其配套的addr2line没法使用该随机地址。
[2] 期待您给结论附个原因

另外,比如在centos上,就不存在这个问题。
/* gcc version 4.8.5 (Red Hat 4.8.5-28) */
#include <stdio.h>

int main(void)
{
return printf("main=%p\n", main);
}


gcc main.c -o main
./main
0x40051d

./main
0x40051d

./main
0x40051d

objdump -ds main
000000000040051d <main>:
....

addr2line -e main 0x40051d -f
main
??:?

[/quote]

Linux下查看 进程 虚拟地址空间:

#include <stdio.h>

int main(void)
{
printf("main=%p\n", main);
while (1);
return 0;
}


gcc vaddr.c -o vaddr
./vaddr &
main=0x55be8d47264a
[1] 1798

cat /proc/1798/maps
55be8d472000-55be8d473000 r-xp 00000000 08:01 264241 /home/lgt/workspace/vaddr/vaddr
55be8d672000-55be8d673000 r--p 00000000 08:01 264241 /home/lgt/workspace/vaddr/vaddr
55be8d673000-55be8d674000 rw-p 00001000 08:01 264241 /home/lgt/workspace/vaddr/vaddr
55be8d963000-55be8d984000 rw-p 00000000 00:00 0 [heap]
7f1c8e21e000-7f1c8e405000 r-xp 00000000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e405000-7f1c8e605000 ---p 001e7000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e605000-7f1c8e609000 r--p 001e7000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e609000-7f1c8e60b000 rw-p 001eb000 08:01 1185760 /lib/x86_64-linux-gnu/libc-2.27.so
7f1c8e60b000-7f1c8e60f000 rw-p 00000000 00:00 0
7f1c8e60f000-7f1c8e636000 r-xp 00000000 08:01 1185732 /lib/x86_64-linux-gnu/ld-2.27.so
7f1c8e822000-7f1c8e824000 rw-p 00000000 00:00 0
7f1c8e836000-7f1c8e837000 r--p 00027000 08:01 1185732 /lib/x86_64-linux-gnu/ld-2.27.so
7f1c8e837000-7f1c8e838000 rw-p 00028000 08:01 1185732 /lib/x86_64-linux-gnu/ld-2.27.so
7f1c8e838000-7f1c8e839000 rw-p 00000000 00:00 0
7ffe47da3000-7ffe47dc4000 rw-p 00000000 00:00 0 [stack]
7ffe47dd7000-7ffe47dda000 r--p 00000000 00:00 0 [vvar]
7ffe47dda000-7ffe47ddc000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

killall -9 vaddr
竹影半墙 2018-09-14
  • 打赏
  • 举报
回复
引用 1 楼 sdsszk 的回复:
这种地址是随机的
我的疑问:
[1] 跟 附 中的内容还是有关系的哈。虚拟地址是随机的完全可以被理解,问题在于 跟其配套的addr2line没法使用该随机地址。
[2] 期待您给结论附个原因

另外,比如在centos上,就不存在这个问题。
/* gcc version 4.8.5 (Red Hat 4.8.5-28) */
#include <stdio.h>

int main(void)
{
return printf("main=%p\n", main);
}


gcc main.c -o main
./main
0x40051d

./main
0x40051d

./main
0x40051d

objdump -ds main
000000000040051d <main>:
....

addr2line -e main 0x40051d -f
main
??:?

sdsszk 2018-09-14
  • 打赏
  • 举报
回复
这种地址是随机的

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧