import less(1)
[unleashed/tickless.git] / usr / src / lib / libkvm / common / test.c
blob8ee3adcb5ad3afabeadf3c0e16443d42dfbce180
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <unistd.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <ctype.h>
35 #include "kvm.h"
37 #include <nlist.h>
38 #include <sys/thread.h>
39 #include <sys/fcntl.h>
40 #include <sys/param.h>
41 #include <sys/user.h>
42 #include <sys/proc.h>
43 #include <sys/elf.h>
45 #define STACK_BIAS 0
47 kvm_t *cookie;
49 struct proc *tst_getproc(pid_t);
50 struct proc *tst_nextproc(void);
51 struct user *tst_getu(struct proc *);
52 int tst_setproc(void);
53 int tst_getcmd(struct proc *, struct user *);
54 void tst_segkp(void);
55 void tst_nlist(struct nlist nl[]);
56 void tst_open(char *, char *, char *, int);
57 void tst_close(void);
58 ssize_t tst_read(uintptr_t, void *, size_t);
59 ssize_t tst_write(uintptr_t, void *, size_t);
60 int tst_getcmd(struct proc *, struct user *);
61 void tst_segkvp(void);
63 char *name;
64 char *core;
65 char *swap;
66 int wflag;
68 struct nlist nl[] = {
69 {"free"},
70 {"fragtbl"},
71 {"freemem"},
72 {"allthreads"},
73 {"nbuckets"},
74 {"cputype"},
75 {0}
78 int
79 main(int argc, char *argv[], char *envp[])
81 int c, errflg = 0;
82 long xx;
83 struct nlist *nlp;
84 struct proc *proc;
85 struct user *u;
86 int envc, ccnt;
88 for (envc = 0; *envp++ != NULL; envc++)
89 continue;
90 envp -= 2;
91 ccnt = (*envp - *argv) + strlen(*envp) + 1;
92 printf("pid %d:: %d args; %d envs; %d chars (%p - %p)\n",
93 getpid(), argc, envc, ccnt,
94 &argv[0], *envp + strlen(*envp));
96 while ((c = getopt(argc, argv, "w")) != EOF)
97 switch (c) {
98 case 'w':
99 wflag++;
100 break;
101 case '?':
102 errflg++;
104 if (errflg) {
105 fprintf(stderr, "usage: %s [-w] [name] [core] [swap]\n",
106 argv[0]);
107 return (2);
109 if (optind < argc) {
110 name = argv[optind++];
111 if (*name == '\0')
112 name = NULL;
113 } else
114 name = NULL;
115 if (optind < argc) {
116 core = argv[optind++];
117 if (*core == '\0')
118 core = NULL;
119 } else
120 core = NULL;
121 if (optind < argc) {
122 swap = argv[optind++];
123 if (*swap == '\0')
124 swap = NULL;
125 } else
126 swap = NULL;
128 tst_open(name, core, swap, (wflag ? O_RDWR : O_RDONLY));
129 if (cookie == NULL)
130 return (1);
132 tst_nlist(nl);
134 for (nlp = nl; nlp[0].n_type != 0; nlp++)
135 tst_read(nlp[0].n_value, &xx, sizeof (xx));
137 while ((proc = tst_nextproc()) != NULL) {
138 struct pid pid;
139 if (kvm_read(cookie, (uintptr_t)proc->p_pidp, &pid,
140 sizeof (pid)) != sizeof (pid)) {
141 printf("ERROR: couldn't get pid\n");
142 break;
144 tst_getproc(pid.pid_id);
147 tst_setproc();
149 while ((proc = tst_nextproc()) != NULL) {
150 if ((u = tst_getu(proc)) != NULL)
151 (void) tst_getcmd(proc, u);
154 tst_segkp();
155 tst_close();
157 return (0);
160 void
161 tst_open(char *namelist, char *corefile, char *swapfile, int flag)
163 printf("kvm_open(%s, %s, %s, %s)\n",
164 (namelist == NULL) ? "LIVE_KERNEL" : namelist,
165 (corefile == NULL) ? "LIVE_KERNEL" : corefile,
166 (swapfile == NULL) ?
167 ((corefile == NULL) ? "LIVE_KERNEL" : "(none)") : swapfile,
168 (flag == O_RDONLY) ? "O_RDONLY" : ((flag == O_RDWR) ?
169 "O_RDWR" : "???"));
171 if ((cookie = kvm_open(namelist, corefile,
172 swapfile, flag, "libkvm test")) == NULL)
173 printf("ERROR: kvm_open returned %p\n", cookie);
176 void
177 tst_close(void)
179 int i;
181 printf("kvm_close()\n");
182 if ((i = kvm_close(cookie)) != 0)
183 printf("ERROR: kvm_close returned %d\n", i);
186 void
187 tst_nlist(struct nlist nl[])
189 int i;
190 char *t, *s;
192 printf("kvm_nlist([nl])\n");
193 if ((i = kvm_nlist(cookie, nl)) != 0)
194 printf("ERROR: kvm_nlist returned %d\n", i);
195 for (i = 0; nl[i].n_name != 0 && nl[i].n_name[0] != '\0'; i++) {
197 * Debug:
198 * n_value gets filled in with st_value,
199 * n_type gets filled in w/ELF32_ST_TYPE(sym->st_info)
200 * n_scnum gets filled in w/st_shndx
202 switch (nl[i].n_type) {
203 case STT_NOTYPE:
204 t = "NOTYPE";
205 break;
206 case STT_OBJECT:
207 t = "OBJECT";
208 break;
209 case STT_FUNC:
210 t = "FUNC";
211 break;
212 case STT_SECTION:
213 t = "SECTION";
214 break;
215 case STT_FILE:
216 t = "FILE";
217 break;
218 case STT_NUM:
219 t = "NUM";
220 break;
221 default:
222 t = "???";
225 switch ((unsigned)nl[i].n_scnum) {
226 static char strbuf[40];
228 case SHN_UNDEF:
229 s = "UNDEF";
230 break;
231 case SHN_LORESERVE:
232 s = "LORESERVE";
233 break;
234 case SHN_ABS:
235 s = "ABS";
236 break;
237 case SHN_COMMON:
238 s = "COMMON";
239 break;
240 case SHN_HIRESERVE:
241 s = "HIRESERVE";
242 break;
243 default:
244 (void) sprintf(strbuf, "unknown (%d)", nl[i].n_scnum);
245 s = strbuf;
246 break;
249 printf("%s: %lx (%s, %s)\n",
250 nl[i].n_name, nl[i].n_value, s, t);
254 ssize_t
255 tst_read(uintptr_t addr, void *buf, size_t nbytes)
257 ssize_t e;
258 int i;
259 char *b;
261 printf("kvm_read(%lx, [buf], %lu)\n", addr, nbytes);
262 if ((e = kvm_read(cookie, addr, buf, nbytes)) != nbytes)
263 printf("ERROR: kvm_read returned %ld instead of %lu\n",
264 e, nbytes);
265 for (b = buf, i = 0; i < nbytes; b++, i++)
266 printf("%lx: %02x (%04o)\n", addr + i,
267 *b & 0xff, *b & 0xff);
269 return (e);
272 ssize_t
273 tst_write(uintptr_t addr, void *buf, size_t nbytes)
275 ssize_t e;
276 ssize_t i;
277 void *b;
279 printf("kvm_write(%lx, [buf], %lu)\n", addr, nbytes);
280 if ((e = kvm_write(cookie, addr, buf, nbytes)) != nbytes)
281 printf("ERROR: kvm_write returned %ld instead of %lu\n",
282 e, nbytes);
283 if ((b = malloc(nbytes)) == 0)
284 printf("ERROR: malloc for readback failed\n");
285 else {
286 if ((i = kvm_read(cookie, addr, b, nbytes)) != nbytes)
287 printf("ERROR: readback returned %ld\n", i);
288 else if (memcmp(b, buf, nbytes))
289 printf("ERROR: write check failed!\n");
290 (void) free(b);
292 return (e);
295 struct proc *
296 tst_getproc(pid_t pid)
298 struct proc *proc;
299 struct pid pidbuf;
301 printf("kvm_getproc(%d)\n", pid);
302 if ((proc = kvm_getproc(cookie, pid)) == NULL) {
303 printf("ERROR: kvm_getproc returned NULL\n");
304 return (proc);
307 if (kvm_read(cookie, (uintptr_t)proc->p_pidp, &pidbuf,
308 sizeof (pidbuf)) != sizeof (pidbuf)) {
309 printf("ERROR: couldn't get pid\n");
310 return (proc);
313 printf("p_pid: %d\n", pidbuf.pid_id);
314 return (proc);
317 struct proc *
318 tst_nextproc(void)
320 struct proc *proc;
321 struct pid pidbuf;
323 printf("kvm_nextproc()\n");
324 if ((proc = kvm_nextproc(cookie)) == NULL) {
325 printf("kvm_nextproc returned NULL\n");
326 return (proc);
330 * p_pid is now a macro which turns into a ptr dereference;
331 * must do a kvm_read to get contents.
333 if (kvm_read(cookie, (u_long)proc->p_pidp, (char *)&pidbuf,
334 sizeof (struct pid)) != sizeof (struct pid)) {
335 printf("ERROR: couldn't get pid\n");
337 printf("p_pid: %d\n", pidbuf.pid_id);
339 return (proc);
343 tst_setproc(void)
345 int i;
347 printf("kvm_setproc()\n");
348 if ((i = kvm_setproc(cookie)) != 0)
349 printf("ERROR: kvm_setproc returned %d\n", i);
350 return (i);
353 struct user *
354 tst_getu(struct proc *proc)
356 register int e;
357 struct proc tp;
358 struct user *u;
359 struct pid pidbuf;
361 if (kvm_read(cookie, (uintptr_t)proc->p_pidp, &pidbuf,
362 sizeof (pidbuf)) != sizeof (pidbuf))
363 printf("ERROR: couldn't get pid\n");
365 printf("kvm_getu(pid:%d)\n", pidbuf.pid_id);
366 if ((u = kvm_getu(cookie, proc)) == NULL)
367 printf("ERROR: kvm_getu returned NULL\n");
368 return (u);
371 static void
372 safe_printf(const char *s)
374 char buf[BUFSIZ], *p;
376 (void) strncpy(buf, s, BUFSIZ - 1);
377 buf[BUFSIZ - 1] = '\0';
379 for (p = buf; *p != '\0'; p++) {
380 if (!isprint(*p))
381 *p = ' ';
384 (void) printf("\"%s\"\n", buf);
388 tst_getcmd(struct proc *proc, struct user *u)
390 char **arg;
391 char **env;
392 int i;
393 char **p;
394 struct pid pidbuf;
396 if (kvm_kread(cookie, (uintptr_t)proc->p_pidp, &pidbuf,
397 sizeof (pidbuf)) != sizeof (pidbuf)) {
398 printf("ERROR: couldn't get pid\n");
399 return (-1);
402 printf("kvm_getcmd(pid:%d, [u], arg, env)\n", pidbuf.pid_id);
403 if ((i = kvm_getcmd(cookie, proc, u, &arg, &env)) != 0) {
404 printf("kvm_getcmd returned %d\n", i);
405 return (i);
408 printf("Args: ");
409 for (p = arg; *p != NULL; p++)
410 safe_printf(*p);
411 printf("Env: ");
412 for (p = env; *p != NULL; p++)
413 safe_printf(*p);
415 (void) free(arg);
416 (void) free(env);
418 return (0);
421 void
422 tst_segkp(void)
424 kthread_t t;
425 caddr_t tp, alltp;
426 uintptr_t stk[16];
427 int i;
429 if (kvm_read(cookie, nl[3].n_value, &alltp, sizeof (alltp))
430 != sizeof (alltp)) {
431 printf("ERROR: couldn't read allthread, addr 0x%lx\n",
432 nl[3].n_value);
433 return;
435 printf("allthreads 0x%lx\n", nl[3].n_value);
436 printf("next offset 0x%lx\n",
437 (uintptr_t)&(t.t_next) - (uintptr_t)&t);
439 for (tp = alltp; tp; tp = (caddr_t)(t.t_next)) {
440 if (kvm_read(cookie,
441 (uintptr_t)tp, &t, sizeof (t)) != sizeof (t)) {
442 printf("ERROR: couldn't read thread, addr 0x%p\n", tp);
443 return;
446 printf("thread 0x%p\n", tp);
447 printf("\tstk 0x%p sp 0x%lx tid %d next 0x%p prev 0x%p\n",
448 tp, t.t_stk, t.t_pcb.val[1], t.t_tid, t.t_next, t.t_prev);
450 if (kvm_read(cookie, t.t_pcb.val[1] + STACK_BIAS, stk,
451 sizeof (stk)) != sizeof (stk)) {
452 printf("ERROR: couldn't read stack, taddr 0x%p\n", tp);
453 continue;
455 for (i = 0; i < 16; i++) {
456 printf("%-16lx ", stk[i]);
457 if (((i + 1) % 4) == 0)
458 printf("\n");
461 if ((caddr_t)(t.t_next) == alltp)
462 break;