Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/hpc/hpc Pass the symbol table to the new kernel. /...



details:   https://anonhg.NetBSD.org/src/rev/e3c758810f30
branches:  trunk
changeset: 559739:e3c758810f30
user:      uwe <uwe%NetBSD.org@localhost>
date:      Tue Mar 23 03:39:11 2004 +0000

description:
Pass the symbol table to the new kernel.  /dev/ksyms now works after reboot.

diffstat:

 sys/arch/hpc/hpc/kloader.c |  249 +++++++++++++++++++++++++++++++-------------
 1 files changed, 172 insertions(+), 77 deletions(-)

diffs (truncated from 406 to 300 lines):

diff -r aae10d8606ff -r e3c758810f30 sys/arch/hpc/hpc/kloader.c
--- a/sys/arch/hpc/hpc/kloader.c        Tue Mar 23 03:36:32 2004 +0000
+++ b/sys/arch/hpc/hpc/kloader.c        Tue Mar 23 03:39:11 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kloader.c,v 1.8 2004/03/22 23:10:55 uwe Exp $  */
+/*     $NetBSD: kloader.c,v 1.9 2004/03/23 03:39:11 uwe Exp $  */
 
 /*-
  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -34,12 +34,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kloader.c,v 1.8 2004/03/22 23:10:55 uwe Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kloader.c,v 1.9 2004/03/23 03:39:11 uwe Exp $");
 
 #include "debug_kloader.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/vnode.h>
 #include <sys/namei.h>
@@ -80,13 +81,16 @@
 #define KLOADER_PROC   (&proc0)
 STATIC struct kloader kloader;
 
+#define ROUND4(x)      (((x) + 3) & ~3)
+
+
 STATIC int kloader_load(void);
 
 STATIC int kloader_alloc_memory(size_t);
 STATIC struct kloader_page_tag *kloader_get_tag(vaddr_t);
-STATIC ssize_t kloader_from_file(vaddr_t, off_t, size_t);
-STATIC ssize_t kloader_copy(vaddr_t, void *, size_t);
-STATIC ssize_t kloader_zero(vaddr_t, size_t);
+STATIC void kloader_from_file(vaddr_t, off_t, size_t);
+STATIC void kloader_copy(vaddr_t, const void *, size_t);
+STATIC void kloader_zero(vaddr_t, size_t);
 
 STATIC void kloader_load_segment(Elf_Phdr *);
 
@@ -175,8 +179,12 @@
        Elf_Ehdr eh;
        Elf_Phdr ph[16], *p;
        Elf_Shdr sh[16];
+       Elf_Addr entry;
        vaddr_t kv;
        size_t sz;
+       size_t shstrsz;
+       char *shstrtab;
+       int symndx, strndx;
        size_t ksymsz;
        struct kloader_bootinfo nbi; /* new boot info */
        char *oldbuf, *newbuf;
@@ -200,6 +208,21 @@
        /* read section headers */
        kloader_read(eh.e_shoff, eh.e_shentsize * eh.e_shnum, sh);
 
