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
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
43 #include <sys/dumphdr.h>
44 #include <sys/sysmacros.h>
47 struct dumphdr kvm_dump
;
53 size_t kvm_coremapsize
;
60 char kvm_namelist
[MAXNAMELEN
+ 1];
61 boolean_t kvm_namelist_core
;
65 #define PREAD (ssize_t (*)(int, void *, size_t, offset_t))pread64
66 #define PWRITE (ssize_t (*)(int, void *, size_t, offset_t))pwrite64
68 static int kvm_nlist_core(kvm_t
*kd
, struct nlist nl
[], const char *err
);
71 fail(kvm_t
*kd
, const char *err
, const char *message
, ...)
75 va_start(args
, message
);
76 if (err
|| (kd
&& kd
->kvm_debug
)) {
77 (void) fprintf(stderr
, "%s: ", err
? err
: "KVM_DEBUG");
78 (void) vfprintf(stderr
, message
, args
);
79 (void) fprintf(stderr
, "\n");
89 kvm_open(const char *namelist
, const char *corefile
, const char *swapfile
,
90 int flag
, const char *err
)
93 struct stat64 memstat
, kmemstat
, allkmemstat
, corestat
;
94 struct nlist nl
[3] = { { "kas" }, { "practive" }, { "" } };
96 if ((kd
= calloc(1, sizeof (kvm_t
))) == NULL
)
97 return (fail(NULL
, err
, "cannot allocate space for kvm_t"));
99 kd
->kvm_corefd
= kd
->kvm_kmemfd
= kd
->kvm_memfd
= -1;
100 kd
->kvm_debug
= getenv("KVM_DEBUG");
102 if ((kd
->kvm_openflag
= flag
) != O_RDONLY
&& flag
!= O_RDWR
)
103 return (fail(kd
, err
, "illegal flag 0x%x to kvm_open()", flag
));
105 if (corefile
== NULL
)
106 corefile
= "/dev/kmem";
108 if (stat64(corefile
, &corestat
) == -1)
109 return (fail(kd
, err
, "cannot stat %s", corefile
));
111 if (S_ISCHR(corestat
.st_mode
)) {
112 if (stat64("/dev/mem", &memstat
) == -1)
113 return (fail(kd
, err
, "cannot stat /dev/mem"));
115 if (stat64("/dev/kmem", &kmemstat
) == -1)
116 return (fail(kd
, err
, "cannot stat /dev/kmem"));
118 if (stat64("/dev/allkmem", &allkmemstat
) == -1)
119 return (fail(kd
, err
, "cannot stat /dev/allkmem"));
120 if (corestat
.st_rdev
== memstat
.st_rdev
||
121 corestat
.st_rdev
== kmemstat
.st_rdev
||
122 corestat
.st_rdev
== allkmemstat
.st_rdev
) {
123 char *kmem
= (corestat
.st_rdev
== allkmemstat
.st_rdev
?
124 "/dev/allkmem" : "/dev/kmem");
126 if ((kd
->kvm_kmemfd
= open64(kmem
, flag
)) == -1)
127 return (fail(kd
, err
, "cannot open %s", kmem
));
128 if ((kd
->kvm_memfd
= open64("/dev/mem", flag
)) == -1)
129 return (fail(kd
, err
, "cannot open /dev/mem"));
132 if ((kd
->kvm_corefd
= open64(corefile
, flag
)) == -1)
133 return (fail(kd
, err
, "cannot open %s", corefile
));
134 if (pread64(kd
->kvm_corefd
, &kd
->kvm_dump
,
135 sizeof (kd
->kvm_dump
), 0) != sizeof (kd
->kvm_dump
))
136 return (fail(kd
, err
, "cannot read dump header"));
137 if (kd
->kvm_dump
.dump_magic
!= DUMP_MAGIC
)
138 return (fail(kd
, err
, "%s is not a kernel core file "
139 "(bad magic number %x)", corefile
,
140 kd
->kvm_dump
.dump_magic
));
141 if (kd
->kvm_dump
.dump_version
!= DUMP_VERSION
)
142 return (fail(kd
, err
,
143 "libkvm version (%u) != corefile version (%u)",
144 DUMP_VERSION
, kd
->kvm_dump
.dump_version
));
145 if (kd
->kvm_dump
.dump_wordsize
!= DUMP_WORDSIZE
)
146 return (fail(kd
, err
, "%s is a %d-bit core file - "
147 "cannot examine with %d-bit libkvm", corefile
,
148 kd
->kvm_dump
.dump_wordsize
, DUMP_WORDSIZE
));
150 * We try to mmap(2) the entire corefile for performance
151 * (so we can use bcopy(3C) rather than pread(2)). Failing
152 * that, we insist on at least mmap(2)ing the dump map.
154 kd
->kvm_coremapsize
= (size_t)corestat
.st_size
;
155 if (corestat
.st_size
> LONG_MAX
||
156 (kd
->kvm_core
= mmap64(NULL
, kd
->kvm_coremapsize
,
157 PROT_READ
, MAP_SHARED
, kd
->kvm_corefd
, 0)) == MAP_FAILED
) {
158 kd
->kvm_coremapsize
= kd
->kvm_dump
.dump_data
;
159 if ((kd
->kvm_core
= mmap64(NULL
, kd
->kvm_coremapsize
,
160 PROT_READ
, MAP_SHARED
, kd
->kvm_corefd
, 0)) ==
162 return (fail(kd
, err
, "cannot mmap corefile"));
164 kd
->kvm_map
= (void *)(kd
->kvm_core
+ kd
->kvm_dump
.dump_map
);
165 kd
->kvm_pfn
= (void *)(kd
->kvm_core
+ kd
->kvm_dump
.dump_pfn
);
168 if (namelist
== NULL
)
169 namelist
= "/dev/ksyms";
171 (void) strncpy(kd
->kvm_namelist
, namelist
, MAXNAMELEN
);
173 if (kvm_nlist(kd
, nl
) == -1) {
174 if (kd
->kvm_corefd
== -1) {
175 return (fail(kd
, err
, "%s is not a %d-bit "
176 "kernel namelist", namelist
, DUMP_WORDSIZE
));
179 if (kvm_nlist_core(kd
, nl
, err
) == -1)
180 return (NULL
); /* fail() already called */
183 kd
->kvm_kas
= (struct as
*)nl
[0].n_value
;
184 kd
->kvm_practive
= (proc_t
*)nl
[1].n_value
;
186 (void) kvm_setproc(kd
);
193 if (kd
->kvm_core
!= NULL
&& kd
->kvm_core
!= MAP_FAILED
)
194 (void) munmap(kd
->kvm_core
, kd
->kvm_coremapsize
);
195 if (kd
->kvm_corefd
!= -1)
196 (void) close(kd
->kvm_corefd
);
197 if (kd
->kvm_kmemfd
!= -1)
198 (void) close(kd
->kvm_kmemfd
);
199 if (kd
->kvm_memfd
!= -1)
200 (void) close(kd
->kvm_memfd
);
201 if (kd
->kvm_namelist_core
)
202 (void) unlink(kd
->kvm_namelist
);
208 kvm_namelist(kvm_t
*kd
)
210 return (kd
->kvm_namelist
);
214 kvm_nlist(kvm_t
*kd
, struct nlist nl
[])
216 return (nlist(kd
->kvm_namelist
, nl
));
220 * If we don't have a name list, try to dig it out of the kernel crash dump.
221 * (The symbols have been present in the dump, uncompressed, for nearly a
222 * decade as of this writing -- and it is frankly surprising that the archaic
223 * notion of a disjoint symbol table managed to survive that change.)
226 kvm_nlist_core(kvm_t
*kd
, struct nlist nl
[], const char *err
)
228 dumphdr_t
*dump
= &kd
->kvm_dump
;
229 char *msg
= "couldn't extract symbols from dump";
230 char *template = "/tmp/.libkvm.kvm_nlist_core.pid%d.XXXXXX";
233 if (dump
->dump_ksyms_size
!= dump
->dump_ksyms_csize
) {
234 (void) fail(kd
, err
, "%s: kernel symbols are compressed", msg
);
238 if (dump
->dump_ksyms
+ dump
->dump_ksyms_size
> kd
->kvm_coremapsize
) {
239 (void) fail(kd
, err
, "%s: kernel symbols not mapped", msg
);
244 * Beause this temporary file may be left as a turd if the caller
245 * does not properly call kvm_close(), we make sure that it clearly
246 * indicates its origins.
248 (void) snprintf(kd
->kvm_namelist
, MAXNAMELEN
, template, getpid());
250 if ((fd
= mkstemp(kd
->kvm_namelist
)) == -1) {
251 (void) fail(kd
, err
, "%s: couldn't create temporary "
252 "symbols file: %s", msg
, strerror(errno
));
256 kd
->kvm_namelist_core
= B_TRUE
;
259 rval
= write(fd
, (caddr_t
)((uintptr_t)kd
->kvm_core
+
260 (uintptr_t)dump
->dump_ksyms
), dump
->dump_ksyms_size
);
261 } while (rval
< dump
->dump_ksyms_size
&& errno
== EINTR
);
263 if (rval
< dump
->dump_ksyms_size
) {
264 (void) fail(kd
, err
, "%s: couldn't write to temporary "
265 "symbols file: %s", msg
, strerror(errno
));
272 if (kvm_nlist(kd
, nl
) == -1) {
273 (void) fail(kd
, err
, "%s: symbols not valid", msg
);
281 kvm_lookup(kvm_t
*kd
, struct as
*as
, uint64_t addr
)
283 uintptr_t pageoff
= addr
& (kd
->kvm_dump
.dump_pagesize
- 1);
284 uint64_t page
= addr
- pageoff
;
288 fprintf(stderr
, "kvm_lookup(%p, %llx):", (void *)as
, addr
);
290 if (as
== NULL
) { /* physical addressing mode */
292 long last
= kd
->kvm_dump
.dump_npages
- 1;
293 pfn_t target
= (pfn_t
)(page
>> kd
->kvm_dump
.dump_pageshift
);
294 while (last
>= first
) {
295 long middle
= (first
+ last
) / 2;
296 pfn_t pfn
= kd
->kvm_pfn
[middle
];
298 fprintf(stderr
, " %ld ->", middle
);
300 off
= kd
->kvm_dump
.dump_data
+ pageoff
+
302 kd
->kvm_dump
.dump_pageshift
);
311 long hash
= DUMP_HASH(&kd
->kvm_dump
, as
, page
);
312 off
= kd
->kvm_map
[hash
].dm_first
;
314 dump_map_t
*dmp
= (void *)(kd
->kvm_core
+ off
);
316 fprintf(stderr
, " %llx ->", off
);
317 if (dmp
< kd
->kvm_map
||
318 dmp
> kd
->kvm_map
+ kd
->kvm_dump
.dump_hashmask
||
319 (off
& (sizeof (offset_t
) - 1)) != 0 ||
320 DUMP_HASH(&kd
->kvm_dump
, dmp
->dm_as
, dmp
->dm_va
) !=
323 fprintf(stderr
, " dump map corrupt\n");
326 if (dmp
->dm_va
== page
&& dmp
->dm_as
== as
) {
327 off
= dmp
->dm_data
+ pageoff
;
334 fprintf(stderr
, "%s found: %llx\n", off
? "" : " not", off
);
339 kvm_rw(kvm_t
*kd
, uint64_t addr
, void *buf
, size_t size
,
340 struct as
*as
, ssize_t (*prw
)(int, void *, size_t, offset_t
))
346 * read/write of zero bytes always succeeds
351 if (kd
->kvm_core
== NULL
) {
356 if (as
== kd
->kvm_kas
)
357 return (prw(kd
->kvm_kmemfd
, buf
, size
, addr
));
359 return (prw(kd
->kvm_memfd
, buf
, size
, addr
));
361 (void) sprintf(procbuf
, "/proc/%ld/as", kd
->kvm_pid
);
362 if ((procfd
= open64(procbuf
, kd
->kvm_openflag
)) == -1)
364 rval
= prw(procfd
, buf
, size
, addr
);
365 (void) close(procfd
);
370 uintptr_t pageoff
= addr
& (kd
->kvm_dump
.dump_pagesize
- 1);
371 ssize_t len
= MIN(resid
, kd
->kvm_dump
.dump_pagesize
- pageoff
);
373 if ((off
= kvm_lookup(kd
, as
, addr
)) == 0)
376 if (prw
== PREAD
&& off
< kd
->kvm_coremapsize
)
377 bcopy(kd
->kvm_core
+ off
, buf
, len
);
378 else if ((len
= prw(kd
->kvm_corefd
, buf
, len
, off
)) <= 0)
382 buf
= (char *)buf
+ len
;
384 return (resid
< size
? size
- resid
: -1);
388 kvm_read(kvm_t
*kd
, uintptr_t addr
, void *buf
, size_t size
)
390 return (kvm_rw(kd
, addr
, buf
, size
, kd
->kvm_kas
, PREAD
));
394 kvm_kread(kvm_t
*kd
, uintptr_t addr
, void *buf
, size_t size
)
396 return (kvm_rw(kd
, addr
, buf
, size
, kd
->kvm_kas
, PREAD
));
400 kvm_uread(kvm_t
*kd
, uintptr_t addr
, void *buf
, size_t size
)
402 return (kvm_rw(kd
, addr
, buf
, size
, kd
->kvm_proc
.p_as
, PREAD
));
406 kvm_aread(kvm_t
*kd
, uintptr_t addr
, void *buf
, size_t size
, struct as
*as
)
408 return (kvm_rw(kd
, addr
, buf
, size
, as
, PREAD
));
412 kvm_pread(kvm_t
*kd
, uint64_t addr
, void *buf
, size_t size
)
414 return (kvm_rw(kd
, addr
, buf
, size
, NULL
, PREAD
));
418 kvm_write(kvm_t
*kd
, uintptr_t addr
, const void *buf
, size_t size
)
420 return (kvm_rw(kd
, addr
, (void *)buf
, size
, kd
->kvm_kas
, PWRITE
));
424 kvm_kwrite(kvm_t
*kd
, uintptr_t addr
, const void *buf
, size_t size
)
426 return (kvm_rw(kd
, addr
, (void *)buf
, size
, kd
->kvm_kas
, PWRITE
));
430 kvm_uwrite(kvm_t
*kd
, uintptr_t addr
, const void *buf
, size_t size
)
432 return (kvm_rw(kd
, addr
, (void *)buf
, size
, kd
->kvm_proc
.p_as
, PWRITE
));
436 kvm_awrite(kvm_t
*kd
, uintptr_t addr
, const void *buf
, size_t size
,
439 return (kvm_rw(kd
, addr
, (void *)buf
, size
, as
, PWRITE
));
443 kvm_pwrite(kvm_t
*kd
, uint64_t addr
, const void *buf
, size_t size
)
445 return (kvm_rw(kd
, addr
, (void *)buf
, size
, NULL
, PWRITE
));
449 kvm_physaddr(kvm_t
*kd
, struct as
*as
, uintptr_t addr
)
454 if (kd
->kvm_core
== NULL
) {
456 mem_vtop
.m_va
= (void *)addr
;
457 if (ioctl(kd
->kvm_kmemfd
, MEM_VTOP
, &mem_vtop
) == 0)
458 return ((uint64_t)mem_vtop
.m_pfn
* getpagesize() +
459 (addr
& (getpagesize() - 1)));
461 if ((off
= kvm_lookup(kd
, as
, addr
)) != 0) {
463 (uoff_t
)(off
- kd
->kvm_dump
.dump_data
) >>
464 kd
->kvm_dump
.dump_pageshift
;
465 return (((uint64_t)kd
->kvm_pfn
[pfn_index
] <<
466 kd
->kvm_dump
.dump_pageshift
) +
467 (addr
& (kd
->kvm_dump
.dump_pagesize
- 1)));
474 kvm_getproc(kvm_t
*kd
, pid_t pid
)
476 (void) kvm_setproc(kd
);
477 while (kvm_nextproc(kd
) != NULL
)
478 if (kd
->kvm_pid
== pid
)
479 return (&kd
->kvm_proc
);
484 kvm_nextproc(kvm_t
*kd
)
486 if (kd
->kvm_proc
.p_next
== NULL
||
487 kvm_kread(kd
, (uintptr_t)kd
->kvm_proc
.p_next
,
488 &kd
->kvm_proc
, sizeof (proc_t
)) != sizeof (proc_t
) ||
489 kvm_kread(kd
, (uintptr_t)&kd
->kvm_proc
.p_pidp
->pid_id
,
490 &kd
->kvm_pid
, sizeof (pid_t
)) != sizeof (pid_t
))
493 return (&kd
->kvm_proc
);
497 kvm_setproc(kvm_t
*kd
)
499 (void) kvm_kread(kd
, (uintptr_t)kd
->kvm_practive
,
500 &kd
->kvm_proc
.p_next
, sizeof (proc_t
*));
507 kvm_getu(kvm_t
*kd
, struct proc
*p
)