Add a function (ksyms_init_explicit) to add a symbol table when we know the
exact address of the symtab and strtab ELF sections contents beforehand. This will be used in i386's Multiboot code to add the initial kernel ksyms without having to prepare a minimal ELF image that matches the format expected by the reguluar ksyms_init function. This part was reviewed by cube@ and successfully passes a full i386 release build.
This commit is contained in:
parent
75939147ff
commit
133d7c5ba4
@ -45,7 +45,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.28 2006/10/12 01:32:15 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.29 2006/10/25 13:46:36 jmmv Exp $");
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include "opt_ddb.h"
|
||||
@ -292,42 +292,44 @@ ksymsattach(int arg __unused)
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a symbol table named name.
|
||||
* This is intended for use when the kernel loader enters the table.
|
||||
* Add a symbol table.
|
||||
* This is intended for use when the symbol table and its corresponding
|
||||
* string table are easily available. If they are embedded in an ELF
|
||||
* image, use addsymtab_elf() instead.
|
||||
*
|
||||
* name - Symbol's table name.
|
||||
* symstart, symsize - Address and size of the symbol table.
|
||||
* strstart, strsize - Address and size of the string table.
|
||||
* tab - Symbol table to be updated with this information.
|
||||
* newstart - Address to which the symbol table has to be copied during
|
||||
* shrinking. If NULL, it is not moved.
|
||||
*/
|
||||
static void
|
||||
addsymtab(const char *name, Elf_Ehdr *ehdr, struct symtab *tab)
|
||||
addsymtab(const char *name,
|
||||
caddr_t symstart, size_t symsize,
|
||||
caddr_t strstart, size_t strsize,
|
||||
struct symtab *tab,
|
||||
caddr_t newstart)
|
||||
{
|
||||
caddr_t start = (caddr_t)ehdr;
|
||||
caddr_t send;
|
||||
Elf_Shdr *shdr;
|
||||
Elf_Sym *sym, *nsym;
|
||||
int i, j, n, g;
|
||||
int i, n, g;
|
||||
char *str;
|
||||
|
||||
/* Find the symbol table and the corresponding string table. */
|
||||
shdr = (Elf_Shdr *)(start + ehdr->e_shoff);
|
||||
for (i = 1; i < ehdr->e_shnum; i++) {
|
||||
if (shdr[i].sh_type != SHT_SYMTAB)
|
||||
continue;
|
||||
if (shdr[i].sh_offset == 0)
|
||||
continue;
|
||||
tab->sd_symstart = (Elf_Sym *)(start + shdr[i].sh_offset);
|
||||
tab->sd_symsize = shdr[i].sh_size;
|
||||
j = shdr[i].sh_link;
|
||||
if (shdr[j].sh_offset == 0)
|
||||
continue; /* Can this happen? */
|
||||
tab->sd_strstart = start + shdr[j].sh_offset;
|
||||
tab->sd_strsize = shdr[j].sh_size;
|
||||
break;
|
||||
}
|
||||
if (newstart == NULL)
|
||||
newstart = symstart;
|
||||
KASSERT(newstart <= symstart && symstart <= strstart);
|
||||
|
||||
tab->sd_symstart = (Elf_Sym *)symstart;
|
||||
tab->sd_symsize = symsize;
|
||||
tab->sd_strstart = strstart;
|
||||
tab->sd_strsize = strsize;
|
||||
tab->sd_name = name;
|
||||
send = tab->sd_strstart + tab->sd_strsize;
|
||||
|
||||
#ifdef KSYMS_DEBUG
|
||||
printf("start %p sym %p symsz %d str %p strsz %d send %p\n",
|
||||
start, tab->sd_symstart, tab->sd_symsize,
|
||||
tab->sd_strstart, tab->sd_strsize, send);
|
||||
printf("newstart %p sym %p symsz %d str %p strsz %d send %p\n",
|
||||
newstart, symstart, symsize, strstart, strsize, send);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -335,7 +337,7 @@ addsymtab(const char *name, Elf_Ehdr *ehdr, struct symtab *tab)
|
||||
* and overwrite the elf header.
|
||||
*/
|
||||
sym = tab->sd_symstart;
|
||||
nsym = (Elf_Sym *)start;
|
||||
nsym = (Elf_Sym *)newstart;
|
||||
str = tab->sd_strstart;
|
||||
for (g = i = n = 0; i < tab->sd_symsize/sizeof(Elf_Sym); i++) {
|
||||
if (i == 0) {
|
||||
@ -370,9 +372,12 @@ addsymtab(const char *name, Elf_Ehdr *ehdr, struct symtab *tab)
|
||||
if (ELF_ST_BIND(nsym[n].st_info) == STB_GLOBAL)
|
||||
g++;
|
||||
#if NKSYMS
|
||||
j = strlen(nsym[n].st_name + tab->sd_strstart) + 1;
|
||||
if (j > ksyms_maxlen)
|
||||
ksyms_maxlen = j;
|
||||
{
|
||||
int j;
|
||||
j = strlen(nsym[n].st_name + tab->sd_strstart) + 1;
|
||||
if (j > ksyms_maxlen)
|
||||
ksyms_maxlen = j;
|
||||
}
|
||||
#endif
|
||||
n++;
|
||||
|
||||
@ -412,6 +417,41 @@ addsymtab(const char *name, Elf_Ehdr *ehdr, struct symtab *tab)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a symbol table named name.
|
||||
* This is intended for use when the kernel loader enters the table.
|
||||
*/
|
||||
static void
|
||||
addsymtab_elf(const char *name, Elf_Ehdr *ehdr, struct symtab *tab)
|
||||
{
|
||||
int i, j;
|
||||
caddr_t start = (caddr_t)ehdr;
|
||||
Elf_Shdr *shdr;
|
||||
caddr_t symstart = NULL, strstart = NULL;
|
||||
size_t symsize = 0, strsize = 0;
|
||||
|
||||
/* Find the symbol table and the corresponding string table. */
|
||||
shdr = (Elf_Shdr *)(start + ehdr->e_shoff);
|
||||
for (i = 1; i < ehdr->e_shnum; i++) {
|
||||
if (shdr[i].sh_type != SHT_SYMTAB)
|
||||
continue;
|
||||
if (shdr[i].sh_offset == 0)
|
||||
continue;
|
||||
symstart = start + shdr[i].sh_offset;
|
||||
symsize = shdr[i].sh_size;
|
||||
j = shdr[i].sh_link;
|
||||
if (shdr[j].sh_offset == 0)
|
||||
continue; /* Can this happen? */
|
||||
strstart = start + shdr[j].sh_offset;
|
||||
strsize = shdr[j].sh_size;
|
||||
break;
|
||||
}
|
||||
|
||||
KASSERT(symstart != NULL && strstart != NULL);
|
||||
|
||||
addsymtab(name, symstart, symsize, strstart, strsize, tab, start);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the kernel symbol table stuff.
|
||||
*/
|
||||
@ -460,7 +500,7 @@ ksyms_init(int symsize, void *start, void *end __unused)
|
||||
ksyms_hdr_init(start);
|
||||
#endif
|
||||
|
||||
addsymtab("netbsd", ehdr, &kernel_symtab);
|
||||
addsymtab_elf("netbsd", ehdr, &kernel_symtab);
|
||||
|
||||
#if NKSYMS
|
||||
ksyms_sizes_calc();
|
||||
@ -475,6 +515,30 @@ ksyms_init(int symsize, void *start, void *end __unused)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the kernel symbol table stuff.
|
||||
* Use this when the address of the symbol and string tables are known;
|
||||
* otherwise use ksyms_init with an ELF image.
|
||||
*/
|
||||
void
|
||||
ksyms_init_explicit(caddr_t symstart, size_t symsize,
|
||||
caddr_t strstart, size_t strsize)
|
||||
{
|
||||
|
||||
KASSERT(symstart != NULL);
|
||||
KASSERT(strstart != NULL);
|
||||
KASSERT(symstart <= strstart);
|
||||
|
||||
addsymtab("netbsd", symstart, symsize, strstart, strsize,
|
||||
&kernel_symtab, NULL);
|
||||
|
||||
#if NKSYMS
|
||||
ksyms_sizes_calc();
|
||||
#endif
|
||||
|
||||
ksymsinited = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the value associated with a symbol.
|
||||
* "mod" is the module name, or null if any module.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ksyms.h,v 1.11 2005/12/11 12:25:20 christos Exp $ */
|
||||
/* $NetBSD: ksyms.h,v 1.12 2006/10/25 13:46:36 jmmv Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001, 2003 Anders Magnusson (ragge@ludd.luth.se).
|
||||
* All rights reserved.
|
||||
@ -65,6 +65,7 @@ int ksyms_addsymtab(const char *, void *, vsize_t, char *, vsize_t);
|
||||
int ksyms_delsymtab(const char *);
|
||||
int ksyms_rensymtab(const char *, const char*);
|
||||
void ksyms_init(int, void *, void *);
|
||||
void ksyms_init_explicit(caddr_t, size_t, caddr_t, size_t);
|
||||
#ifdef DDB
|
||||
int ksyms_sift(char *, char *, int);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user