ectx_find() failed to lookup the emulation context unless it happened

to be the first entry, effectively resetting context of all processes to
default emulation on every EMUL trace record

rewrite ectx_find() to fix this, using <sys/queue.h> LIST for readability

this fix should once and for all remove need to ever use -e option,
and makes kdump work properly for traces with processes under different
emulations
This commit is contained in:
jdolecek 2005-01-15 17:55:38 +00:00
parent 82318e9375
commit 04fa39a4be
1 changed files with 36 additions and 37 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: setemul.c,v 1.19 2004/01/12 13:39:56 mrg Exp $ */ /* $NetBSD: setemul.c,v 1.20 2005/01/15 17:55:38 jdolecek Exp $ */
/*- /*-
* Copyright (c) 2000 The NetBSD Foundation, Inc. * Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -69,12 +69,13 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__RCSID("$NetBSD: setemul.c,v 1.19 2004/01/12 13:39:56 mrg Exp $"); __RCSID("$NetBSD: setemul.c,v 1.20 2005/01/15 17:55:38 jdolecek Exp $");
#endif /* not lint */ #endif /* not lint */
#include <sys/param.h> #include <sys/param.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/queue.h>
#include <err.h> #include <err.h>
#include <stdio.h> #include <stdio.h>
@ -235,7 +236,7 @@ const struct emulation emulations[] = {
struct emulation_ctx { struct emulation_ctx {
pid_t pid; pid_t pid;
const struct emulation *emulation; const struct emulation *emulation;
struct emulation_ctx *next; LIST_ENTRY(emulation_ctx) ctx_link;
}; };
const struct emulation *cur_emul; const struct emulation *cur_emul;
@ -248,8 +249,8 @@ static const struct emulation *mach_fasttraps;
static const struct emulation *default_emul = &emulations[0]; static const struct emulation *default_emul = &emulations[0];
struct emulation_ctx *current_ctx; struct emulation_ctx *current_ctx;
static struct emulation_ctx emul_0 = {0, &emulations[0], NULL}; static LIST_HEAD(, emulation_ctx) emul_ctx =
struct emulation_ctx *emul_ctx = &emul_0; LIST_HEAD_INITIALIZER(emul_ctx);
static struct emulation_ctx *ectx_find(pid_t); static struct emulation_ctx *ectx_find(pid_t);
static void ectx_update(pid_t, const struct emulation *); static void ectx_update(pid_t, const struct emulation *);
@ -300,31 +301,30 @@ setemul(const char *name, pid_t pid, int update_ectx)
static struct emulation_ctx * static struct emulation_ctx *
ectx_find(pid_t pid) ectx_find(pid_t pid)
{ {
struct emulation_ctx *ctx, **pctx; struct emulation_ctx *ctx;
/* Top of list is almost always right... (and list is never empty) */ /* Find an existing entry */
if (emul_ctx->pid == pid) LIST_FOREACH(ctx, &emul_ctx, ctx_link) {
return emul_ctx; if (ctx->pid == pid)
for (pctx = &emul_ctx; ; pctx = &ctx->next) {
ctx = *pctx;
if (ctx == NULL) {
/* create entry with default emulation */
ctx = malloc(sizeof *ctx);
if (ctx == NULL)
err(1, "malloc emul context");
ctx->pid = pid;
ctx->emulation = default_emul;
break; break;
}
if (ctx->pid != pid)
continue;
/* Cut out of chain */
*pctx = ctx->next;
} }
/* Add at chain head */
ctx->next = emul_ctx; if (ctx == NULL) {
emul_ctx = ctx; /* create entry with default emulation */
ctx = malloc(sizeof *ctx);
if (ctx == NULL)
err(1, "malloc emul context");
ctx->pid = pid;
ctx->emulation = default_emul;
/* chain into the list */
LIST_INSERT_HEAD(&emul_ctx, ctx, ctx_link);
} else {
/* move entry to head to optimize lookup for syscall bursts */
LIST_REMOVE(ctx, ctx_link);
LIST_INSERT_HEAD(&emul_ctx, ctx, ctx_link);
}
return ctx; return ctx;
} }
@ -361,20 +361,19 @@ ectx_sanify(pid_t pid)
void void
ectx_delete(void) ectx_delete(void)
{ {
static struct emulation_ctx *ctx; static struct emulation_ctx *ctx = NULL;
struct emulation_ctx *nctx;
if (ctx != NULL) if (ctx != NULL)
free(ctx); free(ctx);
nctx = emul_ctx->next; /*
if (nctx == NULL) { * The emulation for current syscall entry is always on HEAD, due
/* sanity - last item on list should never be killed */ * to code in ectx_find().
ctx = NULL; */
return; ctx = LIST_FIRST(&emul_ctx);
}
ctx = emul_ctx; if (ctx)
emul_ctx = nctx; LIST_REMOVE(ctx, ctx_link);
} }
/* /*