Readelf找到绝对地址

时间:2016-03-13 08:51:28

标签: linker readelf

我有一个C程序,它有一个全局变量和一个局部变量。我的问题在于readelf。以下是我的问题; 1.当我使用“readelf --symbols”获取地址转储时,我得到的全局变量的地址与我运行程序时打印的地址相同。在我的程序运行或加载之前,readelf如何知道绝对地址? 2.为什么局部变量符号没有信息?我只能看到全局变量的符号。

1 个答案:

答案 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_istatic_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_istatic_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

这应该可以解释为什么你没有看到任何“本地”符号。你是自动的 变量永远不会出现在符号表中。你的静态变量只在 符号表,如果您已禁用所有优化。