summaryrefslogtreecommitdiffstats
path: root/usr.sbin/kvm_mkdb
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1998-10-28 06:39:41 +0000
committerjdp <jdp@FreeBSD.org>1998-10-28 06:39:41 +0000
commit3794f7fb2b2fd1531a0f4c26edd11cd7cfe7c48e (patch)
treea14ff03c8cf8040e2bc61d91c6f327dfe9f59b3b /usr.sbin/kvm_mkdb
parentd68c1863e92b2b8a1bcac0b8a895c722649b4f63 (diff)
downloadFreeBSD-src-3794f7fb2b2fd1531a0f4c26edd11cd7cfe7c48e.zip
FreeBSD-src-3794f7fb2b2fd1531a0f4c26edd11cd7cfe7c48e.tar.gz
Handle ELF symbols better. This fixes "vmstat -i" for the case
where "/var/db/kvm_kernel.db" exists. Note, kvm_mkdb tries to be clever, and skips rebuilding the database if it thinks it's already up to date. To see the effects of this fix, you may need to manually delete "/var/db/kvm_kernel.db" and then run "kvm_mkdb".
Diffstat (limited to 'usr.sbin/kvm_mkdb')
-rw-r--r--usr.sbin/kvm_mkdb/nlist.c71
1 files changed, 50 insertions, 21 deletions
diff --git a/usr.sbin/kvm_mkdb/nlist.c b/usr.sbin/kvm_mkdb/nlist.c
index b1c7403..e3e0666 100644
--- a/usr.sbin/kvm_mkdb/nlist.c
+++ b/usr.sbin/kvm_mkdb/nlist.c
@@ -29,6 +29,8 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $FreeBSD$
*/
#ifndef lint
@@ -36,7 +38,7 @@
static char sccsid[] = "@(#)from: nlist.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
- "$Id: nlist.c,v 1.8 1997/09/24 06:44:10 charnier Exp $";
+ "$Id: nlist.c,v 1.9 1998/08/17 08:46:46 dfr Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -180,14 +182,16 @@ __aout_knlist(name, db)
#ifdef DO_ELF
+static void elf_sym_to_nlist __P((struct nlist *, Elf_Sym *, Elf_Shdr *, int));
+
int
__elf_knlist(name, db)
char *name;
DB *db;
{
register caddr_t strtab;
- register off_t symstroff, symoff;
- register u_long symsize;
+ register off_t symstroff = 0, symoff = 0;
+ register u_long symsize = 0;
register u_long kernvma, kernoffs;
register int i;
Elf_Sym *sbuf;
@@ -241,6 +245,8 @@ __elf_knlist(name, db)
kernoffs = sh[i].sh_offset;
}
}
+ if (symsize == 0)
+ badfmt("stripped");
strtab = (char *)&filep[symstroff];
@@ -253,24 +259,7 @@ __elf_knlist(name, db)
sbuf = (Elf_Sym *)&filep[symoff + i * sizeof(*sbuf)];
if (!sbuf->st_name)
continue;
-
- nbuf.n_value = sbuf->st_value;
-
- /*XXX type conversion is pretty rude... */
- switch (ELF_ST_TYPE(sbuf->st_info)) {
- case STT_NOTYPE:
- nbuf.n_type = N_UNDF;
- break;
- case STT_FUNC:
- nbuf.n_type = N_TEXT;
- break;
- case STT_OBJECT:
- nbuf.n_type = N_DATA;
- break;
- }
- if (ELF_ST_BIND(sbuf->st_info) == STB_LOCAL)
- nbuf.n_type = N_EXT;
-
+ elf_sym_to_nlist(&nbuf, sbuf, sh, eh->e_shnum);
key.data = (u_char *)(strtab + sbuf->st_name);
key.size = strlen((char *)key.data);
if (db->put(db, &key, &data, 0))
@@ -311,6 +300,46 @@ __elf_knlist(name, db)
(void)close(fd);
return(0);
}
+
+/*
+ * Convert an Elf_Sym into an nlist structure. This fills in only the
+ * n_value and n_type members.
+ */
+static void
+elf_sym_to_nlist(nl, s, shdr, shnum)
+ struct nlist *nl;
+ Elf_Sym *s;
+ Elf_Shdr *shdr;
+ int shnum;
+{
+ nl->n_value = s->st_value;
+
+ switch (s->st_shndx) {
+ case SHN_UNDEF:
+ case SHN_COMMON:
+ nl->n_type = N_UNDF;
+ break;
+ case SHN_ABS:
+ nl->n_type = ELF_ST_TYPE(s->st_info) == STT_FILE ?
+ N_FN : N_ABS;
+ break;
+ default:
+ if (s->st_shndx >= shnum)
+ nl->n_type = N_UNDF;
+ else {
+ Elf_Shdr *sh = shdr + s->st_shndx;
+
+ nl->n_type = sh->sh_type == SHT_PROGBITS ?
+ (sh->sh_flags & SHF_WRITE ? N_DATA : N_TEXT) :
+ (sh->sh_type == SHT_NOBITS ? N_BSS : N_UNDF);
+ }
+ break;
+ }
+
+ if (ELF_ST_BIND(s->st_info) == STB_GLOBAL ||
+ ELF_ST_BIND(s->st_info) == STB_WEAK)
+ nl->n_type |= N_EXT;
+}
#endif /* DO_ELF */
static struct knlist_handlers {
OpenPOWER on IntegriCloud