+       /* read section names */
+       shstrsz = ROUND4(sh[eh.e_shstrndx].sh_size);
+       shstrtab = malloc(shstrsz, M_TEMP, M_NOWAIT);
+       if (shstrtab == NULL) {
+               PRINTF("unable to allocate memory for .shstrtab\n");
+               return (1);
+       }
+       DPRINTF("reading 0x%x bytes of .shstrtab at 0x%x\n",
+               sh[eh.e_shstrndx].sh_size, sh[eh.e_shstrndx].sh_offset);
+       kloader_read(sh[eh.e_shstrndx].sh_offset, sh[eh.e_shstrndx].sh_size,
+                    shstrtab);
+
+       /* save entry point, code to construct symbol table overwrites it */
+       entry = eh.e_entry;
+
 
        /*
         * Calcurate memory size
@@ -209,7 +232,7 @@
        /* loadable segments */
        for (i = 0; i < eh.e_phnum; i++) {
                if (ph[i].p_type == PT_LOAD) {
-                       DPRINTF("alloc [%d] file 0x%x memory 0x%x\n",
+                       DPRINTF("segment %d size = file 0x%x memory 0x%x\n",
                                i, ph[i].p_filesz, ph[i].p_memsz);
 #ifdef KLOADER_ZERO_BSS
                        sz += round_page(ph[i].p_memsz);
@@ -218,14 +241,37 @@
 #endif
                }
        }
-       DPRINTF("entry: 0x%08x\n", eh.e_entry);
 
        if (sz == 0)            /* nothing to load? */
                return (1);
 
-       /* XXX: ksysm placeholder */
-       ksymsz = SELFMAG;
-       sz += ksymsz;
+       /* symbols/strings sections */
+       symndx = strndx = -1;
+       for (i = 0; i < eh.e_shnum; i++) {
+           if (strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0)
+                   symndx = i;
+           else if (strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0)
+                   strndx = i;
+           else if (i != eh.e_shstrndx)
+                   /* while here, mark all other sections as unused */
+                   sh[i].sh_type = SHT_NULL;
+       }
+
+       if (symndx < 0 || strndx < 0) {
+               if (symndx < 0)
+                       PRINTF("no .symtab section\n");
+               if (strndx < 0)
+                       PRINTF("no .strtab section\n");
+               ksymsz = SELFMAG; /* just a bad magic */
+       } else {
+               ksymsz = sizeof(Elf_Ehdr)
+                       + eh.e_shentsize * eh.e_shnum
+                       + shstrsz               /* rounded to 4 bytes */
+                       + sh[symndx].sh_size
+                       + sh[strndx].sh_size;
+               DPRINTF("ksyms size = 0x%x\n", ksymsz);
+       }
+       sz += ROUND4(ksymsz);
 
        /* boot info for the new kernel */
        sz += sizeof(struct kloader_bootinfo);
@@ -246,12 +292,60 @@
                }
        }
 
+
        /*
-        * XXX: ksyms placeholder
+        * Construct symbol table for ksyms.
         */
-       kloader_zero(kv, SELFMAG);
-       kv += SELFMAG;
+       if (symndx < 0 || strndx < 0) {
+               kloader_zero(kv, SELFMAG);
+               kv += SELFMAG;
+       } else {
+               Elf_Off eoff;
+               off_t symoff, stroff;
+
+               /* save offsets of .symtab and .strtab before we change them */
+               symoff = sh[symndx].sh_offset;
+               stroff = sh[strndx].sh_offset;
+
+               /* no loadable segments */
+               eh.e_entry = 0;
+               eh.e_phnum = 0;
+               eh.e_phoff = 0;
+
+               /* change offsets to reflect new layout */
+               eoff = sizeof(Elf_Ehdr);
+               eh.e_shoff = eoff;
+
+               eoff += eh.e_shentsize * eh.e_shnum;
+               sh[eh.e_shstrndx].sh_offset = eoff;
 
+               eoff += shstrsz;
+               sh[symndx].sh_offset = eoff;
+
+               eoff += sh[symndx].sh_size;
+               sh[strndx].sh_offset = eoff;
+
+               /* local copies massaged, can serve them now */
+               DPRINTF("ksyms ELF header\n");
+               kloader_copy(kv, &eh, sizeof(Elf_Ehdr));
+               kv += sizeof(Elf_Ehdr);
+
+               DPRINTF("ksyms section headers\n");
+               kloader_copy(kv, sh, eh.e_shentsize * eh.e_shnum);
+               kv += eh.e_shentsize * eh.e_shnum;
+
+               DPRINTF("ksyms .shstrtab\n");
+               kloader_copy(kv, shstrtab, shstrsz);
+               kv += shstrsz;
+
+               DPRINTF("ksyms .symtab\n");
+               kloader_from_file(kv, symoff, sh[symndx].sh_size);
+               kv += sh[symndx].sh_size;
+
+               DPRINTF("ksyms .strtab\n");
+               kloader_from_file(kv, stroff, ROUND4(sh[strndx].sh_size));
+               kv += ROUND4(sh[strndx].sh_size);
+       }
 
        /*
         * Create boot info to pass to the new kernel.
@@ -263,7 +357,7 @@
               sizeof(struct kloader_bootinfo));
 
        /* new kernel entry point */
