我有一个C程序,它有一个全局变量和一个局部变量。我的问题在于readelf。以下是我的问题; 1.当我使用“readelf --symbols”获取地址转储时,我得到的全局变量的地址与我运行程序时打印的地址相同。在我的程序运行或加载之前,readelf如何知道绝对地址? 2.为什么局部变量符号没有信息?我只能看到全局变量的符号。
答案 0 :(得分:1)
在程序运行或加载之前,readelf如何知道绝对地址?
因为当链接器完成其工作时,计算的地址 您的全局变量是程序加载器的地址 必须在运行时放置该变量。链接器的工作主要是 将信息放入可执行文件中,告诉程序加载器在哪里 符号将被映射到内存中。
为什么局部变量'符号
没有信息
程序中可能有三种“本地”变量。
<强>的main.c 强>
static int static_filescope_i = 1;
int f()
{
static int static_local_i = 2;
return static_local_i;
}
int g()
{
int automatic_i = 3;
return automatic_i;
}
int global_i = 4;
int main()
{
return global_i + f() + g() + static_filescope_i;
}
在运行时在堆栈上创建类似automatic_local_i
的自动变量
每次程序进入定义它的块,并且不再存在
然后就离开那个街区。这样的变量在可执行文件中不占用存储空间
所以它没有在符号表中表示。
像static_filescope_i
这样的变量通常被称为静态全局,
区别于static_local_i
之类的。 static_local_i
不能
在定义它的区块之外看到。 static_filescope_i
可以
可以在同一个目标文件(main.o
)中定义的任何函数中看到但是
不在任何其他目标文件中:它是main.o
中的全局但是
整个程序中的到该目标文件。
static_filescope_i
和static_local_i
都必须拥有它
程序首次使用变量然后保留时的初始值
它拥有的任何价值,或分配给它的任何新值,直到下一次
它被用于 - 跨函数调用,直到程序结束。这意味着
这些变量需要存储在可执行文件中,而不是存储在堆栈中,而它们可能是也可能不是
在符号表中表示。
global_i
对整个计划来说是全球性的:它可以在中看到
main.o
以及我们可能与main.o
链接的任何其他文件。
如果我们使用默认选项(无优化)编译main.c
:
$ gcc -c main.c
然后我们找到:
$ readelf -s main.o | grep automatic_i
$
... automatic_i
没有符号。
$ readelf -s main.o | grep global_i
12: 0000000000000004 4 OBJECT GLOBAL DEFAULT 3 global_i
... global_i
的全局符号。
$ readelf -s main.o | grep static_filescope_i
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 static_filescope_i
... static_filescope_i
$ readelf -s main.o | grep static_local_i
6: 0000000000000008 4 OBJECT LOCAL DEFAULT 3 static_local_i.1833
...以及static_local_i
的本地符号,但具有范围区别
后缀附加。
此处,GLOBAL
表示链接器可以看到,而LOCAL
表示无法看到
由链接器。
因此,为了将main.o
与任何其他对象文件或库链接起来
要制作可执行文件,static_filescope_i
和static_local_i
也可以
不存在。
这并不意味着它们在目标文件中完全无用。它们很有用 用于调试。它们对于调查静态是有用的 正如我们现在所做的那样,可执行文件的存储由。
组成但它们对链接器没用,所以,如果你用任何优化编译main.c
等级&gt; 0然后编译器将假定您想要的对象代码不是
调试或调查的目的,不发出任何本地符号:
$ gcc -O1 -c main.c
$ readelf -s main.o | grep static_local_i
$ readelf -s main.o | grep static_filescope_i
$ readelf -s main.o | grep global_i
11: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 global_i
...仅剩global_i
。
这应该可以解释为什么你没有看到任何“本地”符号。你是自动的 变量永远不会出现在符号表中。你的静态变量只在 符号表,如果您已禁用所有优化。