【问题标题】:Extract global variables from a.out file从 a.out 文件中提取全局变量
【发布时间】:2012-06-12 19:20:08
【问题描述】:

编辑(更新问题)

我有一个简单的 C 程序:

   // it is not important to know what the code does you may skip the code 

ma​​in.c

#include <bsp.h>

unsigned int   AppCtr;
unsigned char  AppFlag;
int SOME_LARGE_VARIABLE;

static  void  AppTest (void);

void  main (void)
{
    AppCtr  = 0;
    AppFlag = 0;        
    AppTest();
}

static void Foo(void){
    SOME_LARGE_VARIABLE=15; 
}


static  void  AppTest (void)
{
    unsigned int  i;
    i = 0;
    while (i < 200000) {
        i++;
    }

    BSP_Test();      
    SOME_LARGE_VARIABLE=3;    
    Foo();
}

bsp.c

extern int SOME_LARGE_VARIABLE;
extern unsigned char  AppFlag;

unsigned int long My_GREAT_COUNTER;

void  BSP_Test (void) {
  SOME_LARGE_VARIABLE = 5;
  My_GREAT_COUNTER = 4;
}

(程序没有做任何有用的事情......我的目标是提取变量名,它们被声明的位置和它们的内存地址

当我编译程序时,我得到文件a.out,这是一个包含调试信息的elf文件。

公司有人在 5 年前在 .net 中编写了一个程序,该程序将从 a.out 文件中获取所有这些信息。这是代码返回的内容:

   //  Name          Display Name                    Type      Size     Address

对于这个小程序来说效果很好,也适用于其他大型项目。

该代码有 2000 行长,有几个错误,它不支持 .NET 版本 4。这就是我尝试重新创建它的原因。


所以我的问题是,我很迷茫,我不知道要采取什么方法来解决这个问题。这些是我一直在考虑的选项:

  1. 整理我在第一张图片上显示的程序的错误代码,并尝试查看它的作用以及它如何解析 a.out 文件以获取该信息。一旦我完全理解它,试着找出它为什么不支持版本 3 和 4。

  2. 我可以创建正则表达式,所以可以尝试通过执行以下操作在 a.out 文件中查找模式: 到目前为止,我能够找到只有一个文件的模式(main.c)。但是当有多个文件时,它会变得更加复杂。我还没试过。或许它不会那么复杂,并且可以找到模式。

  3. 安装Cygwin 这样我就可以在Windows 上使用Linux 命令,例如objdumpnmelfread。当我使用诸如readelf -w a.out 之类的命令时,我对这些命令的使用还不够,我得到了我需要的更多信息。我没有花太多时间使用这种方法有一些缺点:

    • 缺点:在 Windows 上安装 cygwin 需要一些时间,并且在将此应用程序提供给我们的客户时,我们不希望他们必须安装它。也许有一种方法可以只安装命令 objdump 和 elfread 而不必安装整个东西

    • 优点:如果我们找到正确的命令来使用,我们将不会重新发明轮子并节省一些时间。可能是解析objdump -w a.out等命令结果的问题


如果您想下载 a.out 文件以解析它here it is


总结

我将能够获取 a.out 文件中的全局变量。我想知道每个变量是什么类型(int、char、..),它们有什么内存地址,我还想知道在哪个文件上声明了变量(main.c 或 someOtherFile.c)。如果我不必使用 cygwin,我将不胜感激,因为这将使其更易于部署。 由于这个问题要求很多,我试图将其拆分为更多:

也许我应该删除其他问题。很抱歉是多余的。

【问题讨论】:

  • 您的目标是获取全局变量列表吗?还是从 a.out 文件中获取全局变量?还是要修复您拥有的工具?显然,如果有多个编译单元,则查看 one a.out 文件不会为您提供所有全局变量的列表。
  • ... 您的大部分麻烦似乎还在于对目标文件格式缺乏了解。如果你不愿意投入足够的时间去理解它,你怎么期望得到一个好的结果?
  • a.out 文件包含 dwarf 信息(调试信息)。我知道并非所有 a.out 文件都包含此信息。抱歉没有提到......
  • 它看起来像stackoverflow.com/questions/6082950/…的副本

标签: gcc compiler-construction cygwin elf dwarf


【解决方案1】:

这就是我要做的。为什么要重新发明轮子!

  1. here.下载windows上需要的linux命令

    在 bin 目录上应该有:readelf.exe

    请注意,我们不需要 Cygwin 或任何程序,因此部署很简单!

  2. 一旦我们在 cmd 中执行该文件:

    // cd "path where readelf.exe is"
    readelf.exe -s a.out
    

    这是即将发布的列表:

    因此,如果您看一下,我们有兴趣获取所有大小大于 0 的 OBJECT 类型的变量。

  3. 1234563请注意,在顶部我们知道变量被声明的位置,我们得到了更多信息,例如声明它的行和内存地址
  4. 我们缺少做的最后一件事是获取类型。如果你看一下,我们会看到类型是 = 。这意味着我们必须前往树的 522 以获取有关该时间的更多信息。如果我们去那部分,我们会得到: 通过查看树,我们知道 SOME_LARGE_VARIABLE 是 unsigned long 类型

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多