1132624Smarcel/* 2132624Smarcel * Copyright (c) 2004 Marcel Moolenaar 3132624Smarcel * All rights reserved. 4132624Smarcel * 5132624Smarcel * Redistribution and use in source and binary forms, with or without 6132624Smarcel * modification, are permitted provided that the following conditions 7132624Smarcel * are met: 8132624Smarcel * 9132624Smarcel * 1. Redistributions of source code must retain the above copyright 10132624Smarcel * notice, this list of conditions and the following disclaimer. 11132624Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12132624Smarcel * notice, this list of conditions and the following disclaimer in the 13132624Smarcel * documentation and/or other materials provided with the distribution. 14132624Smarcel * 15132624Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16132624Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17132624Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18132624Smarcel * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19132624Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20132624Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21132624Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22132624Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23132624Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24132624Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25132624Smarcel */ 26132624Smarcel 27132624Smarcel#include <sys/cdefs.h> 28132624Smarcel__FBSDID("$FreeBSD$"); 29132624Smarcel 30132624Smarcel#include <sys/param.h> 31222813Sattilio#include <sys/cpuset.h> 32132624Smarcel#include <sys/proc.h> 33132624Smarcel#include <sys/types.h> 34132624Smarcel#include <sys/signal.h> 35132624Smarcel#include <err.h> 36132624Smarcel#include <inttypes.h> 37132624Smarcel#include <kvm.h> 38132624Smarcel#include <stdio.h> 39132624Smarcel#include <stdlib.h> 40175452Semaste#include <string.h> 41222813Sattilio#include <unistd.h> 42132624Smarcel 43142151Skan#include <defs.h> 44149954Smarcel#include <frame-unwind.h> 45142151Skan 46132624Smarcel#include "kgdb.h" 47161621Sjhb#include <machine/pcb.h> 48132624Smarcel 49210852Sjhbstatic CORE_ADDR dumppcb; 50132624Smarcelstatic int dumptid; 51132624Smarcel 52210852Sjhbstatic CORE_ADDR stoppcbs; 53222813Sattiliostatic cpuset_t stopped_cpus; 54161621Sjhb 55132624Smarcelstatic struct kthr *first; 56132624Smarcelstruct kthr *curkthr; 57132624Smarcel 58210852SjhbCORE_ADDR 59167142Skibkgdb_lookup(const char *sym) 60132624Smarcel{ 61210852Sjhb CORE_ADDR addr; 62210852Sjhb char *name; 63132624Smarcel 64210852Sjhb asprintf(&name, "&%s", sym); 65210852Sjhb addr = kgdb_parse(name); 66210852Sjhb free(name); 67210852Sjhb return (addr); 68132624Smarcel} 69132624Smarcel 70132624Smarcelstruct kthr * 71132624Smarcelkgdb_thr_first(void) 72132624Smarcel{ 73132624Smarcel return (first); 74132624Smarcel} 75132624Smarcel 76225017Sjhbstatic void 77225017Sjhbkgdb_thr_add_procs(uintptr_t paddr) 78225017Sjhb{ 79225017Sjhb struct proc p; 80225017Sjhb struct thread td; 81225017Sjhb struct kthr *kt; 82225017Sjhb CORE_ADDR addr; 83225017Sjhb 84225017Sjhb while (paddr != 0) { 85225017Sjhb if (kvm_read(kvm, paddr, &p, sizeof(p)) != sizeof(p)) { 86225017Sjhb warnx("kvm_read: %s", kvm_geterr(kvm)); 87225017Sjhb break; 88225017Sjhb } 89225017Sjhb addr = (uintptr_t)TAILQ_FIRST(&p.p_threads); 90225017Sjhb while (addr != 0) { 91225017Sjhb if (kvm_read(kvm, addr, &td, sizeof(td)) != 92225017Sjhb sizeof(td)) { 93225017Sjhb warnx("kvm_read: %s", kvm_geterr(kvm)); 94225017Sjhb break; 95225017Sjhb } 96225017Sjhb kt = malloc(sizeof(*kt)); 97225017Sjhb kt->next = first; 98225017Sjhb kt->kaddr = addr; 99225017Sjhb if (td.td_tid == dumptid) 100225017Sjhb kt->pcb = dumppcb; 101225017Sjhb else if (td.td_state == TDS_RUNNING && stoppcbs != 0 && 102225017Sjhb CPU_ISSET(td.td_oncpu, &stopped_cpus)) 103225017Sjhb kt->pcb = (uintptr_t)stoppcbs + 104225017Sjhb sizeof(struct pcb) * td.td_oncpu; 105225017Sjhb else 106225017Sjhb kt->pcb = (uintptr_t)td.td_pcb; 107225017Sjhb kt->kstack = td.td_kstack; 108225017Sjhb kt->tid = td.td_tid; 109225017Sjhb kt->pid = p.p_pid; 110225017Sjhb kt->paddr = paddr; 111225017Sjhb kt->cpu = td.td_oncpu; 112225017Sjhb first = kt; 113225017Sjhb addr = (uintptr_t)TAILQ_NEXT(&td, td_plist); 114225017Sjhb } 115225017Sjhb paddr = (uintptr_t)LIST_NEXT(&p, p_list); 116225017Sjhb } 117225017Sjhb} 118225017Sjhb 119132624Smarcelstruct kthr * 120132624Smarcelkgdb_thr_init(void) 121132624Smarcel{ 122222813Sattilio long cpusetsize; 123132624Smarcel struct kthr *kt; 124210852Sjhb CORE_ADDR addr; 125210852Sjhb uintptr_t paddr; 126178670Sjhb 127178670Sjhb while (first != NULL) { 128178670Sjhb kt = first; 129178670Sjhb first = kt->next; 130178670Sjhb free(kt); 131178670Sjhb } 132132624Smarcel 133210852Sjhb addr = kgdb_lookup("allproc"); 134210852Sjhb if (addr == 0) 135132624Smarcel return (NULL); 136132624Smarcel kvm_read(kvm, addr, &paddr, sizeof(paddr)); 137132624Smarcel 138210852Sjhb dumppcb = kgdb_lookup("dumppcb"); 139210852Sjhb if (dumppcb == 0) 140132624Smarcel return (NULL); 141132624Smarcel 142210852Sjhb addr = kgdb_lookup("dumptid"); 143132624Smarcel if (addr != 0) 144132624Smarcel kvm_read(kvm, addr, &dumptid, sizeof(dumptid)); 145132624Smarcel else 146132624Smarcel dumptid = -1; 147132624Smarcel 148210852Sjhb addr = kgdb_lookup("stopped_cpus"); 149222813Sattilio CPU_ZERO(&stopped_cpus); 150222813Sattilio cpusetsize = sysconf(_SC_CPUSET_SIZE); 151222813Sattilio if (cpusetsize != -1 && (u_long)cpusetsize <= sizeof(cpuset_t) && 152222813Sattilio addr != 0) 153222813Sattilio kvm_read(kvm, addr, &stopped_cpus, cpusetsize); 154161621Sjhb 155210852Sjhb stoppcbs = kgdb_lookup("stoppcbs"); 156163440Sjhb 157225017Sjhb kgdb_thr_add_procs(paddr); 158225017Sjhb addr = kgdb_lookup("zombproc"); 159225017Sjhb if (addr != 0) { 160225017Sjhb kvm_read(kvm, addr, &paddr, sizeof(paddr)); 161225017Sjhb kgdb_thr_add_procs(paddr); 162132624Smarcel } 163142151Skan curkthr = kgdb_thr_lookup_tid(dumptid); 164132624Smarcel if (curkthr == NULL) 165132624Smarcel curkthr = first; 166132624Smarcel return (first); 167132624Smarcel} 168132624Smarcel 169132624Smarcelstruct kthr * 170142151Skankgdb_thr_lookup_tid(int tid) 171132624Smarcel{ 172132624Smarcel struct kthr *kt; 173132624Smarcel 174132624Smarcel kt = first; 175132624Smarcel while (kt != NULL && kt->tid != tid) 176132624Smarcel kt = kt->next; 177132624Smarcel return (kt); 178132624Smarcel} 179132624Smarcel 180132624Smarcelstruct kthr * 181142151Skankgdb_thr_lookup_taddr(uintptr_t taddr) 182142151Skan{ 183142151Skan struct kthr *kt; 184142151Skan 185142151Skan kt = first; 186142151Skan while (kt != NULL && kt->kaddr != taddr) 187142151Skan kt = kt->next; 188142151Skan return (kt); 189142151Skan} 190142151Skan 191142151Skanstruct kthr * 192142151Skankgdb_thr_lookup_pid(int pid) 193142151Skan{ 194142151Skan struct kthr *kt; 195142151Skan 196142151Skan kt = first; 197142151Skan while (kt != NULL && kt->pid != pid) 198142151Skan kt = kt->next; 199142151Skan return (kt); 200142151Skan} 201142151Skan 202142151Skanstruct kthr * 203142151Skankgdb_thr_lookup_paddr(uintptr_t paddr) 204142151Skan{ 205142151Skan struct kthr *kt; 206142151Skan 207142151Skan kt = first; 208142151Skan while (kt != NULL && kt->paddr != paddr) 209142151Skan kt = kt->next; 210142151Skan return (kt); 211142151Skan} 212142151Skan 213142151Skanstruct kthr * 214132624Smarcelkgdb_thr_next(struct kthr *kt) 215132624Smarcel{ 216132624Smarcel return (kt->next); 217132624Smarcel} 218132624Smarcel 219132624Smarcelstruct kthr * 220132624Smarcelkgdb_thr_select(struct kthr *kt) 221132624Smarcel{ 222132624Smarcel struct kthr *pcur; 223132624Smarcel 224132624Smarcel pcur = curkthr; 225132624Smarcel curkthr = kt; 226132624Smarcel return (pcur); 227132624Smarcel} 228142151Skan 229142151Skanchar * 230142151Skankgdb_thr_extra_thread_info(int tid) 231142151Skan{ 232175452Semaste char comm[MAXCOMLEN + 1]; 233175452Semaste char td_name[MAXCOMLEN + 1]; 234142151Skan struct kthr *kt; 235142151Skan struct proc *p; 236175452Semaste struct thread *t; 237178713Sjhb static char buf[64]; 238142151Skan 239142151Skan kt = kgdb_thr_lookup_tid(tid); 240142151Skan if (kt == NULL) 241178713Sjhb return (NULL); 242178713Sjhb snprintf(buf, sizeof(buf), "PID=%d", kt->pid); 243142151Skan p = (struct proc *)kt->paddr; 244142151Skan if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) != 245142151Skan sizeof(comm)) 246178713Sjhb return (buf); 247178713Sjhb strlcat(buf, ": ", sizeof(buf)); 248178713Sjhb strlcat(buf, comm, sizeof(buf)); 249178713Sjhb t = (struct thread *)kt->kaddr; 250175452Semaste if (kvm_read(kvm, (uintptr_t)&t->td_name[0], &td_name, 251175452Semaste sizeof(td_name)) == sizeof(td_name) && 252178713Sjhb strcmp(comm, td_name) != 0) { 253178713Sjhb strlcat(buf, "/", sizeof(buf)); 254178713Sjhb strlcat(buf, td_name, sizeof(buf)); 255178713Sjhb } 256178713Sjhb return (buf); 257142151Skan} 258