reserve correct size of kernel symbol table.

This commit is contained in:
uch 2001-07-03 20:38:03 +00:00
parent b7960ea852
commit d9d3df290a
2 changed files with 144 additions and 61 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: load_elf.cpp,v 1.3 2001/05/08 18:51:23 uch Exp $ */
/* $NetBSD: load_elf.cpp,v 1.4 2001/07/03 20:38:03 uch Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -36,20 +36,30 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <hpcmenu.h>
#include <menu/window.h>
#include <menu/rootwindow.h>
#include <load.h>
#include <load_elf.h>
#include <console.h>
#include <memory.h>
#include <file.h>
#define ROUND4(x) (((x) + 3) & ~3)
ElfLoader::ElfLoader(Console *&cons, MemoryManager *&mem)
: Loader(cons, mem)
{
_sym_blk.enable = FALSE;
DPRINTF((TEXT("Loader: ELF\n")));
}
ElfLoader::~ElfLoader(void)
{
if (_sym_blk.header != NULL)
free (_sym_blk.header);
}
BOOL
@ -58,14 +68,14 @@ ElfLoader::setFile(File *&file)
size_t sz;
Loader::setFile(file);
/* read ELF header and check it */
// read ELF header and check it
if (!read_header())
return FALSE;
/* read section header */
// read section header
sz = _eh.e_shnum * _eh.e_shentsize;
_file->read(_sh, _eh.e_shentsize * _eh.e_shnum, _eh.e_shoff);
/* read program header */
// read program header
sz = _eh.e_phnum * _eh.e_phentsize;
return _file->read(_ph, sz, _eh.e_phoff) == sz;
@ -86,8 +96,13 @@ ElfLoader::memorySize()
sz += _mem->roundPage(filesz);
}
}
/* XXX reserve 192kB for symbols */
sz += 0x30000;
// reserve for symbols
size_t symblk_sz = symbol_block_size();
if (symblk_sz) {
sz += symblk_sz;
DPRINTF((TEXT(" = 0x%x]"), symblk_sz));
}
DPRINTF((TEXT(" = 0x%x byte\n"), sz));
return sz;
@ -104,12 +119,7 @@ BOOL
ElfLoader::load()
{
Elf_Phdr *ph;
Elf_Shdr *sh, *shstr, *shsym;
off_t stroff = 0, symoff = 0, off;
vaddr_t kv;
size_t shstrsize;
char buf[1024];
int i;
_load_segment_start();
@ -127,60 +137,121 @@ ElfLoader::load()
}
}
/*
* Prepare ELF headers for symbol table.
*
* ELF header
* section header
* shstrtab
* strtab
* symtab
*/
memcpy(buf, &_eh, sizeof(_eh));
((Elf_Ehdr *)buf)->e_phoff = 0;
((Elf_Ehdr *)buf)->e_phnum = 0;
((Elf_Ehdr *)buf)->e_entry = 0;
((Elf_Ehdr *)buf)->e_shoff = sizeof(_eh);
off = ((Elf_Ehdr *)buf)->e_shoff;
memcpy(buf + off, _sh, _eh.e_shentsize * _eh.e_shnum);
sh = (Elf_Shdr *)(buf + off);
off += _eh.e_shentsize * _eh.e_shnum;
load_symbol_block(kv);
/* load shstrtab and find desired sections */
shstrsize = (sh[_eh.e_shstrndx].sh_size + 3) & ~0x3;
_file->read(buf + off, shstrsize, sh[_eh.e_shstrndx].sh_offset);
for(i = 0; i < _eh.e_shnum; i++, sh++) {
if (strcmp(".strtab", buf + off + sh->sh_name) == 0) {
stroff = sh->sh_offset;
shstr = sh;
} else if (strcmp(".symtab", buf + off + sh->sh_name) == 0) {
symoff = sh->sh_offset;
shsym = sh;
}
if (i == _eh.e_shstrndx)
sh->sh_offset = off;
else
sh->sh_offset = 0;
}
/* silently return if strtab or symtab can't be found */
if (! stroff || ! symoff)
return TRUE;
shstr->sh_offset = off + shstrsize;
shsym->sh_offset = off + shstrsize + ((shstr->sh_size + 3) & ~0x3);
_load_memory(kv, off + shstrsize, buf);
kv += off + shstrsize;
_load_segment(kv, shstr->sh_size, stroff, shstr->sh_size);
kv += (shstr->sh_size + 3) & ~0x3;
_load_segment(kv, shsym->sh_size, symoff, shsym->sh_size);
/* tag chain still opening */
// tag chain still opening
return TRUE;
}
//
// Prepare ELF headers for symbol table.
//
// ELF header
// section header
// shstrtab
// strtab
// symtab
//
size_t
ElfLoader::symbol_block_size()
{
size_t shstrsize = ROUND4(_sh[_eh.e_shstrndx].sh_size);
size_t shtab_sz = _eh.e_shentsize * _eh.e_shnum;
off_t shstrtab_offset = sizeof(Elf_Ehdr) + shtab_sz;
int i;
memset(&_sym_blk, 0, sizeof(_sym_blk));
_sym_blk.enable = FALSE;
_sym_blk.header_size = sizeof(Elf_Ehdr) + shtab_sz + shstrsize;
// inquire string and symbol table size
_sym_blk.header = static_cast<char *>(malloc(_sym_blk.header_size));
if (_sym_blk.header == NULL) {
MessageBox(HPC_MENU._root->_window,
TEXT("couldn't determine symbol block size"),
TEXT("WARNING"), 0);
return (0);
}
// set pointer for symbol block
Elf_Ehdr *eh = reinterpret_cast<Elf_Ehdr *>(_sym_blk.header);
Elf_Shdr *sh = reinterpret_cast<Elf_Shdr *>
(_sym_blk.header + sizeof(Elf_Ehdr));
char *shstrtab = _sym_blk.header + shstrtab_offset;
// initialize headers
memset(_sym_blk.header, 0, _sym_blk.header_size);
memcpy(eh, &_eh, sizeof(Elf_Ehdr));
eh->e_phoff = 0;
eh->e_phnum = 0;
eh->e_entry = 0; // XXX NetBSD kernel check this member. see machdep.c
eh->e_shoff = sizeof(Elf_Ehdr);
memcpy(sh, _sh, shtab_sz);
// inquire symbol/string table information
_file->read(shstrtab, shstrsize, _sh[_eh.e_shstrndx].sh_offset);
for (i = 0; i < _eh.e_shnum; i++, sh++) {
if (strcmp(".strtab", shstrtab + sh->sh_name) == 0) {
_sym_blk.shstr = sh;
_sym_blk.stroff = sh->sh_offset;
} else if (strcmp(".symtab", shstrtab + sh->sh_name) == 0) {
_sym_blk.shsym = sh;
_sym_blk.symoff = sh->sh_offset;
}
sh->sh_offset = (i == _eh.e_shstrndx) ? shstrtab_offset : 0;
}
if (_sym_blk.shstr == NULL || _sym_blk.shsym == NULL) {
MessageBox(HPC_MENU._root->_window,
TEXT("no symbol and/or strint table in binary"),
TEXT("Information"), 0);
free(_sym_blk.header);
_sym_blk.header = NULL;
return (0);
}
// set Section Headers for symbol/string table
_sym_blk.shstr->sh_offset = shstrtab_offset + shstrsize;
_sym_blk.shsym->sh_offset = shstrtab_offset + shstrsize +
ROUND4(_sym_blk.shstr->sh_size);
_sym_blk.enable = TRUE;
DPRINTF((TEXT("+[(symbol block: header %d string %d symbol %d byte)"),
_sym_blk.header_size,_sym_blk.shstr->sh_size,
_sym_blk.shsym->sh_size));
// return total amount of symbol block
return (_sym_blk.header_size + ROUND4(_sym_blk.shstr->sh_size) +
_sym_blk.shsym->sh_size);
}
void
ElfLoader::load_symbol_block(vaddr_t kv)
{
size_t sz;
if (!_sym_blk.enable)
return;
// load header
_load_memory(kv, _sym_blk.header_size, _sym_blk.header);
kv += _sym_blk.header_size;
// load string table
sz = _sym_blk.shstr->sh_size;
_load_segment(kv, sz, _sym_blk.stroff, sz);
kv += ROUND4(sz);
// load symbol table
sz = _sym_blk.shsym->sh_size;
_load_segment(kv, sz, _sym_blk.symoff, sz);
}
BOOL
ElfLoader::read_header(void)
ElfLoader::read_header()
{
// read ELF header
_file->read(&_eh, sizeof(Elf_Ehdr), 0);
@ -208,7 +279,7 @@ ElfLoader::read_header(void)
return FALSE;
}
/* Check object type */
// Check object type
if (_eh.e_type != ET_EXEC) {
DPRINTF((TEXT("not a executable file. type = %d\n"),
_eh.e_type));

View File

@ -1,4 +1,4 @@
/* -*-C++-*- $NetBSD: load_elf.h,v 1.3 2001/05/08 18:51:23 uch Exp $ */
/* -*-C++-*- $NetBSD: load_elf.h,v 1.4 2001/07/03 20:38:03 uch Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -47,6 +47,16 @@ private:
Elf_Phdr _ph[16];
Elf_Shdr _sh[16];
struct _symbol_block {
BOOL enable;
char *header;
size_t header_size;
Elf_Shdr *shstr;
off_t stroff;
Elf_Shdr *shsym;
off_t symoff;
} _sym_blk;
BOOL is_elf_file(void) {
return
_eh.e_ident[EI_MAG0] == ELFMAG0 &&
@ -56,6 +66,8 @@ private:
}
BOOL read_header(void);
struct PageTag *load_page(vaddr_t, off_t, size_t, struct PageTag *);
size_t symbol_block_size(void);
void load_symbol_block(vaddr_t);
public:
ElfLoader(Console *&, MemoryManager *&);