1 /* 2 * Copyright (c) 2004 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD: src/gnu/usr.bin/gdb/kgdb/kthr.c,v 1.12 2008/05/01 20:36:48 jhb Exp $ 27 */ 28 29 #include <sys/cdefs.h> 30 31 #include <sys/param.h> 32 #include <machine/globaldata.h> 33 #include <sys/user.h> 34 #include <sys/types.h> 35 #include <sys/signal.h> 36 #include <err.h> 37 #include <inttypes.h> 38 #include <kvm.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 #include <defs.h> 44 #include <frame-unwind.h> 45 #include <inferior.h> 46 47 #include "kgdb.h" 48 49 static CORE_ADDR dumppcb; 50 static int dumptid; 51 52 static struct kthr *first; 53 struct kthr *curkthr; 54 55 CORE_ADDR 56 kgdb_lookup(const char *sym) 57 { 58 struct nlist nl[2]; 59 60 nl[0].n_name = (char *)(CORE_ADDR)sym; 61 nl[1].n_name = NULL; 62 if (kvm_nlist(kvm, nl) != 0) 63 return (0); 64 return (nl[0].n_value); 65 } 66 67 struct kthr * 68 kgdb_thr_first(void) 69 { 70 return (first); 71 } 72 73 struct kthr * 74 kgdb_thr_init(void) 75 { 76 struct proc p; 77 struct thread td; 78 struct lwp lwp; 79 struct mdglobaldata gd; 80 struct kthr *kt; 81 CORE_ADDR addr, paddr, prvspace; 82 int cpu, ncpus; 83 84 while (first != NULL) { 85 kt = first; 86 first = kt->next; 87 free(kt); 88 } 89 90 addr = kgdb_lookup("_ncpus"); 91 if (addr == 0) 92 return (NULL); 93 kvm_read(kvm, addr, &ncpus, sizeof(ncpus)); 94 95 dumppcb = kgdb_lookup("_dumppcb"); 96 if (dumppcb == 0) 97 return (NULL); 98 99 prvspace = kgdb_lookup("_CPU_prvspace"); 100 if (prvspace == 0) 101 return (NULL); 102 103 addr = kgdb_lookup("_dumpthread"); 104 if (addr != 0) { 105 kvm_read(kvm, addr, &dumptid, sizeof(dumptid)); 106 } else { 107 /* 108 * XXX Well then. We don't know who dumped us. 109 * We could do some fancy stack matching, but 110 * I doubt this will work. For now just use 111 * cpu0's curthread. 112 * 113 * Actually we don't even know if we were dumped 114 * or if we are life. Find out by querying "dumping". 115 */ 116 int dumping = 0; 117 118 addr = kgdb_lookup("_dumping"); 119 kvm_read(kvm, addr, &dumping, sizeof(dumping)); 120 if (dumping) { 121 kvm_read(kvm, prvspace + 122 offsetof(struct privatespace, mdglobaldata), 123 &gd, sizeof(struct mdglobaldata)); 124 dumptid = (intptr_t)gd.mi.gd_curthread; 125 } else { 126 /* We must be a live system */ 127 dumptid = -1; 128 } 129 } 130 131 for (cpu = 0; cpu < ncpus; cpu++) { 132 kvm_read(kvm, prvspace + 133 cpu * sizeof(struct privatespace) + 134 offsetof(struct privatespace, mdglobaldata), 135 &gd, sizeof(struct mdglobaldata)); 136 137 addr = (uintptr_t)TAILQ_FIRST(&gd.mi.gd_tdallq); 138 while (addr != 0) { 139 if (kvm_read(kvm, addr, &td, sizeof(td)) != sizeof(td)) { 140 warnx("kvm_read: %s, while accessing thread", 141 kvm_geterr(kvm)); 142 break; 143 } 144 kt = malloc(sizeof(*kt)); 145 kt->next = first; 146 kt->kaddr = addr; 147 kt->tid = addr; /* XXX do we have tids? */ 148 kt->pcb = (kt->tid == dumptid) ? dumppcb : 149 (uintptr_t)td.td_pcb; 150 kt->kstack = (uintptr_t)td.td_kstack; 151 if (td.td_proc != NULL) { 152 paddr = (uintptr_t)td.td_proc; 153 if (kvm_read(kvm, paddr, &p, sizeof(p)) != sizeof(p)) 154 warnx("kvm_read: %s", kvm_geterr(kvm)); 155 kt->pid = p.p_pid; 156 kt->paddr = paddr; 157 addr = (uintptr_t)td.td_lwp; 158 if (kvm_read(kvm, addr, &lwp, sizeof(lwp)) != sizeof(lwp)) 159 warnx("kvm_read: %s", kvm_geterr(kvm)); 160 kt->lwpid = lwp.lwp_tid; 161 } else { 162 /* 163 * XXX for some stupid reason, gdb uses pid == -1 164 * as a marker for "dead" threads, so we have to 165 * hook all kernel threads on a different pid :/ 166 */ 167 kt->pid = -2; 168 kt->paddr = 0; 169 /* 170 * We are a kernel thread, so our td_pcb is 171 * not used anyways. An exception is the 172 * dumping thread. 173 * kt->pcb == 0 is a marker for 174 * "non-dumping kernel thread". 175 */ 176 if (kt->tid != dumptid) 177 kt->pcb = 0; 178 } 179 first = kt; 180 addr = (uintptr_t)TAILQ_NEXT(&td, td_allq); 181 } 182 } 183 184 curkthr = kgdb_thr_lookup_tid(dumptid); 185 if (curkthr == NULL) 186 curkthr = first; 187 return (first); 188 } 189 190 struct kthr * 191 kgdb_thr_lookup_tid(int tid) 192 { 193 struct kthr *kt; 194 195 kt = first; 196 while (kt != NULL && kt->tid != tid) 197 kt = kt->next; 198 return (kt); 199 } 200 201 struct kthr * 202 kgdb_thr_lookup_taddr(uintptr_t taddr) 203 { 204 struct kthr *kt; 205 206 kt = first; 207 while (kt != NULL && kt->kaddr != taddr) 208 kt = kt->next; 209 return (kt); 210 } 211 212 struct kthr * 213 kgdb_thr_lookup_pid(int pid) 214 { 215 struct kthr *kt; 216 217 kt = first; 218 while (kt != NULL && kt->pid != pid) 219 kt = kt->next; 220 return (kt); 221 } 222 223 struct kthr * 224 kgdb_thr_lookup_paddr(uintptr_t paddr) 225 { 226 struct kthr *kt; 227 228 kt = first; 229 while (kt != NULL && kt->paddr != paddr) 230 kt = kt->next; 231 return (kt); 232 } 233 234 struct kthr * 235 kgdb_thr_next(struct kthr *kt) 236 { 237 return (kt->next); 238 } 239 240 struct kthr * 241 kgdb_thr_select(struct kthr *kt) 242 { 243 struct kthr *pcur; 244 245 pcur = curkthr; 246 curkthr = kt; 247 return (pcur); 248 } 249 250 char * 251 kgdb_thr_extra_thread_info(int tid) 252 { 253 struct kthr *kt; 254 static char buf[64]; 255 256 kt = kgdb_thr_lookup_tid(tid); 257 if (kt == NULL) 258 return (NULL); 259 260 buf[0] = 0; 261 262 return (NULL); 263 } 264 265 char * 266 kgdb_thr_pid_to_str(ptid_t ptid) 267 { 268 char comm[MAXCOMLEN + 1]; 269 struct kthr *kt; 270 struct proc *p; 271 struct thread *t; 272 static char buf[64]; 273 int tid; 274 275 tid = ptid_get_tid(ptid); 276 if (tid == 0) 277 kt = kgdb_thr_lookup_pid(ptid_get_pid(ptid)); 278 else 279 kt = kgdb_thr_lookup_tid(tid); 280 281 if (kt == NULL) 282 return (NULL); 283 284 buf[0] = 0; 285 286 if (kt->pid != -2) { 287 snprintf(buf, sizeof(buf), "pid %d", kt->pid); 288 289 if (tid != 0) 290 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 291 "/%d", kt->lwpid); 292 293 p = (struct proc *)kt->paddr; 294 if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) != 295 sizeof(comm)) 296 return (buf); 297 298 strlcat(buf, ", ", sizeof(buf)); 299 strlcat(buf, comm, sizeof(buf)); 300 } else { 301 strcpy(buf, "kernel"); 302 303 if (tid != 0) { 304 t = (struct thread *)kt->kaddr; 305 if (kvm_read(kvm, (uintptr_t)&t->td_comm[0], &comm, 306 sizeof(comm)) == sizeof(comm)) { 307 strlcat(buf, " ", sizeof(buf)); 308 strlcat(buf, comm, sizeof(buf)); 309 } 310 } 311 } 312 313 return (buf); 314 } 315