Readelf 查找绝对地址

Readelf finding absolute address

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

How readelf can know the absolute address before my programme is running or been loaded?

因为当 linker 完成工作时,计算的地址是 你的全局变量 程序加载器将在的地址 必须在运行时放置该变量。 linker 的工作主要是 将信息放入 executable 中,告诉程序加载器在哪里 符号将映射到内存中。

Why there are no informations on the local variables' symbols

你的程序中可能存在三种"local"变量。

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的自动变量 每次程序进入定义它的块,然后停止存在 然后它离开那个块。这样的变量在executable中不占用存储空间 所以它没有在符号 table.

中表示

static_filescope_i 这样的变量通常被称为 static global, 以区别于 static_local_istatic_local_i 不能 在定义它的块之外可以看到。 static_filescope_i可以 可以在同一目标文件 (main.o) 中定义的任何函数中看到,但是 不在任何其他目标文件中:它在 main.o 中是 global 但是 在整个程序中本地 目标文件

static_filescope_istatic_local_i都必须有自己的 程序第一次使用变量时的初始值,然后保持 它具有的任何值,或分配给它的任何新值,直到下一次 它被使用 - 跨函数调用,直到程序结束。这表示 这些变量需要存储在 executable 中,而不是堆栈中,它们 可能是也可能不是 用符号 table.

表示

global_i,当然对整个程序来说是全局的:可以在 main.o 以及我们可能 link 和 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表示可以被linker看到,LOCAL表示不可见 由 linker.

因此,为了 linking main.o 与任何其他目标文件或库的目的 制作一个 executable、static_filescope_istatic_local_i 也可以 不存在.

这并不意味着它们在目标文件中完全没有用。它们很有用 用于调试。它们对于调查静态的内容很有用 executable 的存储由,正如我们现在所做的那样。

但是它们对 linker 没有用,因此,如果您编译 main.c 进行任何优化 level > 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

这应该可以解释为什么您没有看到任何 "local" 符号。你的自动 变量永远不会出现在符号 table 中。您的静态变量仅在 符号 table 如果您已禁用所有优化。