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