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 CORE_ADDR dumptid; 51 52 static struct kthr *first; 53 struct kthr *curkthr; 54 55 #define LIVESYS_DUMPTID 10 56 57 CORE_ADDR 58 kgdb_lookup(const char *sym) 59 { 60 struct nlist nl[2]; 61 62 nl[0].n_name = (char *)(CORE_ADDR)sym; 63 nl[1].n_name = NULL; 64 if (kvm_nlist(kvm, nl) != 0) 65 return (0); 66 return (nl[0].n_value); 67 } 68 69 struct kthr * 70 kgdb_thr_first(void) 71 { 72 return (first); 73 } 74 75 struct kthr * 76 kgdb_thr_init(void) 77 { 78 struct proc p; 79 struct thread td; 80 struct lwp lwp; 81 struct mdglobaldata gd; 82 struct kthr *kt; 83 CORE_ADDR addr, paddr, prvspace; 84 int cpu, ncpus; 85 86 while (first != NULL) { 87 kt = first; 88 first = kt->next; 89 free(kt); 90 } 91 92 addr = kgdb_lookup("_ncpus"); 93 if (addr == 0) 94 return (NULL); 95 kvm_read(kvm, addr, &ncpus, sizeof(ncpus)); 96 97 dumppcb = kgdb_lookup("_dumppcb"); 98 if (dumppcb == 0) 99 return (NULL); 100 101 prvspace = kgdb_lookup("_CPU_prvspace"); 102 if (prvspace == 0) 103 return (NULL); 104 105 addr = kgdb_lookup("_dumpthread"); 106 if (addr != 0) { 107 kvm_read(kvm, addr, &dumptid, sizeof(dumptid)); 108 } else { 109 /* 110 * XXX Well then. We don't know who dumped us. 111 * We could do some fancy stack matching, but 112 * I doubt this will work. For now just use 113 * cpu0's curthread. 114 * 115 * Actually we don't even know if we were dumped 116 * or if we are live. Find out by querying "dumping". 117 */ 118 int dumping = 0; 119 120 addr = kgdb_lookup("_dumping"); 121 kvm_read(kvm, addr, &dumping, sizeof(dumping)); 122 if (dumping) { 123 kvm_read(kvm, prvspace + 124 offsetof(struct privatespace, mdglobaldata), 125 &gd, sizeof(struct mdglobaldata)); 126 dumptid = (CORE_ADDR)gd.mi.gd_curthread; 127 } else { 128 /* We must be a live system */ 129 dumptid = LIVESYS_DUMPTID; 130 } 131 } 132 133 for (cpu = 0; cpu < ncpus; cpu++) { 134 kvm_read(kvm, prvspace + 135 cpu * sizeof(struct privatespace) + 136 offsetof(struct privatespace, mdglobaldata), 137 &gd, sizeof(struct mdglobaldata)); 138 139 addr = (uintptr_t)TAILQ_FIRST(&gd.mi.gd_tdallq); 140 while (addr != 0) { 141 if (kvm_read(kvm, addr, &td, sizeof(td)) != sizeof(td)) { 142 warnx("kvm_read: %s, while accessing thread", 143 kvm_geterr(kvm)); 144 break; 145 } 146 kt = malloc(sizeof(*kt)); 147 kt->next = first; 148 kt->kaddr = addr; 149 kt->tid = addr; 150 kt->pcb = (kt->tid == dumptid) ? dumppcb : 151 (uintptr_t)td.td_pcb; 152 kt->kstack = (uintptr_t)td.td_kstack; 153 if (td.td_proc != NULL) { 154 paddr = (uintptr_t)td.td_proc; 155 if (kvm_read(kvm, paddr, &p, sizeof(p)) != sizeof(p)) 156 warnx("kvm_read: %s", kvm_geterr(kvm)); 157 kt->pid = p.p_pid; 158 kt->paddr = paddr; 159 addr = (uintptr_t)td.td_lwp; 160 if (kvm_read(kvm, addr, &lwp, sizeof(lwp)) != sizeof(lwp)) 161 warnx("kvm_read: %s", kvm_geterr(kvm)); 162 kt->lwpid = lwp.lwp_tid; 163 } else { 164 /* 165 * XXX for some stupid reason, gdb uses pid == -1 166 * as a marker for "dead" threads, so we have to 167 * hook all kernel threads on a different pid :/ 168 */ 169 kt->pid = -2; 170 kt->paddr = 0; 171 /* 172 * We are a kernel thread, so our td_pcb is 173 * not used anyways. An exception is the 174 * dumping thread. 175 * kt->pcb == 0 is a marker for 176 * "non-dumping kernel thread". 177 */ 178 if (kt->tid != dumptid) 179 kt->pcb = 0; 180 } 181 first = kt; 182 addr = (uintptr_t)TAILQ_NEXT(&td, td_allq); 183 } 184 } 185 186 curkthr = kgdb_thr_lookup_tid(dumptid); 187 if (curkthr == NULL) 188 curkthr = first; 189 return (first); 190 } 191 192 struct kthr * 193 kgdb_thr_lookup_tid(CORE_ADDR tid) 194 { 195 struct kthr *kt; 196 197 kt = first; 198 while (kt != NULL && kt->tid != tid) 199 kt = kt->next; 200 return (kt); 201 } 202 203 struct kthr * 204 kgdb_thr_lookup_taddr(uintptr_t taddr) 205 { 206 struct kthr *kt; 207 208 kt = first; 209 while (kt != NULL && kt->kaddr != taddr) 210 kt = kt->next; 211 return (kt); 212 } 213 214 struct kthr * 215 kgdb_thr_lookup_pid(int pid) 216 { 217 struct kthr *kt; 218 219 kt = first; 220 while (kt != NULL && kt->pid != pid) 221 kt = kt->next; 222 return (kt); 223 } 224 225 struct kthr * 226 kgdb_thr_lookup_paddr(uintptr_t paddr) 227 { 228 struct kthr *kt; 229 230 kt = first; 231 while (kt != NULL && kt->paddr != paddr) 232 kt = kt->next; 233 return (kt); 234 } 235 236 struct kthr * 237 kgdb_thr_next(struct kthr *kt) 238 { 239 return (kt->next); 240 } 241 242 struct kthr * 243 kgdb_thr_select(struct kthr *kt) 244 { 245 struct kthr *pcur; 246 247 pcur = curkthr; 248 curkthr = kt; 249 return (pcur); 250 } 251 252 char * 253 kgdb_thr_extra_thread_info(CORE_ADDR tid) 254 { 255 #if 0 /* Information already provided */ 256 struct kthr *kt; 257 static char buf[64]; 258 struct proc *p; 259 char comm[MAXCOMLEN + 1]; 260 261 kt = kgdb_thr_lookup_tid(tid); 262 if (kt == NULL) 263 return (NULL); 264 265 snprintf(buf, sizeof(buf), "PID=%d", kt->pid); 266 p = (struct proc *)kt->paddr; 267 if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) == 268 sizeof(comm)) { 269 strlcat(buf, ": ", sizeof(buf)); 270 strlcat(buf, comm, sizeof(buf)); 271 } 272 return (buf); 273 #endif 274 return (NULL); 275 } 276 277 char * 278 kgdb_thr_pid_to_str(ptid_t ptid) 279 { 280 char comm[MAXCOMLEN + 1]; 281 struct kthr *kt; 282 struct proc *p; 283 struct thread *t; 284 static char buf[64]; 285 CORE_ADDR tid; 286 287 tid = ptid_get_tid(ptid); 288 if (tid == 0) 289 kt = kgdb_thr_lookup_pid(ptid_get_pid(ptid)); 290 else 291 kt = kgdb_thr_lookup_tid(tid); 292 293 if (kt == NULL) 294 return (NULL); 295 296 buf[0] = 0; 297 298 if (kt->pid != -2) { 299 snprintf(buf, sizeof(buf), "pid %d", kt->pid); 300 301 if (tid != 0) 302 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 303 "/%ld", kt->lwpid); 304 305 p = (struct proc *)kt->paddr; 306 if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) != 307 sizeof(comm)) 308 return (buf); 309 310 strlcat(buf, ", ", sizeof(buf)); 311 strlcat(buf, comm, sizeof(buf)); 312 } else { 313 strcpy(buf, "kernel"); 314 315 if (tid != 0) { 316 t = (struct thread *)kt->kaddr; 317 if (kvm_read(kvm, (uintptr_t)&t->td_comm[0], &comm, 318 sizeof(comm)) == sizeof(comm)) { 319 strlcat(buf, " ", sizeof(buf)); 320 strlcat(buf, comm, sizeof(buf)); 321 } 322 } 323 } 324 325 return (buf); 326 } 327