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

发布于 2024-12-23 17:27:19 字数 395 浏览 1 评论 0原文

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

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

编辑

一个好的开始是这个问题。

I want to dump all global and static variables to a file and load them back on the next program invocation. A solution I thought of is to dump the .data segment to a file. But .data segment on a 32bit machine spans over 2^32 address space (4GB). In which part of this address space the variables reside? How do I know which part of the .data segment I should dump?

And when loading the dumped file, I guess that since the variables are referenced by offset in the data segment, it will be safe to just memcpy the whole dump to the alleged starting point of the "variables area". Please correct me if I am wrong.

EDIT

A good start is this question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

万水千山粽是情ミ 2024-12-30 17:27:19

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

如果您的所有数据都是相对独立的(它们在同一模块中声明,而不是在单独的模块中),您也许可以在某种结构中声明它们,因此开头将是结构的地址,并且最后将是一些您将在结构之后声明的变量。如果我没记错的话,MASM 有一个“RECORD”指令或类似的指令,您可以使用它来将变量分组在一起。

或者,您可以声明两个附加模块,一个带有名为“beginning”的变量,另一个带有名为“end”的变量,并确保第一个在其他任何内容之前链接,第二个在其他所有内容之后链接。这样,这些变量实际上可能最终标记数据段的开始和结束。但我对此不太确定,我只是给你一个指导。

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

Your problem is how to find the beginning and the end of the data segment. I am not sure how to do this, but I could give you a couple of ideas.

If all your data are relatively self-contained, (they are declared within the same module, not in separate modules,) you might be able to declare them within some kind of structure, so the beginning will be the address of the structure, and the end will be some variable that you will declare right after the structure. If I remember well, MASM had a "RECORD" directive or something like that which you could use to group variables together.

Alternatively, you may be able to declare two additional modules, one with a variable called "beginning" and another with a variable called "end", and make sure that the first gets linked before anything else, and the second gets linked after everything else. This way, these variables might actually end up marking the beginning and the end of the data segment. But I am not sure about this, I am just giving you a pointer.

One thing to remember is that your data will inevitably contain pointers, so saving and loading all your data will only work if the OS under which you are running can guarantee that your program will always be loaded in the same address. If not, forget it. But if you can have this guarantee, then yes, loading the data should work. You should not even need a memcpy, just set the buffer for the read operation to be the beginning of the data segment.

转身泪倾城 2024-12-30 17:27:19

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

The state of an entire program can be very complicated, and will not only involve variables but values in registers. You'll almost certainly be better off keeping track of what data you want to store and then storing it to a file yourself. This can be relatively painless with the right setup and encapsulation. Then when you resume the application, read in the program state and resume.

嘦怹 2024-12-30 17:27:19

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

Assuming you are using gnu tools (gcc, binutils) if you look at the linker scripts the embedded folks use like the gba developers and microcontroller developers using roms (yagarto or devkit-arm for example). In the linker script they surround the segments of interest with variables that they can use elsewhere in their code. For rom based software for example you specify the data segment with a ram AT rom or rom AT ram in the linker script meaning link as if the data segment is in ram at this address space, but also link the data itself into rom at this address space, the boot code then copies the .data segment from the rom to the ram using these variables. I dont see why you couldnt do the same thing to have the compiler/linker tools tell you where stuff is then runtime use those variables to grab the data from memory and save it somewhere to hybernate or shut down and then restore that data from wherever. The variables you use to perform the restore of course should not be part of the .data segment or you trash the variables you are using to restore the segment.

熊抱啵儿 2024-12-30 17:27:19

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

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

In response to your header question, on Windows, the location and size of the data and bss segments can be obtained from the in-memory PE header. How that is laid out and how to parse it is documented in this specification:

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

贪了杯 2024-12-30 17:27:19

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

I do not believe that there is a guarantee that with every execution you will have the sam sequence of variables, hence the offsets may point to the wrong content.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文