4

我遇到了一个示例 gdbinit 文件,其中包含以下语句。谁能告诉我地址​​(0x40000000、0x80000000 和 0xBF000000)有什么特别之处?为什么再次检查他们让我知道有效或无效地址?

define dd
if ( ($arg0 & 0x40000000) || ($arg0 & 0x08000000) || ($arg0 & 0xBF000000) )
set $data_addr=$arg0
ddump 0x10 $arg0
else
printf "Invalid address: %08X\n", $arg0
end
end

此外,以下针对相同地址的检查如何再次告诉我为数据地址选择哪个寄存器?

define datawin
if ( ($esi & 0x40000000) || ($esi & 0x08000000) || ($esi & 0xBF000000) )
set $data_addr=$esi
else
if ( ($edi & 0x40000000) || ($edi & 0x08000000) || ($edi & 0xBF000000) )
set $data_addr=$edi
else
if ( ($eax & 0x40000000) || ($eax & 0x08000000) || ($eax & 0xBF000000) )
set $data_addr=$eax
else
set $data_addr=$esp
end

任何帮助将不胜感激。谢谢。

4

4 回答 4

2

大多数在具有 MMU 功能的 CPU 上运行的现代操作系统为进程提供了一个虚拟内存模型,该模型被划分为某些区域。一般来说,低地址属于进程,高地址属于操作系统。在这些之间,有堆栈空间。在您的情况下,它是一个 32 位系统。第一部分检查地址的有效性(但此检查不保证给定地址的可访问性),第二部分只使用给定的寄存器......

于 2012-04-03T13:44:12.297 回答
2

在大多数电路板中,在这种情况下,0x00000000 到 0x00ffffff RAM 被映射,闪存 0x40000000 到 0x407fffff 被映射。

该特定页面存在很多问题-恕我直言,它大多已过时(对于 80386 可能不太正确)。具体来说: - EBDA 大小以及视频 ROM 和 BIOS 的大小都不是固定大小。有些计算机是“无头”的,没有视频(或视频 ROM)。

  • 视频 ROM 和 BIOS 之间的区域从未包含“无”。它一直为其他“设备特定的 ROM”(SCSI BIOS、以太网启动 ROM 等)保留,对于某些系统,该区域可能包含可用 RAM(某些操作系统,如 Windows 95,实际上会扫描该区域并使用在其中找到的任何 RAM它)。

  • 对于较旧的计算机(可能还有最近的计算机,如果为其配置了 BIOS,包括一些新计算机),15 MB 和 16 MB 之间的区域是一个“内存漏洞”,它曾经(并且可能仍然)用于旧 ISA 设备的内存映射 I/O。这个区域最常被 ISA SVGA 卡使用,但任何 ISA 卡(甚至是插入全新计算机的旧 ISA 卡)都可以使用。

  • NVRAM 和 ACPI 不使用高于 0xFEC00000 的内存,并且永远不会使用。取而代之的是使用 RAM 顶部的内存(例如,对于具有 256 MB RAM 的计算机来说,内存刚好低于 0x10000000)。

  • 通常有一个低于 0xFEC00000 的区域用于内存映射的 PCI/AGP 设备(例如视频线性帧缓冲区)。该区域的大小取决于 BIOS 和主板(通常从 0xC0000000 或 0xE0000000 开始)。这意味着对于具有 4 GB RAM 的计算机,“32 位”操作系统将只能使用 3 GB 或 3.5 GB。大多数“好”的主板会将备用 RAM 映射到 4 GB 以上(操作系统需要使用 PAE、PSE36 或长模式来访问它)。便宜的主板可能只会浪费这个 RAM。

  • 从 0xFEC00000 到 BIOS 底部的区域(实际上刚好低于 4 GB - 由于芯片组技巧,它的全部或部分似乎低于 1 MB)主要为本地 APIC 和 I/O APIC(如果有)保留.

  • 在较新的计算机上,RAM 可能超过 4 GB。这还不是很常见,但Vista 也还没有正式发布。

  • 对于服务器,事情可能会更加复杂。NUMA 是一个问题(包括简单的“双插槽”AMD 系统),它可能会导致 RAM 配置在存储区中(例如 0x00000000 处的 512 MB 和 0x80000000 处的另一个 512 MB,中间有一个大孔)。此外,一些服务器支持“热插拔”RAM 区域(通常高于“启动时安装的 RAM”,通常也高于 4 GB)。

http://forum.osdev.org/viewtopic.php?t=11391

http://books.google.co.in/books?id=xnFdWfJAK9wC&pg=PT289&lpg=PT289&dq=on+hard+disk+addresses+0x40000000&source=bl&ots=GFQJQ5R_-Z&sig=VchcoPWMeIE4E-Vzom1lmUxxJSg&hl=en&sa=X&ei=jvx6TgEA&sqi=2 0CEsQ6AEwAQ#v=onepage&q=on%20hard%20disk%20addresses%200x40000000&f=false

所以,我可以说这些是 Linux 操作系统对内存的限制。我们无法从 0x00000000 获取基地址,因为它被映射到某个限制。基地址 0x40000000 通常是操作系统代码的开始,同样我可以说基地址 0xBF000000 是操作系统代码的限制。

于 2012-04-03T14:02:36.093 回答
1

这是针对 Linux 的。您的标题中有一个地址错误,不是 0x80000000 而是 0x8000000。

Linux 程序通常在 0x8210000 (iirc) 加载。该范围适用于您的代码本身。

堆栈默认为 0xBFFF????。这是第二个范围。

第三个范围可能是可写数据部分的开始,或者是加载库的位置。

虽然检查似乎写得不好,但没有检查二进制 AND 最终返回的内容,因此带有“0xBF000000”的 and 将返回 true 以获得比它应该的更多的地址。

[编辑]您问题的第二部分,如果 esi/edi/eax 中的任何一个在该区域中包含一个数字,它很可能指向您的数据区域中的某个地方。

于 2012-04-03T13:38:59.763 回答
1

Mapping的过程可以查看:

$ pmap pid
$ pmap 3724

图书:

“了解 Linux 内核” 9.3。记忆区;16.2. 内存映射《理解 Linux 虚拟内存管理器》 4.4 内存区域

链接:

http://www.scs.ch/~frey/linux/memorymap.html
http://www.linuxdoc.org/HOWTO/KernelAnalysis-HOWTO-7.html
http://linuxdevcenter.com/pub/a/linux/2006/11/30/linux-out-of-memory.html
http://www.linux-tutorial.info/modules.php?name=MContent&pageid=260
http://www.syslinux.org/wiki/index.php/Memory_Map_(General)

因为我不知道您的代码在什么类型的系统上内存不足;你在用什么这么精确的定义很难给出。在上面的答案中,我给出了来自“Linux 内核编程 - Robert Love”的板映射示例的详细信息,以及有关各种操作系统(linux)和硬件的一些细节,这些都有一些限制。因此,很难判断内存限制是多少。

于 2012-04-06T11:01:28.307 回答