有没有办法知道全局变量和静态变量在数据段(.data + .bss)中的位置?

时间:2012-01-03 16:06:43

标签: c memory assembly x86 portable-executable

我想将所有全局变量和静态变量转储到文件中,并在下一次程序调用时将它们加载回来。我想到的解决方案是将.data段转储到文件中。但32位机器上的.data段跨越2 ^ 32地址空间(4GB)。变量驻留在这个地址空间的哪个部分?我怎么知道我应该转储.data段的哪一部分?

当加载转储文件时,我想由于变量是由数据段中的偏移量引用的,所以将整个转储存储到“变量区域”的所谓起点是安全的。如果我错了,请纠正我。

修改

一个好的开始是this question

5 个答案:

答案 0 :(得分:1)

您的问题是如何找到数据段的开头和结尾。我不知道该怎么做,但我可以给你一些想法。

如果所有数据都是相对自包含的(它们在同一模块中声明,而不是在单独的模块中声明),您可以在某种结构中声明它们,因此开头将是结构,结尾将是一些你将在结构后面声明的变量。如果我记得很清楚,MASM有一个“RECORD”指令或者你可以用来将变量组合在一起的指令。

或者,您可以声明两个额外的模块,一个带有一个名为“begin”的变量,另一个带有一个名为“end”的变量,并确保第一个模块在其他任何内容之前被链接,第二个模块被链接其他一切之后。这样,这些变量实际上可能最终标记数据段的开头和结尾。但我不确定这一点,我只是给你一个指针。

要记住的一件事是,您的数据将不可避免地包含指针,因此保存和加载所有数据只有在您运行的操作系统可以保证您的程序始终加载到同一地址时才有效。如果没有,请忘掉它。但是,如果您可以获得此保证,那么是的,加载数据应该可行。您甚至不需要memcpy,只需将读取操作的缓冲区设置为数据段的开头。

答案 1 :(得分:0)

整个程序的状态可能非常复杂,不仅涉及变量,还涉及寄存器中的值。您几乎肯定会更好地跟踪您要存储的数据,然后自己将其存储到文件中。通过正确的设置和封装,这可以相对轻松。然后,当您恢复应用程序时,请读入程序状态并继续。

答案 2 :(得分:0)

假设您正在使用gnu工具(gcc,binutils),如果您查看链接器脚本,嵌入式人员就像使用roms的gba开发人员和微控制器开发人员那样(例如yagarto或devkit-arm)。在链接描述文件中,它们使用可在代码中的其他位置使用的变量包围感兴趣的段。例如,对于基于rom的软件,您可以在链接器脚本中指定带有ram AT rom或rom AT ram的数据段,这意味着链接就像数据段在此地址空间中的ram一样,但也将数据本身链接到此地址的rom中空间,启动代码然后使用这些变量将.data段从rom复制到ram。我不明白为什么你不能做同样的事情让编译器/链接器工具告诉你什么东西然后运行时使用这些变量从内存中获取数据并将其保存到hybernate或关闭,然后从任何地方恢复该数据。当然,用于执行恢复的变量不应该是.data段的一部分,也不应该删除用于恢复段的变量。

答案 3 :(得分:0)

在回答您的标题问题时,在Windows上,可以从内存中的PE标头获取数据和bss段的位置和大小。本规范中记录了如何布局以及如何解析它:

http://msdn.microsoft.com/en-us/windows/hardware/gg463119

答案 4 :(得分:-1)

我不相信可以保证每次执行都会有sam序列的变量,因此偏移可能指向错误的内容。