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 == 8) ? "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); }