-       nbi.entry = eh.e_entry;
+       nbi.entry = entry;
 
        /* where args currently are, see kloader_bootinfo_set() */
        oldbuf = &kloader.bootinfo->_argbuf[0];
@@ -272,7 +366,7 @@
        newbuf = (char *)(void *)kv
                + offsetof(struct kloader_bootinfo, _argbuf);
 
-       DPRINTF("argbuf: old %p -> new %p\n", oldbuf, newbuf);
+       DPRINTF("argv: old %p -> new %p\n", oldbuf, newbuf);
 
        /* not a valid pointer in this kernel! */
        nbi.argv = (void *)newbuf;
@@ -281,19 +375,19 @@
        ap = (char **)(void *)nbi._argbuf;
 
        for (i = 0; i < kloader.bootinfo->argc; ++i) {
-               DPRINTFN(1, "[%d]: %p -> ", i, kloader.bootinfo->argv[i]);
+               DPRINTFN(1, " [%d]: %p -> ", i, kloader.bootinfo->argv[i]);
                ap[i] = newbuf +
                        (kloader.bootinfo->argv[i] - oldbuf);
                _DPRINTFN(1, "%p\n", ap[i]);
        }
 
        /* arrange for the new bootinfo to get copied */
+       DPRINTF("bootinfo\n");
        kloader_copy(kv, &nbi, sizeof(struct kloader_bootinfo));
 
        /* will be valid by the time the new kernel starts */
        kloader.rebootinfo = (void *)kv;
-
-       kv += sizeof(struct kloader_bootinfo);
+       /* kv += sizeof(struct kloader_bootinfo); */
 
 
        /*
@@ -306,8 +400,8 @@
        /* loader stack starts at the bottom of that page */
        kloader.loader_sp = (vaddr_t)kloader.loader + PAGE_SIZE;
 
-       DPRINTF("[loader] addr=%p sp=0x%08lx\n",
-               kloader.loader, kloader.loader_sp);
+       DPRINTF("[loader] addr=%p sp=%p [kernel] entry=%p\n",
+               kloader.loader, (void *)kloader.loader_sp, (void *)nbi.entry);
 
        return (0);
 }
@@ -344,15 +438,13 @@
        vaddr_t addr;
        struct kloader_page_tag *tag;
 
-       DPRINTFN(1, "%x ", (uint32_t)dst);
-
        tag = kloader.cur_tag;
        if (tag != NULL         /* has tag */
            && tag->sz < BUCKET_SIZE /* that has free space */
            && tag->dst + tag->sz == dst) /* and new data are contiguous */
        {
-               _DPRINTFN(1, "- curtag %x/%x ok\n", tag->dst, tag->sz);
-               return (tag);           /* current tag is ok */
+               DPRINTFN(1, "current tag %x/%x ok\n", tag->dst, tag->sz);
+               return (tag);
        }
 
        pg = kloader.cur_pg;
@@ -377,85 +469,88 @@
  * Operations to populate kloader_page_tag's with data.
  */
 
-/* common prologue */
-#define KLOADER_PREPARE_OP(_tag, _dst, _sz) do {       \
-       size_t freesz;                                  \
-                                                       \
-       _tag = kloader_get_tag(_dst);                   \
-       KDASSERT(_tag != NULL);                         \
-                                                       \
-       DPRINTFN(1, "sz %x", _sz);                      \
-       freesz = BUCKET_SIZE - tag->sz;                 \
-       if (_sz > freesz)                               \
-               _sz = freesz;                           \
-       _DPRINTFN(1, "-> %x\n", _sz);                   \
-} while (/* CONSTCOND */0)
-
-
-ssize_t
+void
 kloader_from_file(vaddr_t dst, off_t ofs, size_t sz)
 {
        struct kloader_page_tag *tag;
-       KLOADER_PREPARE_OP(tag, dst, sz);
+       size_t freesz;
+
+       while (sz > 0) {
+               tag = kloader_get_tag(dst);
+               KDASSERT(tag != NULL);
+               freesz = BUCKET_SIZE - tag->sz;
+               if (freesz > sz)
+                       freesz = sz;
 
-       kloader_read(ofs, sz, (void *)(tag->src + tag->sz));
-       tag->sz += sz;



Home | Main Index | Thread Index | Old Index