在以前的GCC版本中,objdump
报告的符号偏移与实际执行代码期间使用的符号偏移相匹配。例如:
$ cat example.c
#include <stdio.h>
int g_someGlobal = 0;
int main()
{
printf("%d\n", g_someGlobal);
return 0;
}
$ gcc-6 -v
...
gcc version 6.1.1 20160802 (Debian 6.1.1-11)
$ gcc-6 -O0 -g -o example example.c
$ objdump -x example | grep Global
...
080496f4 g O .bss 00000004 g_someGlobal
...
实际上,在运行二进制文件时,执行期间使用的符号的实际地址与objdump报告的地址相同:
$ gdb ./example
...
(gdb) start
Temporary breakpoint 1, main () at example.c:10
10 printf("%d\n", g_someGlobal);
(gdb) p/x &g_someGlobal
$1 = 0x80496f4
不幸的是,在最近发布的Debian Stretch中重复相同的命令序列,反而发生了这种情况:
$ gcc-6 -v
...
gcc version 6.3.0 20170415 (Debian 6.3.0-14)
$ gcc-6 -O0 -g -o example example.c
$ objdump -x example | grep Global
00002020 g O .bss 00000004 g_someGlobal
符号偏移现在似乎是一个小得多的值 - ...
$ gdb ./example
...
(gdb) start
...
Temporary breakpoint 1, main () at example.c:7
7 printf("%d\n", g_someGlobal);
(gdb) p/x &g_someGlobal
$1 = 0x80002020
...不再与运行时使用的那个匹配。
我在这里弄错了吗?在此期间,工具的使用是否发生了变化?如果没有,这种变化背后的原因是什么?
无论如何 - 理论上必须有一种方法可以获得托管变量的.bss段的“预期运行时间偏移”(objdump
会报告它将放入哪个部分,所以最终可以通过添加.bss
偏移量来计算运行时位置。在我的初步尝试中,我还没有找到办法解决这个问题:
$ readelf --sections example | grep bss
[26] .bss NOBITS 0000201c 00101c 000008 00 WA 0 0 4
这似乎没有报告0x80000000的“转移”似乎发生在.bss
- 此示例中的托管变量。
(即使这是这个新执行环境的“神奇常数”,这也适用于.data
变量吗?说实话,我讨厌神奇的价值 - 以前,无论来了什么objdump -x
中的objdump -x
是准确的,无论符号位于何处......)
任何解决此问题的信息都非常受欢迎。理想情况下,我想重现.category{
height: 70px !important;
width: 28% !important;
margin: 0 10px 0 10px;
border: 1px solid #3A94D7;
border-radius: 15px;
box-shadow: 0 0 15px 1px rgba(0,0,0,.75), inset 0 0 2px 0 #4293D5;
}
.icon-steam{
background: url(../img/steam.png) 50% 50% no-repeat;
background-size: 40px;
float: left;
width: 40px;
height: 40px;
margin-right: 0.3em;
}
.platform{
text-shadow: none;
color: #65a1bf;
left:14%;
top:60px;
position: absolute;
}
的旧行为 - 即静态(不是在运行时)从承载它的ELF获取符号的运行时地址的值。
更新:我做了GCC7.1.0的自定义编译(来自源代码),这不再可重现。也许这是GCC 6.3(Debian Stretch中打包的版本)的回归......
答案 0 :(得分:3)
原因是Debian的gcc包是用--enable-default-pie
构建的。在PIE可执行文件中,ELF段可以以任意(只要它正确对齐)基址加载,通常由加载器随机选择。您在ELF文件中看到的符号地址是相对于其加载的基址的偏移量,而不是绝对虚拟地址。
如果您不想要/不需要PIE,可以添加-no-pie
链接命令行以获取您已经习惯的链接时确定的地址。