]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - gnu/usr.bin/gdb/kgdb/kthr.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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/proc.h>
32 #include <sys/types.h>
33 #include <sys/signal.h>
34 #include <err.h>
35 #include <inttypes.h>
36 #include <kvm.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <defs.h>
42 #include <frame-unwind.h>
43
44 #include "kgdb.h"
45 #include <machine/pcb.h>
46
47 static uintptr_t dumppcb;
48 static int dumptid;
49
50 static uintptr_t stoppcbs;
51 static __cpumask_t stopped_cpus;
52
53 static struct kthr *first;
54 struct kthr *curkthr;
55
56 uintptr_t
57 kgdb_lookup(const char *sym)
58 {
59         struct nlist nl[2];
60
61         nl[0].n_type = N_UNDF;
62         nl[0].n_name = (char *)(uintptr_t)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 kthr *kt;
81         uintptr_t addr, paddr;
82         
83         while (first != NULL) {
84                 kt = first;
85                 first = kt->next;
86                 free(kt);
87         }
88
89         addr = kgdb_lookup("_allproc");
90         if (addr == 0) {
91                 warnx("kvm_nlist(_allproc): %s", kvm_geterr(kvm));
92                 return (NULL);
93         }
94         kvm_read(kvm, addr, &paddr, sizeof(paddr));
95
96         dumppcb = kgdb_lookup("_dumppcb");
97         if (dumppcb == 0) {
98                 warnx("kvm_nlist(_dumppcb): %s", kvm_geterr(kvm));
99                 return (NULL);
100         }
101
102         addr = kgdb_lookup("_dumptid");
103         if (addr != 0)
104                 kvm_read(kvm, addr, &dumptid, sizeof(dumptid));
105         else
106                 dumptid = -1;
107
108         addr =  kgdb_lookup("_stopped_cpus");
109         if (addr != 0)
110                 kvm_read(kvm, addr, &stopped_cpus, sizeof(stopped_cpus));
111         else
112                 stopped_cpus = 0;
113
114         stoppcbs = kgdb_lookup("_stoppcbs");
115
116         while (paddr != 0) {
117                 if (kvm_read(kvm, paddr, &p, sizeof(p)) != sizeof(p)) {
118                         warnx("kvm_read: %s", kvm_geterr(kvm));
119                         break;
120                 }
121                 addr = (uintptr_t)TAILQ_FIRST(&p.p_threads);
122                 while (addr != 0) {
123                         if (kvm_read(kvm, addr, &td, sizeof(td)) !=
124                             sizeof(td)) {
125                                 warnx("kvm_read: %s", kvm_geterr(kvm));
126                                 break;
127                         }
128                         kt = malloc(sizeof(*kt));
129                         kt->next = first;
130                         kt->kaddr = addr;
131                         if (td.td_tid == dumptid)
132                                 kt->pcb = dumppcb;
133                         else if (td.td_state == TDS_RUNNING && ((1 << td.td_oncpu) & stopped_cpus)
134                                 && stoppcbs != 0)
135                                 kt->pcb = (uintptr_t) stoppcbs + sizeof(struct pcb) * td.td_oncpu;
136                         else
137                                 kt->pcb = (uintptr_t)td.td_pcb;
138                         kt->kstack = td.td_kstack;
139                         kt->tid = td.td_tid;
140                         kt->pid = p.p_pid;
141                         kt->paddr = paddr;
142                         kt->cpu = td.td_oncpu;
143                         first = kt;
144                         addr = (uintptr_t)TAILQ_NEXT(&td, td_plist);
145                 }
146                 paddr = (uintptr_t)LIST_NEXT(&p, p_list);
147         }
148         curkthr = kgdb_thr_lookup_tid(dumptid);
149         if (curkthr == NULL)
150                 curkthr = first;
151         return (first);
152 }
153
154 struct kthr *
155 kgdb_thr_lookup_tid(int tid)
156 {
157         struct kthr *kt;
158
159         kt = first;
160         while (kt != NULL && kt->tid != tid)
161                 kt = kt->next;
162         return (kt);
163 }
164
165 struct kthr *
166 kgdb_thr_lookup_taddr(uintptr_t taddr)
167 {
168         struct kthr *kt;
169
170         kt = first;
171         while (kt != NULL && kt->kaddr != taddr)
172                 kt = kt->next;
173         return (kt);
174 }
175
176 struct kthr *
177 kgdb_thr_lookup_pid(int pid)
178 {
179         struct kthr *kt;
180
181         kt = first;
182         while (kt != NULL && kt->pid != pid)
183                 kt = kt->next;
184         return (kt);
185 }
186
187 struct kthr *
188 kgdb_thr_lookup_paddr(uintptr_t paddr)
189 {
190         struct kthr *kt;
191
192         kt = first;
193         while (kt != NULL && kt->paddr != paddr)
194                 kt = kt->next;
195         return (kt);
196 }
197
198 struct kthr *
199 kgdb_thr_next(struct kthr *kt)
200 {
201         return (kt->next);
202 }
203
204 struct kthr *
205 kgdb_thr_select(struct kthr *kt)
206 {
207         struct kthr *pcur;
208
209         pcur = curkthr;
210         curkthr = kt;
211         return (pcur);
212 }
213
214 char *
215 kgdb_thr_extra_thread_info(int tid)
216 {
217         char comm[MAXCOMLEN + 1];
218         char td_name[MAXCOMLEN + 1];
219         struct kthr *kt;
220         struct proc *p;
221         struct thread *t;
222         static char buf[64];
223
224         kt = kgdb_thr_lookup_tid(tid);
225         if (kt == NULL)
226                 return (NULL);  
227         snprintf(buf, sizeof(buf), "PID=%d", kt->pid);
228         p = (struct proc *)kt->paddr;
229         if (kvm_read(kvm, (uintptr_t)&p->p_comm[0], &comm, sizeof(comm)) !=
230             sizeof(comm))
231                 return (buf);
232         strlcat(buf, ": ", sizeof(buf));
233         strlcat(buf, comm, sizeof(buf));
234         t = (struct thread *)kt->kaddr;
235         if (kvm_read(kvm, (uintptr_t)&t->td_name[0], &td_name,
236             sizeof(td_name)) == sizeof(td_name) &&
237             strcmp(comm, td_name) != 0) {
238                 strlcat(buf, "/", sizeof(buf));
239                 strlcat(buf, td_name, sizeof(buf));
240         }
241         return (buf);
242 }