xref: /trueos/gnu/usr.bin/gdb/kgdb/kthr.c (revision 69d25b60d5de991a083072a8f88527e258c12e91)
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 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/cpuset.h>
32 #include <sys/proc.h>
33 #include <sys/types.h>
34 #include <sys/signal.h>
35 #include <err.h>
36 #include <inttypes.h>
37 #include <kvm.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 #include <defs.h>
44 #include <frame-unwind.h>
45 
46 #include "kgdb.h"
47 
48 static CORE_ADDR dumppcb;
49 static int dumptid;
50 
51 static cpuset_t stopped_cpus;
52 
53 static struct kthr *first;
54 struct kthr *curkthr;
55 
56 CORE_ADDR
kgdb_lookup(const char * sym)57 kgdb_lookup(const char *sym)
58 {
59 	CORE_ADDR addr;
60 	char *name;
61 
62 	asprintf(&name, "&%s", sym);
63 	addr = kgdb_parse(name);
64 	free(name);
65 	return (addr);
66 }
67 
68 struct kthr *
kgdb_thr_first(void)69 kgdb_thr_first(void)
70 {
71 	return (first);
72 }
73 
74 static void
kgdb_thr_add_procs(uintptr_t paddr)75 kgdb_thr_add_procs(uintptr_t paddr)
76 {
77 	struct proc p;
78 	struct thread td;
79 	struct kthr *kt;
80 	CORE_ADDR addr;
81 
82 	while (paddr != 0) {
83 		if (kvm_read(kvm, paddr, &p, sizeof(p)) != sizeof(p)) {
84 			warnx("kvm_read: %s", kvm_geterr(kvm));
85 			break;
86 		}
87 		addr = (uintptr_t)TAILQ_FIRST(&p.p_threads);
88 		while (addr != 0) {
89 			if (kvm_read(kvm, addr, &td, sizeof(td)) !=
90 			    sizeof(td)) {
91 				warnx("kvm_read: %s", kvm_geterr(kvm));
92 				break;
93 			}
94 			kt = malloc(sizeof(*kt));
95 			kt->next = first;
96 			kt->kaddr = addr;
97 			if (td.td_tid == dumptid)
98 				kt->pcb = dumppcb;
99 			else if (td.td_state == TDS_RUNNING &&
100 			    CPU_ISSET(td.td_oncpu, &stopped_cpus))
101 				kt->pcb = kgdb_trgt_core_pcb(td.td_oncpu);
102 			else
103 				kt->pcb = (uintptr_t)td.td_pcb;
104 			kt->kstack = td.td_kstack;
105 			kt->tid = td.td_tid;
106 			kt->pid = p.p_pid;
107 			kt->paddr = paddr;
108 			kt->cpu = td.td_oncpu;
109 			first = kt;
110 			addr = (uintptr_t)TAILQ_NEXT(&td, td_plist);
111 		}
112 		paddr = (uintptr_t)LIST_NEXT(&p, p_list);
113 	}
114 }
115 
116 struct kthr *
kgdb_thr_init(void)117 kgdb_thr_init(void)
118 {
119 	long cpusetsize;
120 	struct kthr *kt;
121 	CORE_ADDR addr;
122 	uintptr_t paddr;
123 
124 	while (first != NULL) {
125 		kt = first;
126 		first = kt->next;
127 		free(kt);
128 	}
129 
130 	addr = kgdb_lookup("allproc");
131 	if (addr == 0)
132 		return (NULL);
133 	kvm_read(kvm, addr, &paddr, sizeof(paddr));
134 
135 	dumppcb = kgdb_lookup("dumppcb");
136 	if (dumppcb == 0)
137 		return (NULL);
138 
139 	addr = kgdb_lookup("dumptid");
140 	if (addr != 0)
141 		kvm_read(kvm, addr, &dumptid, sizeof(dumptid));
142 	else
143 		dumptid = -1;
144 
145 	addr = kgdb_lookup("stopped_cpus");
146 	CPU_ZERO(&stopped_cpus);
147 	cpusetsize = sysconf(_SC_CPUSET_SIZE);
148 	if (cpusetsize != -1 && (u_long)cpusetsize <= sizeof(cpuset_t) &&
149 	    addr != 0)
150 		kvm_read(kvm, addr, &stopped_cpus, cpusetsize);
151 
152 	kgdb_thr_add_procs(paddr);
153 	addr = kgdb_lookup("zombproc");
154 	if (addr != 0) {
155 		kvm_read(kvm, addr, &paddr, sizeof(paddr));
156 		kgdb_thr_add_procs(paddr);
157 	}
158 	curkthr = kgdb_thr_lookup_tid(dumptid);
159 	if (curkthr == NULL)
160 		curkthr = first;
161 	return (first);
162 }
163 
164 struct kthr *
kgdb_thr_lookup_tid(int tid)165 kgdb_thr_lookup_tid(int tid)
166 {
167 	struct kthr *kt;
168 
169 	kt = first;
170 	while (kt != NULL && kt->tid != tid)
171 		kt = kt->next;
172 	return (kt);
173 }
174 
175 struct kthr *
kgdb_thr_lookup_taddr(uintptr_t taddr)176 kgdb_thr_lookup_taddr(uintptr_t taddr)
177 {
178 	struct kthr *kt;
179 
180 	kt = first;
181 	while (kt != NULL && kt->kaddr != taddr)
182 		kt = kt->next;
183 	return (kt);
184 }
185 
186 struct kthr *
kgdb_thr_lookup_pid(int pid)187 kgdb_thr_lookup_pid(int pid)
188 {
189 	struct kthr *kt;
190 
191 	kt = first;
192 	while (kt != NULL && kt->pid != pid)
193 		kt = kt->next;
194 	return (kt);
195 }
196 
197 struct kthr *
kgdb_thr_lookup_paddr(uintptr_t paddr)198 kgdb_thr_lookup_paddr(uintptr_t paddr)
199 {
200 	struct kthr *kt;
201 
202 	kt = first;
203 	while (kt != NULL && kt->paddr != paddr)
204 		kt = kt->next;
205 	return (kt);
206 }
207 
208 struct kthr *
kgdb_thr_next(struct kthr * kt)209 kgdb_thr_next(struct kthr *kt)
210 {
211 	return (kt->next);
212 }
213 
214 struct kthr *
kgdb_thr_select(struct kthr * kt)215 kgdb_thr_select(struct kthr *kt)
216 {
217 	struct kthr *pcur;
218 
219 	pcur = curkthr;
220 	curkthr = kt;
221 	return (pcur);
222 }
223 
224 char *
kgdb_thr_extra_thread_info(int tid)225 kgdb_thr_extra_thread_info(int tid)
226 {
227 	char comm[MAXCOMLEN + 1];
228 	char td_name[MAXCOMLEN + 1];
229 	struct kthr *kt;
230 	struct proc *p;
231 	struct thread *t;
232 	static char buf[64];
233 
234 	kt = kgdb_thr_lookup_tid(tid);
235 	if (kt == NULL)
236 		return (NULL);
237 	snprintf(buf, sizeof(buf), "PID=%d", kt->pid);
238 	p = (struct proc *)kt->paddr;
239 	if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) !=
240 	    sizeof(comm))
241 		return (buf);
242 	strlcat(buf, ": ", sizeof(buf));
243 	strlcat(buf, comm, sizeof(buf));
244 	t = (struct thread *)kt->kaddr;
245 	if (kvm_read(kvm, (uintptr_t)&t->td_name[0], &td_name,
246 	    sizeof(td_name)) == sizeof(td_name) &&
247 	    strcmp(comm, td_name) != 0) {
248 		strlcat(buf, "/", sizeof(buf));
249 		strlcat(buf, td_name, sizeof(buf));
250 	}
251 	return (buf);
252 }
253