Subject: symbol table support for hpcboot
To: None <uch@netbsd.org>
From: IWAMOTO Toshihiro <iwamoto@sat.t.u-tokyo.ac.jp>
List: port-hpcmips
Date: 03/21/2001 02:51:41
--Multipart_Wed_Mar_21_02:51:41_2001-1
Content-Type: text/plain; charset=US-ASCII

Though hpcboot works great with my jornada720 (NetBSD/hpcarm), I'm
totally tired playing with ddb without symbol table support.
I'd like to commit changes something like the follwing to hpcboot,
which enables use of ddb with symbols.

Main differences from pbsdboot are:

1. Elf_Ehdr's e_entry remains zero.  So it cannot be used for
  determining symbol table size as hpcmips currently does.  I don't
  think using e_entry for such a purpose is a good idea (Am I
  paranoid?).  Anyway, symbol table sizes can be read from section
  headers.  And it should be easy to make hpcmips kernel work both for
  pbsdboot format and this proposed format.

2. All of the section headers are preserved, so that the area of
  kernel text can be read.  This is necessary when someone wants to map
  kernel text readonly.

Any opinions?

--
IWAMOTO Toshihiro


--Multipart_Wed_Mar_21_02:51:41_2001-1
Content-Type: application/octet-stream; type=patch
Content-Disposition: attachment; filename="hpcboot.diff"
Content-Transfer-Encoding: 7bit

Index: hpc/stand/hpcboot/load.cpp
===================================================================
RCS file: /amd/kiku/NetBSD/NetBSD-CVS/syssrc/sys/arch/hpc/stand/hpcboot/load.cpp,v
retrieving revision 1.1
diff -u -r1.1 load.cpp
--- hpc/stand/hpcboot/load.cpp	2001/02/09 18:34:44	1.1
+++ hpc/stand/hpcboot/load.cpp	2001/03/20 15:08:45
@@ -201,6 +201,37 @@
 	_kernend = kv + memsz;
 }
 
+void
+Loader::_load_memory(vaddr_t kv, vsize_t memsz, void *data)
+{
+	struct PageTag *pvec;
+	vaddr_t kv_start = kv, v;
+	paddr_t p, pvec_paddr;
+
+	DPRINTF((TEXT("\t->load 0x%08x+0x%08x=0x%08x\n"),
+		 kv, memsz, kv + memsz));
+	if (memsz > _tpsz) {
+		/* XXX failure */
+		return;
+	}
+
+	_opvec_prev = _pvec_prev;
+	_mem->getTaggedPage(v, p, &pvec, pvec_paddr);      
+	memcpy((void *)v, data, memsz);
+	_pvec_prev->src = ptokv(p);
+	_pvec_prev->dst = kv;
+	_pvec_prev->sz = memsz;
+#ifdef PAGE_LINK_DUMP
+	_pvec_prev->next =(u_int32_t)pvec;
+#else
+	_pvec_prev->next = ptokv(pvec_paddr);
+#endif
+	_pvec_prev = pvec;
+
+	_kernend = kv + memsz;
+	++_nload_link;
+}
+
 struct PageTag *
 Loader::_load_page(vaddr_t kv, off_t ofs, size_t sz, struct PageTag *prev)
 {
Index: hpc/stand/hpcboot/load.h
===================================================================
RCS file: /amd/kiku/NetBSD/NetBSD-CVS/syssrc/sys/arch/hpc/stand/hpcboot/load.h,v
retrieving revision 1.1
diff -u -r1.1 load.h
--- hpc/stand/hpcboot/load.h	2001/02/09 18:34:44	1.1
+++ hpc/stand/hpcboot/load.h	2001/03/19 17:32:46
@@ -68,6 +68,7 @@
 
 	void _load_segment_start(void);
 	void _load_segment(vaddr_t, vsize_t, off_t, size_t);
+	void _load_memory(vaddr_t, vsize_t, void *);
 	void _load_segment_end(void);
 
 public:
Index: hpc/stand/hpcboot/load_elf.cpp
===================================================================
RCS file: /amd/kiku/NetBSD/NetBSD-CVS/syssrc/sys/arch/hpc/stand/hpcboot/load_elf.cpp,v
retrieving revision 1.1
diff -u -r1.1 load_elf.cpp
--- hpc/stand/hpcboot/load_elf.cpp	2001/02/09 18:34:46	1.1
+++ hpc/stand/hpcboot/load_elf.cpp	2001/03/20 16:43:09
@@ -81,6 +81,9 @@
 			sz += _mem->roundPage(filesz);
 		}
 	}
+	/* XXX reserve 192kB for symbols */
+	sz += 0x30000;
+
 	DPRINTF((TEXT(" = 0x%x byte\n"), sz));
 	return sz;
 }
@@ -96,6 +99,11 @@
 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();
@@ -104,13 +112,61 @@
 		if (ph->p_type == PT_LOAD) {
 			size_t filesz = ph->p_filesz;
 			size_t memsz = ph->p_memsz;
-			vaddr_t kv = ph->p_vaddr;
+			kv = ph->p_vaddr;
 			off_t fileofs = ph->p_offset;
 			DPRINTF((TEXT("[%d] vaddr 0x%08x file size 0x%x mem size 0x%x\n"),
 				 i, kv, filesz, memsz));
 			_load_segment(kv, memsz, fileofs, filesz);
+			kv += memsz;
 		}
 	}
+
+	/*
+	 * 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;
+	_file->read(buf + off, _eh.e_shentsize * _eh.e_shnum, _eh.e_shoff);
+	sh = (Elf_Shdr *)(buf + off);
+
+	off += _eh.e_shentsize * _eh.e_shnum;
+	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 */
 
 	return TRUE;

--Multipart_Wed_Mar_21_02:51:41_2001-1--