Add a function to look up a section by name and return address/size, and

nuke return of object entrypoint from kobj_stat(). It's a lot easier to
denote the module entypoint using a linkset.
This commit is contained in:
ad 2008-01-12 23:34:48 +00:00
parent 9ac502f441
commit 9dfa2c0234
2 changed files with 89 additions and 27 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_kobj.c,v 1.7 2008/01/07 20:42:48 ad Exp $ */
/* $NetBSD: subr_kobj.c,v 1.8 2008/01/12 23:35:58 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -69,7 +69,7 @@
#include "opt_modular.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.7 2008/01/07 20:42:48 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.8 2008/01/12 23:35:58 ad Exp $");
#define ELFSIZE ARCH_ELFSIZE
@ -133,10 +133,11 @@ struct kobj {
relent_t *ko_reltab;
Elf_Sym *ko_symtab; /* Symbol table */
char *ko_strtab; /* String table */
uintptr_t ko_entry; /* Entry point */
char *ko_shstrtab; /* Section name string table */
size_t ko_size; /* Size of text/data/bss */
size_t ko_symcnt; /* Number of symbols */
size_t ko_strtabsz; /* Number of bytes in string table */
size_t ko_shstrtabsz; /* Number of bytes in scn str table */
size_t ko_shdrsz;
int ko_nrel;
int ko_nrela;
@ -255,6 +256,17 @@ kobj_close(kobj_t ko)
ko->ko_source = NULL;
ko->ko_type = KT_UNSET;
/* Program table and section strings are no longer needed. */
if (ko->ko_progtab != NULL) {
kmem_free(ko->ko_progtab, ko->ko_nprogtab *
sizeof(*ko->ko_progtab));
ko->ko_progtab = NULL;
}
if (ko->ko_shstrtab) {
kmem_free(ko->ko_shstrtab, ko->ko_shstrtabsz);
ko->ko_shstrtab = NULL;
}
/* If the object hasn't been loaded, then destroy it. */
if (!ko->ko_loaded) {
kobj_unload(ko);
@ -471,6 +483,26 @@ kobj_load(kobj_t ko)
goto out;
}
/*
* Do we have a string table for the section names?
*/
if (hdr->e_shstrndx != 0 && shdr[hdr->e_shstrndx].sh_size != 0 &&
shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
ko->ko_shstrtabsz = shdr[hdr->e_shstrndx].sh_size;
ko->ko_shstrtab = kmem_alloc(shdr[hdr->e_shstrndx].sh_size,
KM_SLEEP);
if (ko->ko_shstrtab == NULL) {
error = ENOMEM;
goto out;
}
error = kobj_read(ko, ko->ko_shstrtab,
shdr[hdr->e_shstrndx].sh_size,
shdr[hdr->e_shstrndx].sh_offset);
if (error != 0) {
goto out;
}
}
/*
* Size up code/data(progbits) and bss(nobits).
*/
@ -504,7 +536,6 @@ kobj_load(kobj_t ko)
}
ko->ko_address = mapbase;
ko->ko_size = mapsize;
ko->ko_entry = mapbase + hdr->e_entry;
/*
* Now load code/data(progbits), zero bss(nobits), allocate space
@ -537,6 +568,10 @@ kobj_load(kobj_t ko)
}
ko->ko_progtab[pb].size = shdr[i].sh_size;
ko->ko_progtab[pb].sec = i;
if (ko->ko_shstrtab != NULL && shdr[i].sh_name != 0) {
ko->ko_progtab[pb].name =
ko->ko_shstrtab + shdr[i].sh_name;
}
/* Update all symbol values with the offset. */
for (j = 0; j < ko->ko_symcnt; j++) {
@ -646,6 +681,9 @@ kobj_unload(kobj_t ko)
{
int error;
KASSERT(ko->ko_progtab == NULL);
KASSERT(ko->ko_shstrtab == NULL);
if (ko->ko_address != 0) {
uvm_km_free(lkm_map, ko->ko_address, round_page(ko->ko_size),
UVM_KMF_WIRED);
@ -680,7 +718,7 @@ kobj_unload(kobj_t ko)
* Return size and load address of an object.
*/
void
kobj_stat(kobj_t ko, vaddr_t *address, size_t *size, uintptr_t *entry)
kobj_stat(kobj_t ko, vaddr_t *address, size_t *size)
{
if (address != NULL) {
@ -689,9 +727,6 @@ kobj_stat(kobj_t ko, vaddr_t *address, size_t *size, uintptr_t *entry)
if (size != NULL) {
*size = ko->ko_size;
}
if (entry != NULL) {
*entry = ko->ko_entry;
}
}
/*
@ -723,6 +758,34 @@ kobj_set_name(kobj_t ko, const char *name)
return error;
}
/*
* kobj_find_section:
*
* Given a section name, search the loaded object and return
* virtual address if present and loaded.
*/
int
kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size)
{
int i;
KASSERT(ko->ko_progtab != NULL);
for (i = 0; i < ko->ko_nprogtab; i++) {
if (strcmp(ko->ko_progtab[i].name, name) == 0) {
if (addr != NULL) {
*addr = ko->ko_progtab[i].addr;
}
if (size != NULL) {
*size = ko->ko_progtab[i].size;
}
return 0;
}
}
return ENOENT;
}
/*
* kobj_release_mem:
*
@ -757,11 +820,6 @@ kobj_release_mem(kobj_t ko)
ko->ko_relatab = NULL;
ko->ko_nrela = 0;
}
if (ko->ko_progtab != NULL) {
kmem_free(ko->ko_progtab, ko->ko_nprogtab *
sizeof(*ko->ko_progtab));
ko->ko_progtab = NULL;
}
if (ko->ko_shdr != NULL) {
kmem_free(ko->ko_shdr, ko->ko_shdrsz);
ko->ko_shdr = NULL;
@ -858,7 +916,7 @@ kobj_relocate(kobj_t ko)
const Elf_Rela *rela;
const Elf_Sym *sym;
uintptr_t base;
int i;
int i, error;
uintptr_t symidx;
/*
@ -880,11 +938,9 @@ kobj_relocate(kobj_t ko)
continue;
}
sym = ko->ko_symtab + symidx;
if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
kobj_reloc(ko, base, rel, false, true);
continue;
}
if (kobj_reloc(ko, base, rel, false, false)) {
error = kobj_reloc(ko, base, rel, false,
ELF_ST_BIND(sym->st_info) == STB_LOCAL);
if (error != 0) {
return ENOENT;
}
}
@ -909,11 +965,9 @@ kobj_relocate(kobj_t ko)
continue;
}
sym = ko->ko_symtab + symidx;
if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
kobj_reloc(ko, base, rela, true, true);
continue;
}
if (kobj_reloc(ko, base, rela, true, false)) {
error = kobj_reloc(ko, base, rela, true,
ELF_ST_BIND(sym->st_info) == STB_LOCAL);
if (error != 0) {
return ENOENT;
}
}
@ -1015,7 +1069,7 @@ kobj_unload(kobj_t ko)
}
void
kobj_stat(kobj_t ko, vaddr_t *base, size_t *size, uintptr_t *entry)
kobj_stat(kobj_t ko, vaddr_t *base, size_t *size)
{
panic("not modular");
@ -1028,4 +1082,11 @@ kobj_set_name(kobj_t ko, const char *name)
panic("not modular");
}
int
kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size)
{
panic("not modular");
}
#endif /* MODULAR */

View File

@ -1,4 +1,4 @@
/* $NetBSD: kobj.h,v 1.4 2008/01/07 18:25:56 ad Exp $ */
/* $NetBSD: kobj.h,v 1.5 2008/01/12 23:34:48 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -44,8 +44,9 @@ int kobj_open_mem(kobj_t *, void *, ssize_t);
void kobj_close(kobj_t);
int kobj_load(kobj_t);
void kobj_unload(kobj_t);
void kobj_stat(kobj_t, vaddr_t *, size_t *, uintptr_t *);
void kobj_stat(kobj_t, vaddr_t *, size_t *);
int kobj_set_name(kobj_t, const char *);
int kobj_find_section(kobj_t, const char *, void **, size_t *);
/* MI-MD interface. */
uintptr_t kobj_sym_lookup(kobj_t, uintptr_t);