Subject: kdump & emulation-pid map
To: None <tech-userlevel@NetBSD.ORG>
From: Niklas Hallqvist <niklas@appli.se>
List: tech-userlevel
Date: 08/22/1995 19:46:21
OK I went ahead as I needed the functionality anyway, here's the
patch.  I hope the style is OK, I'm mostly a GNU style coder
otherwise.  It works OK on my testcase, I might add.

Niklas

Index: kdump.c
===================================================================
RCS file: /u3/CVSROOT/NetBSD/src/usr.bin/kdump/kdump.c,v
retrieving revision 1.1.1.6
retrieving revision 1.1.1.1.2.9
diff -c -r1.1.1.6 -r1.1.1.1.2.9
*** kdump.c     1995/07/31 12:15:29     1.1.1.6
--- kdump.c     1995/08/22 18:11:11     1.1.1.1.2.9
***************
*** 109,116 ****
--- 109,134 ----
        { NULL,                      NULL,                  NULL }
  };
  
+ struct emulation_map {
+       struct emulation_map *em_link;
+       pid_t                em_pid;
+       struct emulation     *em_emulation;
+ };
+ 
+ /* Forward decls. */
+ struct emulation *emulation_from_name __P((char *name));
+ struct emulation *emulation_from_pid __P((pid_t pid));
+ void bind_emulation_to_pid __P((struct emulation *, pid_t));
+ 
+ /* A mapping between pids and emulations currently in charge.  */
+ struct emulation_map *current_emulations;
+ 
+ /* The current emulation (cache during a single trace event).  */
  struct emulation *current;
  
+ /* The default emulation, if nothing else is known.  */
+ struct emulation *default_emulation;
+ 
  
  static char *ptrace_ops[] = {
        "PT_TRACE_ME",  "PT_READ_I",    "PT_READ_D",    "PT_READ_U",
***************
*** 127,138 ****
        register void *m;
        int trpoints = ALL_POINTS;
  
!       current = &emulations[0];       /* NetBSD */
  
        while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
                switch (ch) {
                case 'e':
!                       setemul(optarg);
                        break;
                case 'f':
                        tracefile = optarg;
--- 145,156 ----
        register void *m;
        int trpoints = ALL_POINTS;
  
!       default_emulation = &emulations[0];     /* NetBSD */
  
        while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
                switch (ch) {
                case 'e':
!                       default_emulation = emulation_from_name(optarg);
                        break;
                case 'f':
                        tracefile = optarg;
***************
*** 175,180 ****
--- 193,199 ----
        if (!freopen(tracefile, "r", stdin))
                err(1, "%s", tracefile);
        while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
+               current = emulation_from_pid(ktr_header.ktr_pid);
                if (trpoints & (1<<ktr_header.ktr_type))
                        dumpheader(&ktr_header);
                if ((ktrlen = ktr_header.ktr_len) < 0)
***************
*** 209,215 ****
                        ktrcsw((struct ktr_csw *)m);
                        break;
                case KTR_EMUL:
!                       ktremul(m, ktrlen);
                        break;
                }
                if (tail)
--- 228,234 ----
                        ktrcsw((struct ktr_csw *)m);
                        break;
                case KTR_EMUL:
!                       ktremul(m, ktrlen, ktr_header.ktr_pid);
                        break;
                }
                if (tail)
***************
*** 378,385 ****
        (void)printf("\"%.*s\"\n", len, cp);
  }
  
! ktremul(cp, len) 
        char *cp;
  {
        char name[1024];
  
--- 397,405 ----
        (void)printf("\"%.*s\"\n", len, cp);
  }
  
! ktremul(cp, len, pid) 
        char *cp;
+       pid_t pid;
  {
        char name[1024];
  
***************
*** 390,396 ****
        name[len] = '\0';
        (void)printf("\"%s\"\n", name);
  
!       setemul(name);
  }
  
  ktrgenio(ktr, len)
--- 410,416 ----
        name[len] = '\0';
        (void)printf("\"%s\"\n", name);
  
!       bind_emulation_to_pid(emulation_from_name(name), pid);
  }
  
  ktrgenio(ktr, len)
***************
*** 481,494 ****
        exit(1);
  }
  
! setemul(name)
        char *name;
  {
        int i;
        for (i = 0; emulations[i].name != NULL; i++)
                if (strcmp(emulations[i].name, name) == 0) {
!                       current = &emulations[i];
!                       return;
                }
        warnx("Emulation `%s' unknown", name);
  }
--- 501,549 ----
        exit(1);
  }
  
! struct emulation *
! emulation_from_name(name)
        char *name;
  {
        int i;
        for (i = 0; emulations[i].name != NULL; i++)
                if (strcmp(emulations[i].name, name) == 0) {
!                       return &emulations[i];
                }
        warnx("Emulation `%s' unknown", name);
+       return default_emulation;
+ }
+ 
+ struct emulation *
+ emulation_from_pid(pid)
+       pid_t pid;
+ {
+       struct emulation_map *entry;
+ 
+       for (entry = current_emulations; entry; entry = entry->em_link)
+               if (entry->em_pid == pid)
+                       return entry->em_emulation;
+       return default_emulation;
+ }
+ 
+ void
+ bind_emulation_to_pid(emulation, pid)
+       struct emulation *emulation;
+       pid_t            pid;
+ {
+       struct emulation_map *entry;
+ 
+       for (entry = current_emulations; entry; entry = entry->em_link)
+               if (entry->em_pid == pid) {
+                       entry->em_emulation = emulation;
+                       return;
+               }
+       entry = current_emulations;
+       current_emulations =
+           (struct emulation_map *)malloc(sizeof(struct emulation_map));
+       if (current_emulations == NULL)
+               errx(1, "%s", strerror(ENOMEM));
+       current_emulations->em_link = entry;
+       current_emulations->em_pid = pid;
+       current_emulations->em_emulation = emulation;
  }