Print this page
9210 remove KMDB branch debugging support
9211 ::crregs could do with cr2/cr3 support
9209 ::ttrace should be able to filter by thread
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/mdb/mdb_kproc.c
+++ new/usr/src/cmd/mdb/common/mdb/mdb_kproc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + *
25 + * Copyright 2018 Joyent, Inc.
24 26 */
25 27
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 28 /*
29 29 * Kernel Process View Target
30 30 *
31 31 * The kproc target is activated when the user is debugging a kernel using the
32 32 * kvm target and executes a ::context dcmd to change the debugger view to one
33 33 * of the running processes. The kvm target's t_setcontext operation will
34 34 * create and activate a kproc target in response to this call. The kproc
35 35 * target itself is built upon the kvm target's libkvm cookie and the ability
36 36 * to read information from the kernel itself and the ability to read the
37 37 * address space of a particular user process with kvm_aread(). It also relies
38 38 * on a special set of functions provided by the kvm target's mdb_ks support
39 39 * module in order to bootstrap: specifically, given the initial proc pointer,
40 40 * mdb_ks provides functions to return the set of address space mappings, the
41 41 * address space pointer itself, the aux vector vector saved in the u-area,
42 42 * and the process data model. The kproc target maintains a list of address
43 43 * space mappings (kp_map_t) and load objects (kp_file_t), and for each load
44 44 * object will attempt to read the corresponding dynamic symbol table. In
45 45 * order to bootstrap, the target uses the AT_BASE and AT_ENTRY aux vector
46 46 * elements to locate the dynamic linker and executable mappings. With these
47 47 * mappings in place, we initialize a librtld_db agent on the target (see
48 48 * mdb_pservice.c for how this is done), and then process each load object
49 49 * found in the link-map chain. In order to simplify the construction of
50 50 * symbol tables for each load object, we would like make use of our existing
51 51 * library of GElf processing code. Since the MDB GElf code uses mdb_io
52 52 * objects to read in an ELF file, we simply define a new type of mdb_io object
53 53 * where each read operation is translated into a call to kproc's t_vread
54 54 * function to read from the range of the address space defined by the mapping
55 55 * as if it were a file.
56 56 */
57 57
58 58 #include <sys/types.h>
59 59 #include <sys/proc.h>
60 60 #include <sys/auxv.h>
61 61
62 62 #include <strings.h>
63 63 #include <limits.h>
64 64 #include <rtld_db.h>
65 65 #include <procfs.h>
66 66 #include <dlfcn.h>
67 67 #include <kvm.h>
68 68
69 69 #include <mdb/mdb_target_impl.h>
70 70 #include <mdb/mdb_debug.h>
71 71 #include <mdb/mdb_string.h>
72 72 #include <mdb/mdb_err.h>
73 73 #include <mdb/mdb_ks.h>
74 74 #include <mdb/mdb_gelf.h>
75 75 #include <mdb/mdb_io_impl.h>
76 76 #include <mdb/mdb.h>
77 77
78 78 typedef struct kp_symarg {
79 79 mdb_tgt_sym_f *sym_cb; /* Caller's callback function */
80 80 void *sym_data; /* Callback function argument */
81 81 uint_t sym_type; /* Symbol type/binding filter */
82 82 uintptr_t sym_adjust; /* Symbol value adjustment */
83 83 mdb_syminfo_t sym_info; /* Symbol id and table id */
84 84 const char *sym_obj; /* Containing object */
85 85 } kp_symarg_t;
86 86
87 87 typedef struct kp_file {
88 88 mdb_gelf_file_t *kpf_file; /* ELF file object */
89 89 mdb_io_t *kpf_fio; /* ELF file back-end */
90 90 mdb_gelf_symtab_t *kpf_dynsym; /* Dynamic symbol table */
91 91 struct kp_map *kpf_map; /* Primary (text) mapping */
92 92 const char *kpf_basename; /* Mapping basename */
93 93 uintptr_t kpf_dyn_base; /* Load address for ET_DYN files */
94 94 uintptr_t kpf_text_base; /* Base address of text mapping */
95 95 uintptr_t kpf_data_base; /* Base address of data mapping */
96 96 struct kp_file *kpf_next; /* Pointer to next file */
97 97 } kp_file_t;
98 98
99 99 typedef struct kp_map {
100 100 mdb_map_t kpm_map; /* Mapping information */
101 101 kp_file_t *kpm_file; /* Pointer to load object */
102 102 struct kp_map *kpm_next; /* Pointer to next mapping */
103 103 } kp_map_t;
104 104
105 105 typedef struct kp_io {
106 106 mdb_tgt_t *kpi_tgt; /* Backpointer to kproc target */
107 107 kp_map_t *kpi_map; /* Mapping for this i/o */
108 108 uintptr_t kpi_ptr; /* Virtual address pointer */
109 109 uintptr_t kpi_lim; /* Virtual address limit */
110 110 } kp_io_t;
111 111
112 112 typedef struct kp_data {
113 113 mdb_tgt_t *kp_parent; /* Parent kvm target */
114 114 kvm_t *kp_cookie; /* Cookie for libkvm routines */
115 115 rd_agent_t *kp_rap; /* Cookie for librtld_db routines */
116 116 proc_t *kp_proc; /* Proc address in dump */
117 117 struct as *kp_as; /* Proc as address in dump */
118 118 pid_t kp_pid; /* Process ID */
119 119 auxv_t *kp_auxv; /* Auxv array from u-area */
120 120 int kp_nauxv; /* Length of kp_auxv */
121 121 const char *kp_platform; /* Platform string from kvm target */
122 122 uint_t kp_model; /* Process data model */
123 123 kp_file_t *kp_file_head; /* Head of load object list */
124 124 kp_file_t *kp_file_tail; /* Tail of load object list */
125 125 kp_map_t *kp_map_head; /* Head of mapping list */
126 126 kp_map_t *kp_map_tail; /* Tail of mapping list */
127 127 int kp_num_files; /* Length of load object list */
128 128 int kp_num_maps; /* Length of mapping list */
129 129 kp_map_t *kp_map_exec; /* Executable mapping */
130 130 kp_map_t *kp_map_ldso; /* Interpreter mapping */
131 131 kp_file_t kp_prfile; /* Fake file for mdb.m_prsym */
132 132 } kp_data_t;
133 133
134 134 static mdb_io_t *kp_io_create(mdb_tgt_t *, kp_map_t *);
135 135
136 136 static kp_map_t *
137 137 kp_addr_to_kpmap(kp_data_t *kp, uintptr_t addr)
138 138 {
139 139 kp_map_t *kpm;
140 140
141 141 for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) {
142 142 if (addr >= kpm->kpm_map.map_base &&
143 143 addr < kpm->kpm_map.map_base + kpm->kpm_map.map_size)
144 144 return (kpm);
145 145 }
146 146
147 147 return (NULL);
148 148 }
149 149
150 150 static long
151 151 kp_getauxval(kp_data_t *kp, int type)
152 152 {
153 153 auxv_t *auxp;
154 154
155 155 for (auxp = kp->kp_auxv; auxp->a_type != AT_NULL; auxp++) {
156 156 if (auxp->a_type == type)
157 157 return (auxp->a_un.a_val);
158 158 }
159 159
160 160 return (-1L);
161 161 }
162 162
163 163 static void
164 164 kp_add_mapping(const mdb_map_t *pmp, void *data)
165 165 {
166 166 kp_map_t *kpm = mdb_zalloc(sizeof (kp_map_t), UM_SLEEP);
167 167 kp_data_t *kp = data;
168 168
169 169 bcopy(pmp, &kpm->kpm_map, sizeof (mdb_map_t));
170 170
171 171 if (kp->kp_map_tail != NULL)
172 172 kp->kp_map_tail->kpm_next = kpm;
173 173 else
174 174 kp->kp_map_head = kpm;
175 175
176 176 kp->kp_map_tail = kpm;
177 177 kp->kp_num_maps++;
178 178 }
179 179
180 180 static kp_file_t *
181 181 kp_file_create(mdb_tgt_t *t, kp_map_t *kpm, GElf_Half etype)
182 182 {
183 183 kp_file_t *kpf = mdb_zalloc(sizeof (kp_file_t), UM_SLEEP);
184 184 kp_data_t *kp = t->t_data;
185 185 size_t dyns_sz;
186 186 void *dyns;
187 187
188 188 kpf->kpf_fio = kp_io_create(t, kpm);
189 189 kpf->kpf_map = kpm;
190 190 kpf->kpf_basename = strbasename(kpm->kpm_map.map_name);
191 191 kpf->kpf_file = mdb_gelf_create(kpf->kpf_fio, etype, GF_PROGRAM);
192 192 kpf->kpf_text_base = kpm->kpm_map.map_base;
193 193
194 194 if (kpm != kp->kp_map_exec)
195 195 kpf->kpf_dyn_base = kpf->kpf_text_base;
196 196
197 197 if (kpf->kpf_file == NULL)
198 198 goto err; /* Failed to create ELF file */
199 199
200 200 mdb_dprintf(MDB_DBG_TGT, "loading symbols for %s\n",
201 201 kpm->kpm_map.map_name);
202 202
203 203 if ((kp->kp_rap != NULL) && (rd_get_dyns(kp->kp_rap,
204 204 kpf->kpf_text_base, &dyns, &dyns_sz) == RD_OK))
205 205 mdb_gelf_dyns_set(kpf->kpf_file, dyns, dyns_sz);
206 206
207 207 kpf->kpf_dynsym = mdb_gelf_symtab_create_dynamic(kpf->kpf_file,
208 208 MDB_TGT_DYNSYM);
209 209
210 210 if (kpf->kpf_dynsym == NULL)
211 211 goto err; /* Failed to create symbol table */
212 212
213 213 kpm->kpm_file = kpf;
214 214
215 215 if (kp->kp_file_tail != NULL)
216 216 kp->kp_file_tail->kpf_next = kpf;
217 217 else
218 218 kp->kp_file_head = kpf;
219 219
220 220 kp->kp_file_tail = kpf;
221 221 kp->kp_num_files++;
222 222
223 223 return (kpf);
224 224
225 225 err:
226 226 if (kpf->kpf_file != NULL)
227 227 mdb_gelf_destroy(kpf->kpf_file);
228 228 else
229 229 mdb_io_destroy(kpf->kpf_fio);
230 230 mdb_free(kpf, sizeof (kp_file_t));
231 231 return (NULL);
232 232 }
233 233
234 234 static void
235 235 kp_file_destroy(kp_file_t *kpf)
236 236 {
237 237 if (kpf->kpf_dynsym != NULL)
238 238 mdb_gelf_symtab_destroy(kpf->kpf_dynsym);
239 239
240 240 mdb_gelf_destroy(kpf->kpf_file);
241 241 mdb_free(kpf, sizeof (kp_file_t));
242 242 }
243 243
244 244 static int
245 245 kp_setcontext(mdb_tgt_t *t, void *context)
246 246 {
247 247 kp_data_t *kp = t->t_data;
248 248
249 249 if (kp->kp_proc != context) {
250 250 mdb_tgt_destroy(t);
251 251 return (mdb_tgt_setcontext(mdb.m_target, context));
252 252 }
253 253
254 254 mdb_warn("debugger context is already set to proc %p\n", context);
255 255 return (0);
256 256 }
257 257
258 258 static kp_map_t *
259 259 kp_find_data(kp_data_t *kp, kp_file_t *kpf, const rd_loadobj_t *rlp)
260 260 {
261 261 GElf_Phdr *gpp = kpf->kpf_file->gf_phdrs;
262 262 size_t i, n = kpf->kpf_file->gf_npload;
263 263
264 264 /*
265 265 * Find the first loadable, writeable Phdr and compute kpf_data_base
266 266 * as the virtual address at which is was loaded.
267 267 */
268 268 for (i = 0; i < n; i++, gpp++) {
269 269 if (gpp->p_type == PT_LOAD && (gpp->p_flags & PF_W)) {
270 270 kpf->kpf_data_base = gpp->p_vaddr;
271 271 if (kpf->kpf_map != kp->kp_map_exec)
272 272 kpf->kpf_data_base += rlp->rl_base;
273 273 break;
274 274 }
275 275 }
276 276
277 277 /*
278 278 * If we found a suitable Phdr and set kpf_data_base, return
279 279 * the mapping information for this address; otherwise fail.
280 280 */
281 281 if (kpf->kpf_data_base != 0)
282 282 return (kp_addr_to_kpmap(kp, kpf->kpf_data_base));
283 283
284 284 return (NULL);
285 285 }
286 286
287 287 static int
288 288 kp_iter_mapping(const rd_loadobj_t *rlp, mdb_tgt_t *t)
289 289 {
290 290 kp_data_t *kp = t->t_data;
291 291 kp_file_t *kpf;
292 292 kp_map_t *kpm;
293 293
294 294 char name[MDB_TGT_MAPSZ];
295 295
296 296 if (mdb_tgt_readstr(t, MDB_TGT_AS_VIRT, name,
297 297 sizeof (name), (mdb_tgt_addr_t)rlp->rl_nameaddr) <= 0) {
298 298 mdb_dprintf(MDB_DBG_TGT, "failed to read name %p",
299 299 (void *)rlp->rl_nameaddr);
300 300 return (1); /* Keep going; forget this if we can't read name */
301 301 }
302 302
303 303 mdb_dprintf(MDB_DBG_TGT, "rd_loadobj name = \"%s\" rl_base = %p\n",
304 304 name, (void *)rlp->rl_base);
305 305
306 306 if ((kpm = kp_addr_to_kpmap(kp, rlp->rl_base)) == NULL)
307 307 return (1); /* Keep going; no mapping at this address */
308 308
309 309 (void) strncpy(kpm->kpm_map.map_name, name, MDB_TGT_MAPSZ);
310 310 kpm->kpm_map.map_name[MDB_TGT_MAPSZ - 1] = '\0';
311 311
312 312 if ((kpf = kpm->kpm_file) == NULL) {
313 313 if (kpm == kp->kp_map_exec)
314 314 kpf = kp_file_create(t, kpm, ET_EXEC);
315 315 else
316 316 kpf = kp_file_create(t, kpm, ET_DYN);
317 317
318 318 if (kpf == NULL)
319 319 return (1); /* Keep going; failed to build ELF file */
320 320 } else
321 321 kpf->kpf_basename = strbasename(kpm->kpm_map.map_name);
322 322
323 323 if ((kpm = kp_find_data(kp, kpf, rlp)) != NULL) {
324 324 mdb_dprintf(MDB_DBG_TGT, "found data for %s at %p\n",
325 325 kpf->kpf_basename, (void *)kpm->kpm_map.map_base);
326 326 kpm->kpm_file = kpf;
327 327 }
328 328
329 329 return (1);
330 330 }
331 331
332 332 /*ARGSUSED*/
333 333 static int
334 334 kp_status_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
335 335 {
336 336 kp_data_t *kp = mdb.m_target->t_data;
337 337
338 338 mdb_printf("debugging PID %d (%d-bit) in kernel crash dump\n",
339 339 kp->kp_pid, kp->kp_model == PR_MODEL_ILP32 ? 32 : 64);
340 340
341 341 if (kp->kp_map_exec != NULL) {
342 342 mdb_printf("executable file: %s\n",
343 343 kp->kp_map_exec->kpm_map.map_name);
344 344 }
345 345
346 346 return (DCMD_OK);
347 347 }
348 348
349 349 static const mdb_dcmd_t kp_dcmds[] = {
350 350 { "status", NULL, "print summary of current target", kp_status_dcmd },
351 351 { NULL }
352 352 };
353 353
354 354 static void
355 355 kp_activate(mdb_tgt_t *t)
356 356 {
357 357 kp_data_t *kp = t->t_data;
358 358
359 359 mdb_prop_postmortem = TRUE;
360 360 mdb_prop_kernel = FALSE;
361 361
362 362 if (kp->kp_model == PR_MODEL_ILP32)
363 363 mdb_prop_datamodel = MDB_TGT_MODEL_ILP32;
364 364 else
365 365 mdb_prop_datamodel = MDB_TGT_MODEL_LP64;
366 366
367 367 /*
368 368 * Initialize our rtld_db agent and then iterate over the link map,
369 369 * instantiating kp_file objects as we go.
370 370 */
371 371 if ((kp->kp_rap = rd_new((struct ps_prochandle *)t)) != NULL) {
372 372 (void) rd_loadobj_iter(kp->kp_rap, (rl_iter_f *)
373 373 kp_iter_mapping, t);
374 374 } else {
375 375 mdb_warn("unable to initialize rtld_db agent for proc %p\n",
376 376 (void *)kp->kp_proc);
377 377 }
378 378
379 379 (void) mdb_tgt_register_dcmds(t, &kp_dcmds[0], MDB_MOD_FORCE);
380 380
381 381 if (kp->kp_map_exec != NULL && kp->kp_map_exec->kpm_file != NULL)
382 382 mdb_tgt_elf_export(kp->kp_map_exec->kpm_file->kpf_file);
383 383 else
384 384 mdb_tgt_elf_export(NULL);
385 385 }
386 386
387 387 static void
388 388 kp_deactivate(mdb_tgt_t *t)
389 389 {
390 390 const mdb_dcmd_t *dcp;
391 391
392 392 for (dcp = &kp_dcmds[0]; dcp->dc_name != NULL; dcp++) {
393 393 if (mdb_module_remove_dcmd(t->t_module, dcp->dc_name) == -1)
394 394 warn("failed to remove dcmd %s", dcp->dc_name);
395 395 }
396 396
397 397 mdb_prop_postmortem = FALSE;
398 398 mdb_prop_kernel = FALSE;
399 399 mdb_prop_datamodel = MDB_TGT_MODEL_UNKNOWN;
400 400 }
401 401
402 402 static void
403 403 kp_destroy(mdb_tgt_t *t)
404 404 {
405 405 kp_data_t *kp = t->t_data;
406 406 kp_map_t *kpm, *nkpm;
407 407 kp_file_t *kpf, *nkpf;
408 408
409 409 if (kp->kp_rap != NULL)
410 410 rd_delete(kp->kp_rap);
411 411
412 412 for (kpm = kp->kp_map_head; kpm != NULL; kpm = nkpm) {
413 413 nkpm = kpm->kpm_next;
414 414 mdb_free(kpm, sizeof (kp_map_t));
415 415 }
416 416
417 417 for (kpf = kp->kp_file_head; kpf != NULL; kpf = nkpf) {
418 418 nkpf = kpf->kpf_next;
419 419 kp_file_destroy(kpf);
420 420 }
421 421
422 422 mdb_free(kp->kp_auxv, kp->kp_nauxv * sizeof (auxv_t));
423 423 mdb_free(kp, sizeof (kp_data_t));
424 424 }
425 425
426 426 /*ARGSUSED*/
427 427 static const char *
428 428 kp_name(mdb_tgt_t *t)
429 429 {
430 430 return ("kproc");
431 431 }
432 432
433 433 static const char *
434 434 kp_isa(mdb_tgt_t *t)
435 435 {
436 436 kp_data_t *kp = t->t_data;
437 437 #ifdef __sparc
438 438 return (kp->kp_model == PR_MODEL_ILP32 ? "sparc" : "sparcv9");
439 439 #else
440 440 return (kp->kp_model == PR_MODEL_ILP32 ? "i386" : "amd64");
441 441 #endif
442 442 }
443 443
444 444 static const char *
445 445 kp_platform(mdb_tgt_t *t)
446 446 {
447 447 return (((kp_data_t *)t->t_data)->kp_platform);
448 448 }
449 449
450 450 static int
451 451 kp_uname(mdb_tgt_t *t, struct utsname *utsp)
452 452 {
453 453 kp_data_t *kp = t->t_data;
454 454 return (mdb_tgt_uname(kp->kp_parent, utsp));
455 455 }
456 456
457 457 static int
458 458 kp_dmodel(mdb_tgt_t *t)
459 459 {
460 460 kp_data_t *kp = t->t_data;
461 461
462 462 switch (kp->kp_model) {
463 463 case PR_MODEL_ILP32:
464 464 return (MDB_TGT_MODEL_ILP32);
465 465 case PR_MODEL_LP64:
466 466 return (MDB_TGT_MODEL_LP64);
467 467 }
468 468
469 469 return (MDB_TGT_MODEL_UNKNOWN);
470 470 }
471 471
472 472 static kp_map_t *
473 473 kp_name_to_kpmap(kp_data_t *kp, const char *name)
474 474 {
475 475 size_t namelen;
476 476 kp_file_t *kpf;
477 477 kp_map_t *kpm;
478 478
479 479 /*
480 480 * Handle special reserved names (except for MDB_TGT_OBJ_EVERY):
481 481 */
482 482 if (name == MDB_TGT_OBJ_EXEC)
483 483 return (kp->kp_map_exec);
484 484
485 485 if (name == MDB_TGT_OBJ_RTLD)
486 486 return (kp->kp_map_ldso);
487 487
488 488 /*
489 489 * First pass: look for exact matches on the entire pathname
490 490 * associated with the mapping or its basename.
491 491 */
492 492 for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) {
493 493 if ((kpf = kpm->kpm_file) != NULL) {
494 494 if (strcmp(kpm->kpm_map.map_name, name) == 0 ||
495 495 strcmp(kpf->kpf_basename, name) == 0)
496 496 return (kpf->kpf_map);
497 497 }
498 498 }
499 499
500 500 namelen = strlen(name);
501 501
502 502 /*
503 503 * Second pass: look for partial matches (initial basename match
504 504 * up to a '.' suffix); allows "libc.so" or "libc" to match "libc.so.1"
505 505 */
506 506 for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) {
507 507 if ((kpf = kpm->kpm_file) != NULL) {
508 508 if (strncmp(kpf->kpf_basename, name, namelen) == 0 &&
509 509 kpf->kpf_basename[namelen] == '.')
510 510 return (kpf->kpf_map);
511 511 }
512 512 }
513 513
514 514 /*
515 515 * One last check: we allow "a.out" to always alias the executable,
516 516 * assuming this name was not in use for something else.
517 517 */
518 518 if (strcmp(name, "a.out") == 0)
519 519 return (kp->kp_map_exec);
520 520
521 521 return (NULL);
522 522 }
523 523
524 524
525 525 static ssize_t
526 526 kp_vread(mdb_tgt_t *t, void *buf, size_t nbytes, uintptr_t addr)
527 527 {
528 528 kp_data_t *kp = t->t_data;
529 529 ssize_t n = kvm_aread(kp->kp_cookie, addr, buf, nbytes, kp->kp_as);
530 530
531 531 if (n == -1)
532 532 return (set_errno(EMDB_NOMAP));
533 533
534 534 return (n);
535 535 }
536 536
537 537 static ssize_t
538 538 kp_vwrite(mdb_tgt_t *t, const void *buf, size_t nbytes, uintptr_t addr)
539 539 {
540 540 kp_data_t *kp = t->t_data;
541 541 ssize_t n = kvm_awrite(kp->kp_cookie, addr, buf, nbytes, kp->kp_as);
542 542
543 543 if (n == -1)
544 544 return (set_errno(EMDB_NOMAP));
545 545
546 546 return (n);
547 547 }
548 548
549 549
550 550 int
551 551 kp_vtop(mdb_tgt_t *t, mdb_tgt_as_t as, uintptr_t va, physaddr_t *pap)
552 552 {
553 553 kp_data_t *kp = t->t_data;
554 554 physaddr_t pa;
555 555
556 556 if (as != MDB_TGT_AS_VIRT)
557 557 return (set_errno(EINVAL));
558 558
559 559 if ((pa = kvm_physaddr(kp->kp_cookie, kp->kp_as, va)) != -1ULL) {
560 560 *pap = pa;
561 561 return (0);
562 562 }
563 563
564 564 return (set_errno(EMDB_NOMAP));
565 565 }
566 566
567 567 static int
568 568 kp_lookup_by_name(mdb_tgt_t *t, const char *object,
569 569 const char *name, GElf_Sym *symp, mdb_syminfo_t *sip)
570 570 {
571 571 kp_data_t *kp = t->t_data;
572 572 kp_file_t *kpf;
573 573 int n;
574 574
575 575 GElf_Sym sym;
576 576 uint_t symid;
577 577 int rv = -1;
578 578
579 579 /*
580 580 * Simplify our task: if object is EVERY, then we need to search
581 581 * kp_num_files files beginning at kp_file_head; otherwise we are
582 582 * searching 1 file whose file pointer is obtained via object_to_map.
583 583 */
584 584 if (object != MDB_TGT_OBJ_EVERY) {
585 585 kp_map_t *kpm = kp_name_to_kpmap(kp, object);
586 586 if (kpm == NULL || kpm->kpm_file == NULL)
587 587 return (set_errno(EMDB_NOOBJ));
588 588 kpf = kpm->kpm_file;
589 589 n = 1;
590 590 } else {
591 591 kpf = kp->kp_file_head;
592 592 n = kp->kp_num_files;
593 593 }
594 594
595 595 /*
596 596 * Iterate through the load object files and look for the symbol name
597 597 * in the .dynsym of each. If we encounter a match with SHN_UNDEF,
598 598 * keep looking in hopes of finding a better match. This means that
599 599 * a name such as "puts" will match the puts function in libc instead
600 600 * of matching the puts PLT entry in the a.out file.
601 601 */
602 602 for (; n > 0; n--, kpf = kpf->kpf_next) {
603 603 if (kpf->kpf_dynsym == NULL)
604 604 continue; /* No symbols for this file */
605 605
606 606 if (mdb_gelf_symtab_lookup_by_name(kpf->kpf_dynsym,
607 607 name, symp, &sip->sym_id) != 0)
608 608 continue; /* Symbol name not found */
609 609
610 610 symp->st_value += kpf->kpf_dyn_base;
611 611
612 612 if (symp->st_shndx != SHN_UNDEF) {
613 613 sip->sym_table = MDB_TGT_DYNSYM;
614 614 return (0);
615 615 }
616 616
617 617 if (rv != 0) {
618 618 sym = *symp;
619 619 symid = sip->sym_id;
620 620 rv = 0;
621 621 }
622 622 }
623 623
624 624 if (rv != 0)
625 625 return (set_errno(EMDB_NOSYM));
626 626
627 627 sip->sym_table = MDB_TGT_DYNSYM;
628 628 sip->sym_id = symid;
629 629 *symp = sym;
630 630
631 631 return (0);
632 632 }
633 633
634 634 static int
635 635 kp_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags,
636 636 char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip)
637 637 {
638 638 kp_data_t *kp = t->t_data;
639 639 kp_map_t *kpm = kp_addr_to_kpmap(kp, addr);
640 640
641 641 kp_file_t *sym_kpf = NULL;
642 642 GElf_Sym sym;
643 643 uint_t symid;
644 644
645 645 const char *name;
646 646 kp_file_t *kpf;
647 647 int n;
648 648
649 649 /*
650 650 * Check the user's private symbol table first; if a match is
651 651 * found there, we're done or we have a first guess.
652 652 */
653 653 if (mdb_gelf_symtab_lookup_by_addr(mdb.m_prsym,
654 654 addr, flags, buf, nbytes, symp, &sip->sym_id) == 0) {
655 655 sym_kpf = &kp->kp_prfile;
656 656 if (flags & MDB_TGT_SYM_EXACT)
657 657 goto found;
658 658 sym = *symp;
659 659 symid = sip->sym_id;
660 660 }
661 661
662 662 /*
663 663 * If no mapping contains the address and EXACT mode is set, we're done.
664 664 * Otherwise we need to search all the symbol tables in fuzzy mode.
665 665 * If we find a mapping, then we only need to search that symtab.
666 666 */
667 667 if (kpm == NULL || kpm->kpm_file == NULL) {
668 668 if (flags & MDB_TGT_SYM_EXACT)
669 669 return (set_errno(EMDB_NOSYMADDR));
670 670 kpf = kp->kp_file_head;
671 671 n = kp->kp_num_files;
672 672 } else {
673 673 kpf = kpm->kpm_file;
674 674 n = 1;
675 675 }
676 676
677 677 /*
678 678 * Iterate through our list of load objects, scanning each one which
679 679 * has a symbol table. In fuzzy mode, we continue looking and
680 680 * improve our choice if we find a closer symbol.
681 681 */
682 682 for (; n > 0; n--, kpf = kpf->kpf_next) {
683 683 if (kpf->kpf_dynsym == NULL)
684 684 continue; /* No symbols for this file */
685 685
686 686 if (mdb_gelf_symtab_lookup_by_addr(kpf->kpf_dynsym,
687 687 addr - kpf->kpf_dyn_base, flags, buf, nbytes,
688 688 symp, &sip->sym_id) != 0)
689 689 continue; /* No symbol for this address */
690 690
691 691 symp->st_value += kpf->kpf_dyn_base;
692 692
693 693 if (flags & MDB_TGT_SYM_EXACT) {
694 694 sym_kpf = kpf;
695 695 goto found;
696 696 }
697 697
698 698 if (sym_kpf == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) {
699 699 sym_kpf = kpf;
700 700 sym = *symp;
701 701 symid = sip->sym_id;
702 702 }
703 703 }
704 704
705 705 if (sym_kpf == NULL)
706 706 return (set_errno(EMDB_NOSYMADDR));
707 707
708 708 *symp = sym; /* Copy our best symbol into the caller's symbol */
709 709 sip->sym_id = symid;
710 710 found:
711 711 /*
712 712 * Once we've found something, copy the final name into the caller's
713 713 * buffer and prefix it with the load object name if appropriate.
714 714 */
715 715 name = mdb_gelf_sym_name(sym_kpf->kpf_dynsym, symp);
716 716
717 717 if (sym_kpf != kp->kp_map_exec->kpm_file && sym_kpf != &kp->kp_prfile) {
718 718 (void) mdb_snprintf(buf, nbytes, "%s`%s",
719 719 sym_kpf->kpf_basename, name);
720 720 } else if (nbytes > 0) {
721 721 (void) strncpy(buf, name, nbytes);
722 722 buf[nbytes - 1] = '\0';
723 723 }
724 724
725 725 if (sym_kpf == &kp->kp_prfile)
726 726 sip->sym_table = MDB_TGT_PRVSYM;
727 727 else
728 728 sip->sym_table = MDB_TGT_DYNSYM;
729 729
730 730 return (0);
731 731 }
732 732
733 733 static int
734 734 kp_symtab_func(void *data, const GElf_Sym *symp, const char *name, uint_t id)
735 735 {
736 736 kp_symarg_t *argp = data;
737 737 if (mdb_tgt_sym_match(symp, argp->sym_type)) {
738 738 GElf_Sym sym = *symp;
739 739
740 740 sym.st_value += argp->sym_adjust;
741 741
742 742 argp->sym_info.sym_id = id;
743 743
744 744 return (argp->sym_cb(argp->sym_data, &sym, name,
745 745 &argp->sym_info, argp->sym_obj));
746 746 }
747 747
748 748 return (0);
749 749 }
750 750
751 751 static void
752 752 kp_symtab_iter(kp_file_t *kpf, uint_t type, const char *obj,
753 753 mdb_tgt_sym_f *cb, void *data)
754 754 {
755 755 if (kpf->kpf_dynsym != NULL) {
756 756 kp_symarg_t arg;
757 757
758 758 arg.sym_cb = cb;
759 759 arg.sym_data = data;
760 760 arg.sym_type = type;
761 761 arg.sym_adjust = kpf->kpf_dyn_base;
762 762 arg.sym_info.sym_table = kpf->kpf_dynsym->gst_tabid;
763 763 arg.sym_obj = obj;
764 764
765 765 mdb_gelf_symtab_iter(kpf->kpf_dynsym, kp_symtab_func, &arg);
766 766 }
767 767 }
768 768
769 769 /*ARGSUSED*/
770 770 static int
771 771 kp_symbol_iter(mdb_tgt_t *t, const char *object, uint_t which,
772 772 uint_t type, mdb_tgt_sym_f *func, void *private)
773 773 {
774 774 kp_data_t *kp = t->t_data;
775 775 kp_file_t *kpf = NULL;
776 776 kp_map_t *kpm;
777 777
778 778 switch ((uintptr_t)object) {
779 779 case (uintptr_t)MDB_TGT_OBJ_EVERY:
780 780 if (kp->kp_map_exec && kp->kp_map_exec->kpm_file) {
781 781 kpf = kp->kp_map_exec->kpm_file;
782 782 kp_symtab_iter(kpf, type, MDB_TGT_OBJ_EXEC, func,
783 783 private);
784 784 }
785 785 if (kp->kp_map_ldso && kp->kp_map_ldso->kpm_file) {
786 786 kpf = kp->kp_map_ldso->kpm_file;
787 787 kp_symtab_iter(kpf, type, MDB_TGT_OBJ_RTLD, func,
788 788 private);
789 789 }
790 790 return (0);
791 791
792 792 case (uintptr_t)MDB_TGT_OBJ_EXEC:
793 793 if (kp->kp_map_exec && kp->kp_map_exec->kpm_file)
794 794 kpf = kp->kp_map_exec->kpm_file;
795 795 break;
796 796
797 797 case (uintptr_t)MDB_TGT_OBJ_RTLD:
798 798 if (kp->kp_map_ldso && kp->kp_map_ldso->kpm_file)
799 799 kpf = kp->kp_map_ldso->kpm_file;
800 800 break;
801 801
802 802 default:
803 803 if ((kpm = kp_name_to_kpmap(kp, object)) != NULL) {
804 804 kpf = kpm->kpm_file;
805 805 break;
806 806 } else
807 807 return (set_errno(EMDB_NOOBJ));
808 808 }
809 809
810 810 if (kpf != NULL)
811 811 kp_symtab_iter(kpf, type, object, func, private);
812 812
813 813 return (0);
814 814 }
815 815
816 816 static int
817 817 kp_mapping_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
818 818 {
819 819 kp_data_t *kp = t->t_data;
820 820 kp_map_t *kpm;
821 821
822 822 for (kpm = kp->kp_map_head; kpm != NULL; kpm = kpm->kpm_next) {
823 823 if (func(private, &kpm->kpm_map, kpm->kpm_map.map_name) != 0)
824 824 break;
825 825 }
826 826
827 827 return (0);
828 828 }
829 829
830 830 static int
831 831 kp_object_iter(mdb_tgt_t *t, mdb_tgt_map_f *func, void *private)
832 832 {
833 833 kp_data_t *kp = t->t_data;
834 834 kp_file_t *kpf;
835 835
836 836 for (kpf = kp->kp_file_head; kpf != NULL; kpf = kpf->kpf_next) {
837 837 if (func(private, &kpf->kpf_map->kpm_map,
838 838 kpf->kpf_map->kpm_map.map_name) != 0)
839 839 break;
840 840 }
841 841
842 842 return (0);
843 843 }
844 844
845 845 static const mdb_map_t *
846 846 kp_addr_to_map(mdb_tgt_t *t, uintptr_t addr)
847 847 {
848 848 kp_map_t *kpm = kp_addr_to_kpmap(t->t_data, addr);
849 849
850 850 if (kpm != NULL)
851 851 return (&kpm->kpm_map);
852 852
853 853 (void) set_errno(EMDB_NOMAP);
854 854 return (NULL);
855 855 }
856 856
857 857 static const mdb_map_t *
858 858 kp_name_to_map(mdb_tgt_t *t, const char *name)
859 859 {
860 860 kp_map_t *kpm = kp_name_to_kpmap(t->t_data, name);
861 861
862 862 if (kpm != NULL)
863 863 return (&kpm->kpm_map);
864 864
865 865 (void) set_errno(EMDB_NOOBJ);
866 866 return (NULL);
867 867 }
868 868
869 869 /*ARGSUSED*/
870 870 static int
871 871 kp_status(mdb_tgt_t *t, mdb_tgt_status_t *tsp)
872 872 {
873 873 bzero(tsp, sizeof (mdb_tgt_status_t));
874 874 tsp->st_state = MDB_TGT_DEAD;
875 875 return (0);
876 876 }
877 877
878 878 static int
879 879 kp_auxv(mdb_tgt_t *t, const auxv_t **auxvp)
880 880 {
881 881 kp_data_t *kp = t->t_data;
882 882 *auxvp = kp->kp_auxv;
883 883 return (0);
884 884 }
885 885
886 886 static const mdb_tgt_ops_t kproc_ops = {
887 887 (int (*)()) mdb_tgt_notsup, /* t_setflags */
888 888 kp_setcontext, /* t_setcontext */
889 889 kp_activate, /* t_activate */
890 890 kp_deactivate, /* t_deactivate */
891 891 (void (*)()) mdb_tgt_nop, /* t_periodic */
892 892 kp_destroy, /* t_destroy */
893 893 kp_name, /* t_name */
894 894 kp_isa, /* t_isa */
895 895 kp_platform, /* t_platform */
896 896 kp_uname, /* t_uname */
897 897 kp_dmodel, /* t_dmodel */
898 898 (ssize_t (*)()) mdb_tgt_notsup, /* t_aread */
899 899 (ssize_t (*)()) mdb_tgt_notsup, /* t_awrite */
900 900 kp_vread, /* t_vread */
901 901 kp_vwrite, /* t_vwrite */
902 902 (ssize_t (*)()) mdb_tgt_notsup, /* t_pread */
903 903 (ssize_t (*)()) mdb_tgt_notsup, /* t_pwrite */
904 904 (ssize_t (*)()) mdb_tgt_notsup, /* t_fread */
905 905 (ssize_t (*)()) mdb_tgt_notsup, /* t_fwrite */
906 906 (ssize_t (*)()) mdb_tgt_notsup, /* t_ioread */
907 907 (ssize_t (*)()) mdb_tgt_notsup, /* t_iowrite */
908 908 kp_vtop, /* t_vtop */
909 909 kp_lookup_by_name, /* t_lookup_by_name */
910 910 kp_lookup_by_addr, /* t_lookup_by_addr */
911 911 kp_symbol_iter, /* t_symbol_iter */
↓ open down ↓ |
874 lines elided |
↑ open up ↑ |
912 912 kp_mapping_iter, /* t_mapping_iter */
913 913 kp_object_iter, /* t_object_iter */
914 914 kp_addr_to_map, /* t_addr_to_map */
915 915 kp_name_to_map, /* t_name_to_map */
916 916 (struct ctf_file *(*)()) mdb_tgt_null, /* t_addr_to_ctf */
917 917 (struct ctf_file *(*)()) mdb_tgt_null, /* t_name_to_ctf */
918 918 kp_status, /* t_status */
919 919 (int (*)()) mdb_tgt_notsup, /* t_run */
920 920 (int (*)()) mdb_tgt_notsup, /* t_step */
921 921 (int (*)()) mdb_tgt_notsup, /* t_step_out */
922 - (int (*)()) mdb_tgt_notsup, /* t_step_branch */
923 922 (int (*)()) mdb_tgt_notsup, /* t_next */
924 923 (int (*)()) mdb_tgt_notsup, /* t_cont */
925 924 (int (*)()) mdb_tgt_notsup, /* t_signal */
926 925 (int (*)()) mdb_tgt_null, /* t_add_sbrkpt */
927 926 (int (*)()) mdb_tgt_null, /* t_add_vbrkpt */
928 927 (int (*)()) mdb_tgt_null, /* t_add_pwapt */
929 928 (int (*)()) mdb_tgt_null, /* t_add_vwapt */
930 929 (int (*)()) mdb_tgt_null, /* t_add_iowapt */
931 930 (int (*)()) mdb_tgt_null, /* t_add_sysenter */
932 931 (int (*)()) mdb_tgt_null, /* t_add_sysexit */
933 932 (int (*)()) mdb_tgt_null, /* t_add_signal */
934 933 (int (*)()) mdb_tgt_null, /* t_add_fault */
935 934 (int (*)()) mdb_tgt_notsup, /* t_getareg XXX */
936 935 (int (*)()) mdb_tgt_notsup, /* t_putareg XXX */
937 936 (int (*)()) mdb_tgt_notsup, /* t_stack_iter XXX */
938 937 kp_auxv /* t_auxv */
939 938 };
940 939
941 940 int
942 941 mdb_kproc_tgt_create(mdb_tgt_t *t, int argc, const char *argv[])
943 942 {
944 943 kp_data_t *kp = mdb_zalloc(sizeof (kp_data_t), UM_SLEEP);
945 944 void *proc = (void *)argv[0];
946 945 long at_entry, at_base;
947 946 GElf_Sym sym;
948 947
949 948 int (*f_asiter)(uintptr_t, void (*)(const mdb_map_t *, void *), void *);
950 949 int (*f_auxv)(uintptr_t, auxv_t *);
951 950 uintptr_t (*f_as)(uintptr_t);
952 951 uint_t (*f_model)(uintptr_t);
953 952 pid_t (*f_pid)(uintptr_t);
954 953
955 954 if (argc != 1)
956 955 return (set_errno(EINVAL));
957 956
958 957 t->t_flags &= ~MDB_TGT_F_RDWR;
959 958 t->t_data = kp;
960 959 t->t_ops = &kproc_ops;
961 960
962 961 f_asiter = (int (*)()) dlsym(RTLD_NEXT, "mdb_kproc_asiter");
963 962 f_auxv = (int (*)()) dlsym(RTLD_NEXT, "mdb_kproc_auxv");
964 963 f_as = (uintptr_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_as");
965 964 f_model = (model_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_model");
966 965 f_pid = (pid_t (*)()) dlsym(RTLD_NEXT, "mdb_kproc_pid");
967 966
968 967 if (f_asiter == NULL || f_auxv == NULL ||
969 968 f_as == NULL || f_model == NULL || f_pid == NULL) {
970 969 warn("required kernel support module is not loaded\n");
971 970 goto err;
972 971 }
973 972
974 973 /*
975 974 * Here the kproc target relies on the fact that at the time of its
976 975 * instantiation, mdb.m_target is pointing at a kvm target, and
977 976 * that the kvm target has stored its libkvm handle in t_pshandle.
978 977 */
979 978 kp->kp_parent = mdb.m_target;
980 979 kp->kp_cookie = mdb.m_target->t_pshandle;
981 980 kp->kp_platform = mdb_tgt_platform(mdb.m_target);
982 981 kp->kp_proc = proc;
983 982 kp->kp_as = (struct as *)f_as((uintptr_t)proc);
984 983 kp->kp_pid = f_pid((uintptr_t)proc);
985 984
986 985 if (kp->kp_as == NULL) {
987 986 warn("failed to obtain address space for proc %p\n", proc);
988 987 goto err;
989 988 }
990 989
991 990 if (kp->kp_pid == -1) {
992 991 warn("failed to obtain PID for proc %p\n", proc);
993 992 goto err;
994 993 }
995 994
996 995 if (mdb_tgt_lookup_by_name(kp->kp_parent, MDB_TGT_OBJ_EXEC, "kas",
997 996 &sym, NULL) == 0 && kp->kp_as ==
998 997 (struct as *)(uintptr_t)sym.st_value) {
999 998 warn("specified process is a system process (no context)\n");
1000 999 goto err;
1001 1000 }
1002 1001
1003 1002 if ((kp->kp_model = f_model((uintptr_t)proc)) == PR_MODEL_UNKNOWN) {
1004 1003 warn("failed to obtain data model for proc %p\n", proc);
1005 1004 goto err;
1006 1005 }
1007 1006
1008 1007 if (f_asiter((uintptr_t)kp->kp_as, kp_add_mapping, kp) == -1) {
1009 1008 warn("failed to load mappings for proc %p", proc);
1010 1009 goto err;
1011 1010 }
1012 1011
1013 1012 kp->kp_nauxv = f_auxv((uintptr_t)proc, NULL) + 1;
1014 1013 kp->kp_auxv = mdb_alloc(sizeof (auxv_t) * kp->kp_nauxv, UM_SLEEP);
1015 1014
1016 1015 if (f_auxv((uintptr_t)proc, kp->kp_auxv) == -1) {
1017 1016 warn("failed to load auxv for proc %p", proc);
1018 1017 goto err;
1019 1018 }
1020 1019
1021 1020 kp->kp_auxv[kp->kp_nauxv - 1].a_type = AT_NULL;
1022 1021 kp->kp_auxv[kp->kp_nauxv - 1].a_un.a_val = 0;
1023 1022
1024 1023 if ((at_entry = kp_getauxval(kp, AT_ENTRY)) == -1L) {
1025 1024 warn("auxv for proc %p is missing AT_ENTRY\n", proc);
1026 1025 goto err;
1027 1026 }
1028 1027
1029 1028 if ((at_base = kp_getauxval(kp, AT_BASE)) == -1L) {
1030 1029 warn("auxv for proc %p is missing AT_BASE\n", proc);
1031 1030 goto err;
1032 1031 }
1033 1032
1034 1033 /*
1035 1034 * If we're applying kproc to a live kernel, we need to force libkvm
1036 1035 * to set the current process to the process in question so we can
1037 1036 * read from its address space. If kvm_getproc returns NULL, the
1038 1037 * process may have gone away since our previous calls to mdb_ks.
1039 1038 */
1040 1039 if (mdb_prop_postmortem == FALSE &&
1041 1040 kvm_getproc(kp->kp_cookie, kp->kp_pid) == NULL)
1042 1041 warn("failed to attach to PID %d\n", (int)kp->kp_pid);
1043 1042
1044 1043 kp->kp_map_exec = kp_addr_to_kpmap(kp, at_entry);
1045 1044 kp->kp_map_ldso = kp_addr_to_kpmap(kp, at_base);
1046 1045
1047 1046 (void) kp_file_create(t, kp->kp_map_exec, ET_EXEC);
1048 1047 (void) kp_file_create(t, kp->kp_map_ldso, ET_DYN);
1049 1048
1050 1049 kp->kp_prfile.kpf_dynsym = mdb.m_prsym;
1051 1050
1052 1051 return (0);
1053 1052
1054 1053 err:
1055 1054 kp_destroy(t);
1056 1055 return (-1);
1057 1056 }
1058 1057
1059 1058 static ssize_t
1060 1059 kp_io_read(mdb_io_t *io, void *buf, size_t nbytes)
1061 1060 {
1062 1061 kp_io_t *kpi = io->io_data;
1063 1062 kp_data_t *kp = kpi->kpi_tgt->t_data;
1064 1063
1065 1064 kp_map_t *kpm = kp_addr_to_kpmap(kp, kpi->kpi_ptr);
1066 1065 size_t left;
1067 1066
1068 1067 if (kpm != NULL) {
1069 1068 const mdb_map_t *mp = &kpm->kpm_map;
1070 1069 left = mp->map_base + mp->map_size - kpi->kpi_ptr;
1071 1070 } else
1072 1071 left = 0;
1073 1072
1074 1073 if (left != 0) {
1075 1074 ssize_t rbytes = kp_vread(kpi->kpi_tgt,
1076 1075 buf, MIN(nbytes, left), kpi->kpi_ptr);
1077 1076
1078 1077 if (rbytes >= 0)
1079 1078 kpi->kpi_ptr += rbytes;
1080 1079
1081 1080 return (rbytes);
1082 1081 }
1083 1082
1084 1083 return (0); /* At end of segment or in hole; return EOF */
1085 1084 }
1086 1085
1087 1086 static off64_t
1088 1087 kp_io_seek(mdb_io_t *io, off64_t offset, int whence)
1089 1088 {
1090 1089 kp_io_t *kpi = io->io_data;
1091 1090 const mdb_map_t *mp = &kpi->kpi_map->kpm_map;
1092 1091 uintptr_t nptr;
1093 1092
1094 1093 if (io->io_next != NULL)
1095 1094 return (IOP_SEEK(io->io_next, offset, whence));
1096 1095
1097 1096 switch (whence) {
1098 1097 case SEEK_SET:
1099 1098 nptr = mp->map_base + offset;
1100 1099 break;
1101 1100 case SEEK_CUR:
1102 1101 nptr = kpi->kpi_ptr + offset;
1103 1102 break;
1104 1103 case SEEK_END:
1105 1104 nptr = kpi->kpi_lim + offset;
1106 1105 break;
1107 1106 default:
1108 1107 return (set_errno(EINVAL));
1109 1108 }
1110 1109
1111 1110 if (nptr < mp->map_base || nptr >= kpi->kpi_lim)
1112 1111 return (set_errno(EINVAL));
1113 1112
1114 1113 kpi->kpi_ptr = nptr;
1115 1114 return ((off64_t)(nptr - mp->map_base));
1116 1115 }
1117 1116
1118 1117 static void
1119 1118 kp_io_close(mdb_io_t *io)
1120 1119 {
1121 1120 mdb_free(io->io_data, sizeof (kp_io_t));
1122 1121 }
1123 1122
1124 1123 static const char *
1125 1124 kp_io_name(mdb_io_t *io)
1126 1125 {
1127 1126 kp_io_t *kpi = io->io_data;
1128 1127
1129 1128 if (io->io_next != NULL)
1130 1129 return (IOP_NAME(io->io_next));
1131 1130
1132 1131 return (kpi->kpi_map->kpm_map.map_name);
1133 1132 }
1134 1133
1135 1134 static const mdb_io_ops_t kp_io_ops = {
1136 1135 kp_io_read,
1137 1136 no_io_write,
1138 1137 kp_io_seek,
1139 1138 no_io_ctl,
1140 1139 kp_io_close,
1141 1140 kp_io_name,
1142 1141 no_io_link,
1143 1142 no_io_unlink,
1144 1143 no_io_setattr,
1145 1144 no_io_suspend,
1146 1145 no_io_resume
1147 1146 };
1148 1147
1149 1148 static mdb_io_t *
1150 1149 kp_io_create(mdb_tgt_t *t, kp_map_t *kpm)
1151 1150 {
1152 1151 kp_data_t *kp = t->t_data;
1153 1152 mdb_map_t *mp = &kp->kp_map_tail->kpm_map;
1154 1153
1155 1154 mdb_io_t *io = mdb_alloc(sizeof (mdb_io_t), UM_SLEEP);
1156 1155 kp_io_t *kpi = mdb_alloc(sizeof (kp_io_t), UM_SLEEP);
1157 1156
1158 1157 kpi->kpi_tgt = t;
1159 1158 kpi->kpi_map = kpm;
1160 1159 kpi->kpi_ptr = kpm->kpm_map.map_base;
1161 1160 kpi->kpi_lim = mp->map_base + mp->map_size;
1162 1161
1163 1162 io->io_ops = &kp_io_ops;
1164 1163 io->io_data = kpi;
1165 1164 io->io_next = NULL;
1166 1165 io->io_refcnt = 0;
1167 1166
1168 1167 return (io);
1169 1168 }
↓ open down ↓ |
237 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX