Displaying the Physical Memory Map
The Apple Kernel Debug Kit comes with a kernel gdb macros file (kgmacros) that contains numerous macros useful during low-level development and analysis. One of the macros is showbootermemorymap, which dumps the physical memory map from EFI. The information in this map is very useful for certain types of development.
Since I am often mobile—without ready access to a two-machine debugging set up—I can’t use real kernel debugging much of the time. For introspection-only kernel "debugging", one can use the darwin-kernel gdb target on Mac OS X. It does require that you have a /dev/kmem device available. /dev/kmem is not enabled by default on Mac OS X, but you can enable it at boot time by including kmem=1 in the kernel’s boot arguments.
$ sudo nvram boot-args="-v kmem=1 ..." $ sudo reboot /* system reboots */ $ cd /path/to/kernel/debug/kit/for/current/system/ $ sudo gdb ./mach_kernel ... (gdb) source kgmacros Loading Kernel GDB Macros package. Type "help kgm" for more info. (gdb) target darwin-kernel (gdb) attach Connected. (gdb) showbootermemorymap Type Physical Start Number of Pages available 0000000000000000 000000000000008f ACPI_NVS 000000000008f000 0000000000000001 available 0000000000090000 0000000000000010 ... RT_data 0000000000a8c000 000000000000002b RT_data 0000000000ab7000 0000000000000001 (gdb)
A more convenient alternative is to simply use DTrace to print this information. The following is a DTrace script that mimics the behavior of the showbootermemorymap kernel debug macro.
#! /usr/sbin/dtrace -s
/*
* showbootermemorymap - DTrace script that prints out the physical memory
* map from EFI. Mimics the output format of the
* kernel debugging macro of the same name.
*
* Amit Singh
* http://osxbook.com
*/
#pragma D option quiet
BEGIN
{
self->inited = 1;
self->kgm_boot_args = ((struct boot_args*)(`PE_state).bootArgs);
self->kgm_msize = self->kgm_boot_args->MemoryMapDescriptorSize;
self->kgm_mcount = self->kgm_boot_args->MemoryMapSize / self->kgm_msize;
printf("Type Physical Start Number of Pages\n");
self->kgm_i = 0;
}
fbt:::entry
/self->inited && self->kgm_i < self->kgm_mcount/
{
this->kgm_mptr = (struct EfiMemoryRange*)
((unsigned long)self->kgm_boot_args->MemoryMap +
self->kgm_i * self->kgm_msize);
self->kgm_i++;
printf("%s", (this->kgm_mptr->Type == 0) ? "reserved " :
(this->kgm_mptr->Type == 1) ? "LoaderCode" :
(this->kgm_mptr->Type == 2) ? "LoaderData" :
(this->kgm_mptr->Type == 3) ? "BS_code " :
(this->kgm_mptr->Type == 4) ? "BS_data " :
(this->kgm_mptr->Type == 5) ? "RT_code " :
(this->kgm_mptr->Type == 6) ? "RT_data " :
(this->kgm_mptr->Type == 7) ? "available " :
(this->kgm_mptr->Type ==
? "Unusable " :
(this->kgm_mptr->Type == 9) ? "ACPI_recl " :
(this->kgm_mptr->Type == 10) ? "ACPI_NVS " :
(this->kgm_mptr->Type == 11) ? "MemMapIO " :
(this->kgm_mptr->Type == 12) ? "MemPortIO " :
(this->kgm_mptr->Type == 13) ? "PAL_code " :
"UNKNOWN ");
printf(" %016llx %016llx\n",
this->kgm_mptr->PhysicalStart, this->kgm_mptr->NumberOfPages);
}
fbt:::return
/self->inited && self->kgm_i >= self->kgm_mcount/
{
exit(0);
}