我有一个简单的C程序:
// it is not important to know what the code does you may skip the code
的main.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
,这是一个包含调试信息的精灵文件。
该公司有人在5年前在.net上编写了一个程序,它将从a.out文件中获取所有这些信息。这是代码返回的内容:
// Name Display Name Type Size Address
对于这个小程序,它可以很好地工作,也适用于其他大型项目。
该代码长度为2000行,有几个错误,并且它不支持.NET版本4.这就是我尝试重新创建它的原因。
所以我的问题是,因为我不知道采取什么方法来解决这个问题,我迷失了。这些是我一直在考虑的选择:
组织我在第一张图片上显示的程序的错误代码,并尝试查看它的作用以及它如何解析a.out文件以获取该信息。一旦我完全理解它,试着弄清楚为什么它不支持版本3和4。
我可以创建正则表达式,所以也许尝试通过执行以下操作来查找a.out文件中的模式:到目前为止,我能够找到只有...的模式一个文件(main.c)。但是当有几个文件时会变得更复杂。我还没有尝试过。也许它不会那么复杂,有可能找到模式。
安装Cygwin,以便我可以在objdump
,nm
或elfread
等窗口上使用linux命令。当我使用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,我会很感激,因为这样可以更容易部署。由于这个问题要求很多,我试图把它分成更多:
也许我应该删除其他问题。抱歉多余了。
答案 0 :(得分:13)
这是我要做的。为什么重新发明轮子!
应该是:readelf.exe
请注意,我们不需要Cygwin或任何程序,因此部署简单!
一旦我们在cmd中执行该文件:
// cd "path where readelf.exe is"
readelf.exe -s a.out
这是将要出现的列表:
所以如果你看看我们有兴趣获得OBJECT类型大小大于0的所有变量。
获得变量之后,我们可以使用readelf.exe -w a.out
命令来查看树,它看起来像:让我们开始寻找变量之一我们在第2步找到(SOME_GREAT_COUNTER)注意,在顶部我们知道声明变量的位置,我们获得了更多信息,例如声明它的行和内存地址
我们要做的最后一件事就是获取类型。如果你看一下我们看到的类型是=&lt; 0x522&gt;。这意味着我们必须转到树的522才能获得有关该时间的更多信息。如果我们去那个部分,这就是我们得到的:从树上看,我们知道SOME_LARGE_VARIABLE的类型是unsigned long