【问题标题】:Readelf finding absolute addressReadelf查找绝对地址
【发布时间】:2016-03-13 08:51:27
【问题描述】:

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

【问题讨论】:

    标签: linker readelf


    【解决方案1】:

    readelf 如何在我的程序运行或加载之前知道绝对地址?

    因为当链接器完成它的工作时,为 您的全局变量程序加载器将在该地址 必须在运行时放置该变量。链接器的工作主要是 将信息放入一个可执行文件中,告诉程序加载器在哪里 符号将被映射到内存中。

    为什么没有关于局部变量符号的信息

    您的程序中可能存在三种“局部”变量。

    ma​​in.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 内是 global 但 在整个程序中本地到该目标文件

    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 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

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

    【讨论】:

    • 谢谢迈克。它澄清了我关于局部变量的第二个问题。但我的第一个问题仍然毫无疑问。如果我正在为另一台机器构建我的代码,我的本地链接器如何了解远程机器的内存结构。两个 macbines 中的全局变量地址打印相同,而本地变量地址不同。我注意到全局变量的地址打印为 6 位,但局部变量的地址为 12 位。是不是全局变量地址不是RAM的物理内存地址?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    相关资源
    最近更新 更多