In the "heading-down-a-slippery-slope" department, I've hacked
up a version of crash that is capable of dealing with the
relocatable x86 FC7/upstream kernels, whose kernel symbol values
in the vmlinux file do not match up with their counterparts
when the kernel is actually loaded.
In the "vmlinux and /dev/crash do not match" FC7/upstream
scenario, the kernel gets compiled with:
CONFIG_PHYSICAL_START=0x1000000 (16MB)
CONFIG_PHYSICAL_ALIGN=0x400000 (4MB)
In that case, the kernel symbols start at PAGE_OFFSET (c0000000)
plus the CONFIG_PHYSICAL_START value, or c1000000. However, despite
its name of "CONFIG_PHYSICAL_START", the kernel is actually loaded at
4MB physical, so the real "physical start" location looks to be
controlled by the CONFIG_PHYSICAL_ALIGN value. (Vivek, correct
me if I'm wrong...)
So, whereas the vmlinux file shows these symbol values:
$ nm -Bn vmlinux
...
c1000000 T _text
c1000000 T startup_32
c1001000 T startup_32_smp
c1001080 t checkCPUtype
c1001101 t is486
c1001108 t is386
c1001175 t check_x87
c10011a0 T setup_pda
c10011c2 t setup_idt
c10011df t rp_sidt
c1001262 t early_divide_err
c1001268 t early_illegal_opcode
c1001271 t early_protection_fault
c1001278 t early_page_fault
c100127f t early_fault
c10012a7 t hlt_loop
c10012ac t ignore_int
c10012f0 T _stext
c10012f0 t run_init_process
c10012f0 T stext
c1001304 t init_post
...
But when loaded into memory, they are all changed to reflect that
the kernel was loaded at at 4MB physical instead of 16MB:
$ cat /proc/kallsyms
c0400000 T _text
c0400000 T startup_32
c0401000 T startup_32_smp
c0401080 t checkCPUtype
c0401101 t is486
c0401108 t is386
c0401175 t check_x87
c04011a0 T setup_pda
c04011c2 t setup_idt
c04011df t rp_sidt
c0401262 t early_divide_err
c0401268 t early_illegal_opcode
c0401271 t early_protection_fault
c0401278 t early_page_fault
c040127f t early_fault
c04012a7 t hlt_loop
c04012ac t ignore_int
c04012f0 T _stext
c04012f0 t run_init_process
c04012f0 T stext
c0401304 t init_post
...
So in the case above, it amounts to a 12MB relocation from
from the compiled-in value to the loaded value. And so
if I:
(1) hack in the relocation value when reading/storing
the vmlinux symbols, and later on
(2) back-patch all of the "incorrect" symbols stored by gdb from
the vmlinux file -- in the same manner as when a System.map
file used,
then crash comes up fine, and everything seems to work OK.
(Although, as is the case when a System.map file is
used to back-patch gdb's notion of symbol values, line
numbers from gdb are unavailable)
Anyway, I can't find anything obvious in the vmlinux file
that indicates what the relocation value would be. On a
live system, the vmlinux symbols can be matched with
/proc/kallsyms if it exists. If /proc/kallsyms doesn't
exist, or if running against a dumpfile, the only option
I can think of is adding a crash command line "relocation"
argument.
On the other hand, it's preferable to configure the kernel
such that the virtual address for which it is compiled results
in "unity-mapped" kernel virtual addresses. That has always
been the case, where the kernel is compiled with a base virtual
address of c0100000 or c0400000, gets loaded at a base physical
address of 1MB or 4MB respectively, so that a virtual-to-
physical translation can be done by subtracting the c0000000
(PAGE_OFFSET) unity-map identifier. To make that happen with
the FC7/upstream kernels, the CONFIG_PHYSICAL_START address
needs to be equal to or less than the CONFIG_PHYSICAL_ALIGN
value. In other words, I've rebuilt with these two
combinations:
CONFIG_PHYSICAL_START=0x100000 (1MB)
CONFIG_PHYSICAL_ALIGN=0x400000 (4MB)
or
CONFIG_PHYSICAL_START=0x400000 (4MB)
CONFIG_PHYSICAL_ALIGN=0x400000 (4MB)
and in both cases the kernel gets compiled for c0400000 as
a base virtual address.
In any case, there is hope for handling such kernels.
Dave