Subject: port-i386/34007: vmstat fails on the multiboot kernel booted by GRUB-0.97
To: None <port-i386-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: Noriyuki Shiota <nori@shiota.jp>
List: netbsd-bugs
Date: 07/15/2006 18:20:01
>Number:         34007
>Category:       port-i386
>Synopsis:       vmstat fails on the multiboot kernel booted by GRUB-0.97
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    port-i386-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Jul 15 18:20:01 +0000 2006
>Originator:     Noriyuki Shiota
>Release:        NetBSD 3.99.21
>Organization:
N/A
>Environment:
System: NetBSD toproad.shiota.jp 3.99.21 NetBSD 3.99.21 (TOPROAD) #2: Wed Jul 5 02:20:05 JST 2006 nori@toproad.shiota.jp:/usr/src/sys/arch/i386/compile/TOPROAD i386
Architecture: i386
Machine: i386

>Description:
On multiboot kernel booted by GRUB-0.97,
vmstat, netstat, systat,... fail to get the kernel symbols from /dev/ksyms.

copy_syms() in sys/arch/i386/i386/multiboot.c convert kernel symbols from
multiboot_info format to NetBSD's bootinfo format. then register symbols
by ksyms_init().
ksyms_init() accepts the symbols and /dev/ksyms becomes ready.
but some values in the ELF header for /dev/ksyms are invalid.

kvm_nlist() returns error because e_machine members of the ELF header
is invalid.  /usr/bin/nm checks other members of ELF header.

we need complete initialization of ELF header for /dev/ksyms.

>How-To-Repeat:
install pkgsrc/sysutils/grub, then add following entry to /grub/menu.lst:

	title NetBSD
		root (hd0,3,a)
		kernel /netbsd

boot the kernel via GRUB titled "NetBSD"

# vmstat
vmstat: kvm_nlist: namelist bad namelist
# netstat
netstat: no namelist
# nm /dev/ksyms
nm: /dev/ksyms: File format not recognized
# cat /dev/ksyms > /tmp/zzz
# readelf -a /tmp/zzz | head -20
ELF Header:
  Magic:   7f 45 4c 46 01 00 00 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              none
  Version:                           0 
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           None
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          116 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         2
  Size of section headers:           40 (bytes)
  Number of section headers:         4
  Section header string table index: 3

>Fix:

Index: multiboot.c
===================================================================
RCS file: /home/NetBSD-cvs/main/src/sys/arch/i386/i386/multiboot.c,v
retrieving revision 1.4
diff -u -r1.4 multiboot.c
--- multiboot.c	4 Feb 2006 11:28:54 -0000	1.4
+++ multiboot.c	14 Jul 2006 08:42:26 -0000
@@ -279,6 +279,7 @@
 	int i;
 	Elf32_Shdr *symtabp, *strtabp;
 	struct symbols_image *si;
+	extern void start(void);
 
 	/*
 	 * Check if the Multiboot information header has symbols or not.
@@ -340,8 +341,12 @@
 	 */
 	memcpy(si->i_ehdr.e_ident, ELFMAG, SELFMAG);
 	si->i_ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+	si->i_ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+	si->i_ehdr.e_ident[EI_VERSION] = EV_CURRENT;
 	si->i_ehdr.e_type = ET_EXEC;
+	si->i_ehdr.e_machine = EM_386;
 	si->i_ehdr.e_version = 1;
+	si->i_ehdr.e_entry = (Elf32_Addr)start;
 	si->i_ehdr.e_shoff = offsetof(struct symbols_image, i_shdr);
 	si->i_ehdr.e_ehsize = sizeof(si->i_ehdr);
 	si->i_ehdr.e_shentsize = sizeof(si->i_shdr[0]);