Print this page
3946 ::gcore
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libproc/common/Psymtab.c
+++ new/usr/src/lib/libproc/common/Psymtab.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
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 /*
23 23 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 + * Copyright (c) 2013 by Delphix. All rights reserved.
25 26 */
26 27
27 28 #include <assert.h>
28 29 #include <stdio.h>
29 30 #include <stdlib.h>
30 31 #include <stddef.h>
31 32 #include <unistd.h>
32 33 #include <ctype.h>
33 34 #include <fcntl.h>
34 35 #include <string.h>
35 36 #include <strings.h>
36 37 #include <memory.h>
37 38 #include <errno.h>
38 39 #include <dirent.h>
39 40 #include <signal.h>
40 41 #include <limits.h>
41 42 #include <libgen.h>
42 43 #include <sys/types.h>
43 44 #include <sys/stat.h>
44 -#include <sys/systeminfo.h>
45 45 #include <sys/sysmacros.h>
46 46
47 47 #include "libproc.h"
48 48 #include "Pcontrol.h"
49 49 #include "Putil.h"
50 50 #include "Psymtab_machelf.h"
51 51
52 52 static file_info_t *build_map_symtab(struct ps_prochandle *, map_info_t *);
53 53 static map_info_t *exec_map(struct ps_prochandle *);
54 54 static map_info_t *object_to_map(struct ps_prochandle *, Lmid_t, const char *);
55 55 static map_info_t *object_name_to_map(struct ps_prochandle *,
56 56 Lmid_t, const char *);
57 57 static GElf_Sym *sym_by_name(sym_tbl_t *, const char *, GElf_Sym *, uint_t *);
58 58 static int read_ehdr32(struct ps_prochandle *, Elf32_Ehdr *, uint_t *,
59 59 uintptr_t);
60 60 #ifdef _LP64
61 61 static int read_ehdr64(struct ps_prochandle *, Elf64_Ehdr *, uint_t *,
62 62 uintptr_t);
63 63 #endif
64 64
65 65 #define DATA_TYPES \
66 66 ((1 << STT_OBJECT) | (1 << STT_FUNC) | \
67 67 (1 << STT_COMMON) | (1 << STT_TLS))
68 68 #define IS_DATA_TYPE(tp) (((1 << (tp)) & DATA_TYPES) != 0)
69 69
70 70 #define MA_RWX (MA_READ | MA_WRITE | MA_EXEC)
71 71
72 72 typedef enum {
73 73 PRO_NATURAL,
74 74 PRO_BYADDR,
75 75 PRO_BYNAME
76 76 } pr_order_t;
77 77
78 78 static int
79 79 addr_cmp(const void *aa, const void *bb)
80 80 {
81 81 uintptr_t a = *((uintptr_t *)aa);
82 82 uintptr_t b = *((uintptr_t *)bb);
83 83
84 84 if (a > b)
85 85 return (1);
86 86 if (a < b)
87 87 return (-1);
88 88 return (0);
89 89 }
90 90
91 91 /*
92 92 * This function creates a list of addresses for a load object's sections.
93 93 * The list is in ascending address order and alternates start address
94 94 * then end address for each section we're interested in. The function
95 95 * returns a pointer to the list, which must be freed by the caller.
96 96 */
97 97 static uintptr_t *
98 98 get_saddrs(struct ps_prochandle *P, uintptr_t ehdr_start, uint_t *n)
99 99 {
100 100 uintptr_t a, addr, *addrs, last = 0;
101 101 uint_t i, naddrs = 0, unordered = 0;
102 102
103 103 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
104 104 Elf32_Ehdr ehdr;
105 105 Elf32_Phdr phdr;
106 106 uint_t phnum;
107 107
108 108 if (read_ehdr32(P, &ehdr, &phnum, ehdr_start) != 0)
109 109 return (NULL);
110 110
111 111 addrs = malloc(sizeof (uintptr_t) * phnum * 2);
112 112 a = ehdr_start + ehdr.e_phoff;
113 113 for (i = 0; i < phnum; i++, a += ehdr.e_phentsize) {
114 114 if (Pread(P, &phdr, sizeof (phdr), a) !=
115 115 sizeof (phdr)) {
116 116 free(addrs);
117 117 return (NULL);
118 118 }
119 119 if (phdr.p_type != PT_LOAD || phdr.p_memsz == 0)
120 120 continue;
121 121
122 122 addr = phdr.p_vaddr;
123 123 if (ehdr.e_type == ET_DYN)
124 124 addr += ehdr_start;
125 125 if (last > addr)
126 126 unordered = 1;
127 127 addrs[naddrs++] = addr;
128 128 addrs[naddrs++] = last = addr + phdr.p_memsz - 1;
129 129 }
130 130 #ifdef _LP64
131 131 } else {
132 132 Elf64_Ehdr ehdr;
133 133 Elf64_Phdr phdr;
134 134 uint_t phnum;
135 135
136 136 if (read_ehdr64(P, &ehdr, &phnum, ehdr_start) != 0)
137 137 return (NULL);
138 138
139 139 addrs = malloc(sizeof (uintptr_t) * phnum * 2);
140 140 a = ehdr_start + ehdr.e_phoff;
141 141 for (i = 0; i < phnum; i++, a += ehdr.e_phentsize) {
142 142 if (Pread(P, &phdr, sizeof (phdr), a) !=
143 143 sizeof (phdr)) {
144 144 free(addrs);
145 145 return (NULL);
146 146 }
147 147 if (phdr.p_type != PT_LOAD || phdr.p_memsz == 0)
148 148 continue;
149 149
150 150 addr = phdr.p_vaddr;
151 151 if (ehdr.e_type == ET_DYN)
152 152 addr += ehdr_start;
153 153 if (last > addr)
154 154 unordered = 1;
155 155 addrs[naddrs++] = addr;
156 156 addrs[naddrs++] = last = addr + phdr.p_memsz - 1;
157 157 }
158 158 #endif
159 159 }
160 160
161 161 if (unordered)
162 162 qsort(addrs, naddrs, sizeof (uintptr_t), addr_cmp);
163 163
164 164 *n = naddrs;
165 165 return (addrs);
166 166 }
167 167
168 168 /*
169 169 * Allocation function for a new file_info_t
170 170 */
171 171 file_info_t *
172 172 file_info_new(struct ps_prochandle *P, map_info_t *mptr)
173 173 {
174 174 file_info_t *fptr;
175 175 map_info_t *mp;
176 176 uintptr_t mstart, mend, sstart, send;
177 177 uint_t i;
178 178
179 179 if ((fptr = calloc(1, sizeof (file_info_t))) == NULL)
180 180 return (NULL);
181 181
182 182 list_link(fptr, &P->file_head);
183 183 (void) strcpy(fptr->file_pname, mptr->map_pmap.pr_mapname);
184 184 mptr->map_file = fptr;
185 185 fptr->file_ref = 1;
186 186 fptr->file_fd = -1;
187 187 P->num_files++;
188 188
189 189 /*
190 190 * To figure out which map_info_t instances correspond to the mappings
191 191 * for this load object we try to obtain the start and end address
192 192 * for each section of our in-memory ELF image. If successful, we
193 193 * walk down the list of addresses and the list of map_info_t
194 194 * instances in lock step to correctly find the mappings that
195 195 * correspond to this load object.
196 196 */
197 197 if ((fptr->file_saddrs = get_saddrs(P, mptr->map_pmap.pr_vaddr,
198 198 &fptr->file_nsaddrs)) == NULL)
199 199 return (fptr);
200 200
201 201 mp = P->mappings;
202 202 i = 0;
203 203 while (mp < P->mappings + P->map_count && i < fptr->file_nsaddrs) {
204 204
205 205 /* Calculate the start and end of the mapping and section */
206 206 mstart = mp->map_pmap.pr_vaddr;
207 207 mend = mp->map_pmap.pr_vaddr + mp->map_pmap.pr_size;
208 208 sstart = fptr->file_saddrs[i];
209 209 send = fptr->file_saddrs[i + 1];
210 210
211 211 if (mend <= sstart) {
212 212 /* This mapping is below the current section */
213 213 mp++;
214 214 } else if (mstart >= send) {
215 215 /* This mapping is above the current section */
216 216 i += 2;
217 217 } else {
218 218 /* This mapping overlaps the current section */
219 219 if (mp->map_file == NULL) {
220 220 dprintf("file_info_new: associating "
221 221 "segment at %p\n",
222 222 (void *)mp->map_pmap.pr_vaddr);
223 223 mp->map_file = fptr;
224 224 fptr->file_ref++;
225 225 } else {
226 226 dprintf("file_info_new: segment at %p "
227 227 "already associated with %s\n",
228 228 (void *)mp->map_pmap.pr_vaddr,
229 229 (mp == mptr ? "this file" :
230 230 mp->map_file->file_pname));
231 231 }
232 232 mp++;
233 233 }
234 234 }
235 235
236 236 return (fptr);
237 237 }
238 238
239 239 /*
240 240 * Deallocation function for a file_info_t
241 241 */
242 242 static void
243 243 file_info_free(struct ps_prochandle *P, file_info_t *fptr)
244 244 {
245 245 if (--fptr->file_ref == 0) {
246 246 list_unlink(fptr);
247 247 if (fptr->file_symtab.sym_elf) {
248 248 (void) elf_end(fptr->file_symtab.sym_elf);
249 249 free(fptr->file_symtab.sym_elfmem);
250 250 }
251 251 if (fptr->file_symtab.sym_byname)
252 252 free(fptr->file_symtab.sym_byname);
253 253 if (fptr->file_symtab.sym_byaddr)
254 254 free(fptr->file_symtab.sym_byaddr);
255 255
256 256 if (fptr->file_dynsym.sym_elf) {
257 257 (void) elf_end(fptr->file_dynsym.sym_elf);
258 258 free(fptr->file_dynsym.sym_elfmem);
259 259 }
260 260 if (fptr->file_dynsym.sym_byname)
261 261 free(fptr->file_dynsym.sym_byname);
262 262 if (fptr->file_dynsym.sym_byaddr)
263 263 free(fptr->file_dynsym.sym_byaddr);
264 264
265 265 if (fptr->file_lo)
266 266 free(fptr->file_lo);
267 267 if (fptr->file_lname)
268 268 free(fptr->file_lname);
269 269 if (fptr->file_rname)
270 270 free(fptr->file_rname);
271 271 if (fptr->file_elf)
272 272 (void) elf_end(fptr->file_elf);
273 273 if (fptr->file_elfmem != NULL)
274 274 free(fptr->file_elfmem);
275 275 if (fptr->file_fd >= 0)
276 276 (void) close(fptr->file_fd);
277 277 if (fptr->file_ctfp) {
278 278 ctf_close(fptr->file_ctfp);
279 279 free(fptr->file_ctf_buf);
280 280 }
281 281 if (fptr->file_saddrs)
282 282 free(fptr->file_saddrs);
283 283 free(fptr);
284 284 P->num_files--;
285 285 }
286 286 }
287 287
288 288 /*
289 289 * Deallocation function for a map_info_t
290 290 */
291 291 static void
292 292 map_info_free(struct ps_prochandle *P, map_info_t *mptr)
293 293 {
294 294 file_info_t *fptr;
295 295
296 296 if ((fptr = mptr->map_file) != NULL) {
297 297 if (fptr->file_map == mptr)
298 298 fptr->file_map = NULL;
299 299 file_info_free(P, fptr);
300 300 }
301 301 if (P->execname && mptr == P->map_exec) {
302 302 free(P->execname);
303 303 P->execname = NULL;
304 304 }
305 305 if (P->auxv && (mptr == P->map_exec || mptr == P->map_ldso)) {
306 306 free(P->auxv);
307 307 P->auxv = NULL;
308 308 P->nauxv = 0;
309 309 }
310 310 if (mptr == P->map_exec)
311 311 P->map_exec = NULL;
312 312 if (mptr == P->map_ldso)
313 313 P->map_ldso = NULL;
314 314 }
315 315
316 316 /*
317 317 * Call-back function for librtld_db to iterate through all of its shared
318 318 * libraries. We use this to get the load object names for the mappings.
319 319 */
320 320 static int
321 321 map_iter(const rd_loadobj_t *lop, void *cd)
322 322 {
323 323 char buf[PATH_MAX];
324 324 struct ps_prochandle *P = cd;
325 325 map_info_t *mptr;
326 326 file_info_t *fptr;
327 327
328 328 dprintf("encountered rd object at %p\n", (void *)lop->rl_base);
329 329
330 330 if ((mptr = Paddr2mptr(P, lop->rl_base)) == NULL) {
331 331 dprintf("map_iter: base address doesn't match any mapping\n");
332 332 return (1); /* Base address does not match any mapping */
333 333 }
334 334
335 335 if ((fptr = mptr->map_file) == NULL &&
336 336 (fptr = file_info_new(P, mptr)) == NULL) {
337 337 dprintf("map_iter: failed to allocate a new file_info_t\n");
338 338 return (1); /* Failed to allocate a new file_info_t */
339 339 }
340 340
341 341 if ((fptr->file_lo == NULL) &&
342 342 (fptr->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) {
343 343 dprintf("map_iter: failed to allocate rd_loadobj_t\n");
344 344 file_info_free(P, fptr);
345 345 return (1); /* Failed to allocate rd_loadobj_t */
346 346 }
347 347
348 348 fptr->file_map = mptr;
349 349 *fptr->file_lo = *lop;
350 350
351 351 fptr->file_lo->rl_plt_base = fptr->file_plt_base;
352 352 fptr->file_lo->rl_plt_size = fptr->file_plt_size;
353 353
354 354 if (fptr->file_lname) {
355 355 free(fptr->file_lname);
356 356 fptr->file_lname = NULL;
357 357 fptr->file_lbase = NULL;
358 358 }
359 359 if (fptr->file_rname) {
360 360 free(fptr->file_rname);
361 361 fptr->file_rname = NULL;
362 362 fptr->file_rbase = NULL;
363 363 }
364 364
365 365 if (Pread_string(P, buf, sizeof (buf), lop->rl_nameaddr) > 0) {
366 366 if ((fptr->file_lname = strdup(buf)) != NULL)
367 367 fptr->file_lbase = basename(fptr->file_lname);
368 368 } else {
369 369 dprintf("map_iter: failed to read string at %p\n",
370 370 (void *)lop->rl_nameaddr);
371 371 }
372 372
373 373 if ((Pfindmap(P, mptr, buf, sizeof (buf)) != NULL) &&
374 374 ((fptr->file_rname = strdup(buf)) != NULL))
375 375 fptr->file_rbase = basename(fptr->file_rname);
376 376
377 377 dprintf("loaded rd object %s lmid %lx\n",
378 378 fptr->file_lname ? buf : "<NULL>", lop->rl_lmident);
379 379 return (1);
380 380 }
381 381
382 382 static void
383 383 map_set(struct ps_prochandle *P, map_info_t *mptr, const char *lname)
384 384 {
385 385 file_info_t *fptr;
386 386 char buf[PATH_MAX];
387 387
388 388 if ((fptr = mptr->map_file) == NULL &&
389 389 (fptr = file_info_new(P, mptr)) == NULL)
390 390 return; /* Failed to allocate a new file_info_t */
391 391
392 392 fptr->file_map = mptr;
393 393
394 394 if ((fptr->file_lo == NULL) &&
395 395 (fptr->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) {
396 396 file_info_free(P, fptr);
397 397 return; /* Failed to allocate rd_loadobj_t */
398 398 }
399 399
400 400 (void) memset(fptr->file_lo, 0, sizeof (rd_loadobj_t));
401 401 fptr->file_lo->rl_base = mptr->map_pmap.pr_vaddr;
402 402 fptr->file_lo->rl_bend =
403 403 mptr->map_pmap.pr_vaddr + mptr->map_pmap.pr_size;
404 404
405 405 fptr->file_lo->rl_plt_base = fptr->file_plt_base;
406 406 fptr->file_lo->rl_plt_size = fptr->file_plt_size;
407 407
408 408 if ((fptr->file_lname == NULL) &&
409 409 (fptr->file_lname = strdup(lname)) != NULL)
410 410 fptr->file_lbase = basename(fptr->file_lname);
411 411
412 412 if ((Pfindmap(P, mptr, buf, sizeof (buf)) != NULL) &&
413 413 ((fptr->file_rname = strdup(buf)) != NULL))
414 414 fptr->file_rbase = basename(fptr->file_rname);
415 415 }
416 416
417 417 static void
418 418 load_static_maps(struct ps_prochandle *P)
419 419 {
420 420 map_info_t *mptr;
421 421
422 422 /*
423 423 * Construct the map for the a.out.
424 424 */
425 425 if ((mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_EXEC)) != NULL)
426 426 map_set(P, mptr, "a.out");
↓ open down ↓ |
372 lines elided |
↑ open up ↑ |
427 427
428 428 /*
429 429 * If the dynamic linker exists for this process,
430 430 * construct the map for it.
431 431 */
432 432 if (Pgetauxval(P, AT_BASE) != -1L &&
433 433 (mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_LDSO)) != NULL)
434 434 map_set(P, mptr, "ld.so.1");
435 435 }
436 436
437 +int
438 +Preadmaps(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp)
439 +{
440 + return (P->ops.pop_read_maps(P, Pmapp, nmapp, P->data));
441 +}
442 +
437 443 /*
438 444 * Go through all the address space mappings, validating or updating
439 445 * the information already gathered, or gathering new information.
440 446 *
441 447 * This function is only called when we suspect that the mappings have changed
442 448 * because this is the first time we're calling it or because of rtld activity.
443 449 */
444 450 void
445 451 Pupdate_maps(struct ps_prochandle *P)
446 452 {
447 - char mapfile[PATH_MAX];
448 - int mapfd;
449 - struct stat statb;
450 453 prmap_t *Pmap = NULL;
451 454 prmap_t *pmap;
452 455 ssize_t nmap;
453 456 int i;
454 457 uint_t oldmapcount;
455 458 map_info_t *newmap, *newp;
456 459 map_info_t *mptr;
457 460
458 461 if (P->info_valid || P->state == PS_UNDEAD)
459 462 return;
460 463
461 464 Preadauxvec(P);
462 465
463 - (void) snprintf(mapfile, sizeof (mapfile), "%s/%d/map",
464 - procfs_path, (int)P->pid);
465 - if ((mapfd = open(mapfile, O_RDONLY)) < 0 ||
466 - fstat(mapfd, &statb) != 0 ||
467 - statb.st_size < sizeof (prmap_t) ||
468 - (Pmap = malloc(statb.st_size)) == NULL ||
469 - (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 ||
470 - (nmap /= sizeof (prmap_t)) == 0) {
471 - if (Pmap != NULL)
472 - free(Pmap);
473 - if (mapfd >= 0)
474 - (void) close(mapfd);
475 - Preset_maps(P); /* utter failure; destroy tables */
466 + if (Preadmaps(P, &Pmap, &nmap) != 0)
476 467 return;
477 - }
478 - (void) close(mapfd);
479 468
480 469 if ((newmap = calloc(1, nmap * sizeof (map_info_t))) == NULL)
481 470 return;
482 471
483 472 /*
484 473 * We try to merge any file information we may have for existing
485 474 * mappings, to avoid having to rebuild the file info.
486 475 */
487 476 mptr = P->mappings;
488 477 pmap = Pmap;
489 478 newp = newmap;
490 479 oldmapcount = P->map_count;
491 480 for (i = 0; i < nmap; i++, pmap++, newp++) {
492 481
493 482 if (oldmapcount == 0) {
494 483 /*
495 484 * We've exhausted all the old mappings. Every new
496 485 * mapping should be added.
497 486 */
498 487 newp->map_pmap = *pmap;
499 488
500 489 } else if (pmap->pr_vaddr == mptr->map_pmap.pr_vaddr &&
501 490 pmap->pr_size == mptr->map_pmap.pr_size &&
502 491 pmap->pr_offset == mptr->map_pmap.pr_offset &&
503 492 (pmap->pr_mflags & ~(MA_BREAK | MA_STACK)) ==
504 493 (mptr->map_pmap.pr_mflags & ~(MA_BREAK | MA_STACK)) &&
505 494 pmap->pr_pagesize == mptr->map_pmap.pr_pagesize &&
506 495 pmap->pr_shmid == mptr->map_pmap.pr_shmid &&
507 496 strcmp(pmap->pr_mapname, mptr->map_pmap.pr_mapname) == 0) {
508 497
509 498 /*
510 499 * This mapping matches exactly. Copy over the old
511 500 * mapping, taking care to get the latest flags.
512 501 * Make sure the associated file_info_t is updated
513 502 * appropriately.
514 503 */
515 504 *newp = *mptr;
516 505 if (P->map_exec == mptr)
517 506 P->map_exec = newp;
518 507 if (P->map_ldso == mptr)
519 508 P->map_ldso = newp;
520 509 newp->map_pmap.pr_mflags = pmap->pr_mflags;
521 510 if (mptr->map_file != NULL &&
522 511 mptr->map_file->file_map == mptr)
523 512 mptr->map_file->file_map = newp;
524 513 oldmapcount--;
525 514 mptr++;
526 515
527 516 } else if (pmap->pr_vaddr + pmap->pr_size >
528 517 mptr->map_pmap.pr_vaddr) {
529 518
530 519 /*
531 520 * The old mapping doesn't exist any more, remove it
532 521 * from the list.
533 522 */
534 523 map_info_free(P, mptr);
535 524 oldmapcount--;
536 525 i--;
537 526 newp--;
538 527 pmap--;
539 528 mptr++;
540 529
541 530 } else {
542 531
543 532 /*
544 533 * This is a new mapping, add it directly.
545 534 */
546 535 newp->map_pmap = *pmap;
547 536 }
548 537 }
549 538
550 539 /*
551 540 * Free any old maps
552 541 */
553 542 while (oldmapcount) {
554 543 map_info_free(P, mptr);
555 544 oldmapcount--;
556 545 mptr++;
557 546 }
558 547
559 548 free(Pmap);
560 549 if (P->mappings != NULL)
561 550 free(P->mappings);
562 551 P->mappings = newmap;
563 552 P->map_count = P->map_alloc = nmap;
564 553 P->info_valid = 1;
565 554
566 555 /*
567 556 * Consult librtld_db to get the load object
568 557 * names for all of the shared libraries.
569 558 */
570 559 if (P->rap != NULL)
571 560 (void) rd_loadobj_iter(P->rap, map_iter, P);
572 561 }
573 562
574 563 /*
575 564 * Update all of the mappings and rtld_db as if by Pupdate_maps(), and then
576 565 * forcibly cache all of the symbol tables associated with all object files.
577 566 */
578 567 void
579 568 Pupdate_syms(struct ps_prochandle *P)
580 569 {
581 570 file_info_t *fptr;
582 571 int i;
583 572
584 573 Pupdate_maps(P);
585 574
586 575 for (i = 0, fptr = list_next(&P->file_head); i < P->num_files;
587 576 i++, fptr = list_next(fptr)) {
588 577 Pbuild_file_symtab(P, fptr);
589 578 (void) Pbuild_file_ctf(P, fptr);
590 579 }
591 580 }
592 581
593 582 /*
594 583 * Return the librtld_db agent handle for the victim process.
595 584 * The handle will become invalid at the next successful exec() and the
596 585 * client (caller of proc_rd_agent()) must not use it beyond that point.
597 586 * If the process is already dead, we've already tried our best to
598 587 * create the agent during core file initialization.
599 588 */
600 589 rd_agent_t *
601 590 Prd_agent(struct ps_prochandle *P)
602 591 {
603 592 if (P->rap == NULL && P->state != PS_DEAD && P->state != PS_IDLE) {
604 593 Pupdate_maps(P);
605 594 if (P->num_files == 0)
606 595 load_static_maps(P);
607 596 rd_log(_libproc_debug);
608 597 if ((P->rap = rd_new(P)) != NULL)
609 598 (void) rd_loadobj_iter(P->rap, map_iter, P);
610 599 }
611 600 return (P->rap);
612 601 }
613 602
614 603 /*
615 604 * Return the prmap_t structure containing 'addr', but only if it
616 605 * is in the dynamic linker's link map and is the text section.
617 606 */
618 607 const prmap_t *
619 608 Paddr_to_text_map(struct ps_prochandle *P, uintptr_t addr)
620 609 {
621 610 map_info_t *mptr;
622 611
623 612 if (!P->info_valid)
624 613 Pupdate_maps(P);
625 614
626 615 if ((mptr = Paddr2mptr(P, addr)) != NULL) {
627 616 file_info_t *fptr = build_map_symtab(P, mptr);
628 617 const prmap_t *pmp = &mptr->map_pmap;
629 618
630 619 /*
631 620 * Assume that if rl_data_base is NULL, it means that no
632 621 * data section was found for this load object, and that
633 622 * a section must be text. Otherwise, a section will be
634 623 * text unless it ends above the start of the data
635 624 * section.
636 625 */
637 626 if (fptr != NULL && fptr->file_lo != NULL &&
638 627 (fptr->file_lo->rl_data_base == NULL ||
639 628 pmp->pr_vaddr + pmp->pr_size <=
640 629 fptr->file_lo->rl_data_base))
641 630 return (pmp);
642 631 }
643 632
644 633 return (NULL);
645 634 }
646 635
647 636 /*
648 637 * Return the prmap_t structure containing 'addr' (no restrictions on
649 638 * the type of mapping).
650 639 */
651 640 const prmap_t *
652 641 Paddr_to_map(struct ps_prochandle *P, uintptr_t addr)
653 642 {
654 643 map_info_t *mptr;
655 644
656 645 if (!P->info_valid)
657 646 Pupdate_maps(P);
658 647
659 648 if ((mptr = Paddr2mptr(P, addr)) != NULL)
660 649 return (&mptr->map_pmap);
661 650
662 651 return (NULL);
663 652 }
664 653
665 654 /*
666 655 * Convert a full or partial load object name to the prmap_t for its
667 656 * corresponding primary text mapping.
668 657 */
669 658 const prmap_t *
670 659 Plmid_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name)
671 660 {
672 661 map_info_t *mptr;
673 662
674 663 if (name == PR_OBJ_EVERY)
675 664 return (NULL); /* A reasonable mistake */
676 665
677 666 if ((mptr = object_name_to_map(P, lmid, name)) != NULL)
678 667 return (&mptr->map_pmap);
679 668
680 669 return (NULL);
681 670 }
682 671
683 672 const prmap_t *
684 673 Pname_to_map(struct ps_prochandle *P, const char *name)
685 674 {
686 675 return (Plmid_to_map(P, PR_LMID_EVERY, name));
687 676 }
688 677
689 678 const rd_loadobj_t *
690 679 Paddr_to_loadobj(struct ps_prochandle *P, uintptr_t addr)
691 680 {
692 681 map_info_t *mptr;
693 682
694 683 if (!P->info_valid)
695 684 Pupdate_maps(P);
696 685
697 686 if ((mptr = Paddr2mptr(P, addr)) == NULL)
698 687 return (NULL);
699 688
700 689 /*
701 690 * By building the symbol table, we implicitly bring the PLT
702 691 * information up to date in the load object.
703 692 */
704 693 (void) build_map_symtab(P, mptr);
705 694
706 695 return (mptr->map_file->file_lo);
707 696 }
708 697
709 698 const rd_loadobj_t *
710 699 Plmid_to_loadobj(struct ps_prochandle *P, Lmid_t lmid, const char *name)
711 700 {
712 701 map_info_t *mptr;
713 702
714 703 if (name == PR_OBJ_EVERY)
715 704 return (NULL);
716 705
717 706 if ((mptr = object_name_to_map(P, lmid, name)) == NULL)
718 707 return (NULL);
719 708
720 709 /*
721 710 * By building the symbol table, we implicitly bring the PLT
722 711 * information up to date in the load object.
723 712 */
724 713 (void) build_map_symtab(P, mptr);
725 714
726 715 return (mptr->map_file->file_lo);
727 716 }
728 717
729 718 const rd_loadobj_t *
730 719 Pname_to_loadobj(struct ps_prochandle *P, const char *name)
731 720 {
732 721 return (Plmid_to_loadobj(P, PR_LMID_EVERY, name));
733 722 }
734 723
735 724 ctf_file_t *
736 725 Pbuild_file_ctf(struct ps_prochandle *P, file_info_t *fptr)
737 726 {
738 727 ctf_sect_t ctdata, symtab, strtab;
739 728 sym_tbl_t *symp;
740 729 int err;
741 730
742 731 if (fptr->file_ctfp != NULL)
743 732 return (fptr->file_ctfp);
744 733
745 734 Pbuild_file_symtab(P, fptr);
746 735
747 736 if (fptr->file_ctf_size == 0)
748 737 return (NULL);
749 738
750 739 symp = fptr->file_ctf_dyn ? &fptr->file_dynsym : &fptr->file_symtab;
751 740 if (symp->sym_data_pri == NULL)
752 741 return (NULL);
753 742
754 743 /*
755 744 * The buffer may alread be allocated if this is a core file that
756 745 * contained CTF data for this file.
757 746 */
758 747 if (fptr->file_ctf_buf == NULL) {
759 748 fptr->file_ctf_buf = malloc(fptr->file_ctf_size);
760 749 if (fptr->file_ctf_buf == NULL) {
761 750 dprintf("failed to allocate ctf buffer\n");
762 751 return (NULL);
763 752 }
764 753
765 754 if (pread(fptr->file_fd, fptr->file_ctf_buf,
766 755 fptr->file_ctf_size, fptr->file_ctf_off) !=
767 756 fptr->file_ctf_size) {
768 757 free(fptr->file_ctf_buf);
769 758 fptr->file_ctf_buf = NULL;
770 759 dprintf("failed to read ctf data\n");
771 760 return (NULL);
772 761 }
773 762 }
774 763
775 764 ctdata.cts_name = ".SUNW_ctf";
776 765 ctdata.cts_type = SHT_PROGBITS;
777 766 ctdata.cts_flags = 0;
778 767 ctdata.cts_data = fptr->file_ctf_buf;
779 768 ctdata.cts_size = fptr->file_ctf_size;
780 769 ctdata.cts_entsize = 1;
781 770 ctdata.cts_offset = 0;
782 771
783 772 symtab.cts_name = fptr->file_ctf_dyn ? ".dynsym" : ".symtab";
784 773 symtab.cts_type = symp->sym_hdr_pri.sh_type;
785 774 symtab.cts_flags = symp->sym_hdr_pri.sh_flags;
786 775 symtab.cts_data = symp->sym_data_pri->d_buf;
787 776 symtab.cts_size = symp->sym_hdr_pri.sh_size;
788 777 symtab.cts_entsize = symp->sym_hdr_pri.sh_entsize;
789 778 symtab.cts_offset = symp->sym_hdr_pri.sh_offset;
790 779
791 780 strtab.cts_name = fptr->file_ctf_dyn ? ".dynstr" : ".strtab";
792 781 strtab.cts_type = symp->sym_strhdr.sh_type;
793 782 strtab.cts_flags = symp->sym_strhdr.sh_flags;
794 783 strtab.cts_data = symp->sym_strs;
795 784 strtab.cts_size = symp->sym_strhdr.sh_size;
796 785 strtab.cts_entsize = symp->sym_strhdr.sh_entsize;
797 786 strtab.cts_offset = symp->sym_strhdr.sh_offset;
798 787
799 788 fptr->file_ctfp = ctf_bufopen(&ctdata, &symtab, &strtab, &err);
800 789 if (fptr->file_ctfp == NULL) {
801 790 dprintf("ctf_bufopen() failed, error code %d\n", err);
802 791 free(fptr->file_ctf_buf);
803 792 fptr->file_ctf_buf = NULL;
804 793 return (NULL);
805 794 }
806 795
807 796 dprintf("loaded %lu bytes of CTF data for %s\n",
808 797 (ulong_t)fptr->file_ctf_size, fptr->file_pname);
809 798
810 799 return (fptr->file_ctfp);
811 800 }
812 801
813 802 ctf_file_t *
814 803 Paddr_to_ctf(struct ps_prochandle *P, uintptr_t addr)
815 804 {
816 805 map_info_t *mptr;
817 806 file_info_t *fptr;
818 807
819 808 if (!P->info_valid)
820 809 Pupdate_maps(P);
821 810
822 811 if ((mptr = Paddr2mptr(P, addr)) == NULL ||
823 812 (fptr = mptr->map_file) == NULL)
824 813 return (NULL);
825 814
826 815 return (Pbuild_file_ctf(P, fptr));
827 816 }
828 817
829 818 ctf_file_t *
830 819 Plmid_to_ctf(struct ps_prochandle *P, Lmid_t lmid, const char *name)
831 820 {
832 821 map_info_t *mptr;
833 822 file_info_t *fptr;
834 823
835 824 if (name == PR_OBJ_EVERY)
836 825 return (NULL);
837 826
838 827 if ((mptr = object_name_to_map(P, lmid, name)) == NULL ||
839 828 (fptr = mptr->map_file) == NULL)
840 829 return (NULL);
↓ open down ↓ |
352 lines elided |
↑ open up ↑ |
841 830
842 831 return (Pbuild_file_ctf(P, fptr));
843 832 }
844 833
845 834 ctf_file_t *
846 835 Pname_to_ctf(struct ps_prochandle *P, const char *name)
847 836 {
848 837 return (Plmid_to_ctf(P, PR_LMID_EVERY, name));
849 838 }
850 839
851 -/*
852 - * If we're not a core file, re-read the /proc/<pid>/auxv file and store
853 - * its contents in P->auxv. In the case of a core file, we either
854 - * initialized P->auxv in Pcore() from the NT_AUXV, or we don't have an
855 - * auxv because the note was missing.
856 - */
857 840 void
858 841 Preadauxvec(struct ps_prochandle *P)
859 842 {
860 - char auxfile[64];
861 - struct stat statb;
862 - ssize_t naux;
863 - int fd;
864 -
865 - if (P->state == PS_DEAD)
866 - return; /* Already read during Pgrab_core() */
867 - if (P->state == PS_IDLE)
868 - return; /* No aux vec for Pgrab_file() */
869 -
870 843 if (P->auxv != NULL) {
871 844 free(P->auxv);
872 845 P->auxv = NULL;
873 846 P->nauxv = 0;
874 847 }
875 848
876 - (void) snprintf(auxfile, sizeof (auxfile), "%s/%d/auxv",
877 - procfs_path, (int)P->pid);
878 - if ((fd = open(auxfile, O_RDONLY)) < 0)
879 - return;
880 -
881 - if (fstat(fd, &statb) == 0 &&
882 - statb.st_size >= sizeof (auxv_t) &&
883 - (P->auxv = malloc(statb.st_size + sizeof (auxv_t))) != NULL) {
884 - if ((naux = read(fd, P->auxv, statb.st_size)) < 0 ||
885 - (naux /= sizeof (auxv_t)) < 1) {
886 - free(P->auxv);
887 - P->auxv = NULL;
888 - } else {
889 - P->auxv[naux].a_type = AT_NULL;
890 - P->auxv[naux].a_un.a_val = 0L;
891 - P->nauxv = (int)naux;
892 - }
893 - }
894 -
895 - (void) close(fd);
849 + P->ops.pop_read_aux(P, &P->auxv, &P->nauxv, P->data);
896 850 }
897 851
898 852 /*
899 853 * Return a requested element from the process's aux vector.
900 854 * Return -1 on failure (this is adequate for our purposes).
901 855 */
902 856 long
903 857 Pgetauxval(struct ps_prochandle *P, int type)
904 858 {
905 859 auxv_t *auxv;
906 860
907 861 if (P->auxv == NULL)
908 862 Preadauxvec(P);
909 863
910 864 if (P->auxv == NULL)
911 865 return (-1);
912 866
913 867 for (auxv = P->auxv; auxv->a_type != AT_NULL; auxv++) {
914 868 if (auxv->a_type == type)
915 869 return (auxv->a_un.a_val);
916 870 }
917 871
918 872 return (-1);
919 873 }
920 874
921 875 /*
922 876 * Return a pointer to our internal copy of the process's aux vector.
923 877 * The caller should not hold on to this pointer across any libproc calls.
924 878 */
925 879 const auxv_t *
926 880 Pgetauxvec(struct ps_prochandle *P)
927 881 {
928 882 static const auxv_t empty = { AT_NULL, 0L };
929 883
930 884 if (P->auxv == NULL)
931 885 Preadauxvec(P);
932 886
933 887 if (P->auxv == NULL)
934 888 return (&empty);
935 889
936 890 return (P->auxv);
937 891 }
938 892
939 893 /*
940 894 * Return 1 if the given mapping corresponds to the given file_info_t's
941 895 * load object; return 0 otherwise.
942 896 */
943 897 static int
944 898 is_mapping_in_file(struct ps_prochandle *P, map_info_t *mptr, file_info_t *fptr)
945 899 {
946 900 prmap_t *pmap = &mptr->map_pmap;
947 901 rd_loadobj_t *lop = fptr->file_lo;
948 902 uint_t i;
949 903 uintptr_t mstart, mend, sstart, send;
950 904
951 905 /*
952 906 * We can get for free the start address of the text and data
953 907 * sections of the load object. Start by seeing if the mapping
954 908 * encloses either of these.
955 909 */
956 910 if ((pmap->pr_vaddr <= lop->rl_base &&
957 911 lop->rl_base < pmap->pr_vaddr + pmap->pr_size) ||
958 912 (pmap->pr_vaddr <= lop->rl_data_base &&
959 913 lop->rl_data_base < pmap->pr_vaddr + pmap->pr_size))
960 914 return (1);
961 915
962 916 /*
963 917 * It's still possible that this mapping correponds to the load
964 918 * object. Consider the example of a mapping whose start and end
965 919 * addresses correspond to those of the load object's text section.
966 920 * If the mapping splits, e.g. as a result of a segment demotion,
967 921 * then although both mappings are still backed by the same section,
968 922 * only one will be seen to enclose that section's start address.
969 923 * Thus, to be rigorous, we ask not whether this mapping encloses
970 924 * the start of a section, but whether there exists a section that
971 925 * overlaps this mapping.
972 926 *
973 927 * If we don't already have the section addresses, and we successfully
974 928 * get them, then we cache them in case we come here again.
975 929 */
976 930 if (fptr->file_saddrs == NULL &&
977 931 (fptr->file_saddrs = get_saddrs(P,
978 932 fptr->file_map->map_pmap.pr_vaddr, &fptr->file_nsaddrs)) == NULL)
979 933 return (0);
980 934
981 935 mstart = mptr->map_pmap.pr_vaddr;
982 936 mend = mptr->map_pmap.pr_vaddr + mptr->map_pmap.pr_size;
983 937 for (i = 0; i < fptr->file_nsaddrs; i += 2) {
984 938 /* Does this section overlap the mapping? */
985 939 sstart = fptr->file_saddrs[i];
986 940 send = fptr->file_saddrs[i + 1];
987 941 if (!(mend <= sstart || mstart >= send))
988 942 return (1);
989 943 }
990 944
991 945 return (0);
992 946 }
993 947
994 948 /*
995 949 * Find or build the symbol table for the given mapping.
996 950 */
997 951 static file_info_t *
998 952 build_map_symtab(struct ps_prochandle *P, map_info_t *mptr)
999 953 {
1000 954 prmap_t *pmap = &mptr->map_pmap;
1001 955 file_info_t *fptr;
1002 956 uint_t i;
1003 957
1004 958 if ((fptr = mptr->map_file) != NULL) {
1005 959 Pbuild_file_symtab(P, fptr);
1006 960 return (fptr);
1007 961 }
1008 962
1009 963 if (pmap->pr_mapname[0] == '\0')
1010 964 return (NULL);
1011 965
1012 966 /*
1013 967 * Attempt to find a matching file.
1014 968 * (A file can be mapped at several different addresses.)
1015 969 */
1016 970 for (i = 0, fptr = list_next(&P->file_head); i < P->num_files;
1017 971 i++, fptr = list_next(fptr)) {
1018 972 if (strcmp(fptr->file_pname, pmap->pr_mapname) == 0 &&
1019 973 fptr->file_lo && is_mapping_in_file(P, mptr, fptr)) {
1020 974 mptr->map_file = fptr;
1021 975 fptr->file_ref++;
1022 976 Pbuild_file_symtab(P, fptr);
1023 977 return (fptr);
1024 978 }
1025 979 }
1026 980
1027 981 /*
1028 982 * If we need to create a new file_info structure, iterate
1029 983 * through the load objects in order to attempt to connect
1030 984 * this new file with its primary text mapping. We again
1031 985 * need to handle ld.so as a special case because we need
1032 986 * to be able to bootstrap librtld_db.
1033 987 */
1034 988 if ((fptr = file_info_new(P, mptr)) == NULL)
1035 989 return (NULL);
1036 990
1037 991 if (P->map_ldso != mptr) {
1038 992 if (P->rap != NULL)
1039 993 (void) rd_loadobj_iter(P->rap, map_iter, P);
1040 994 else
1041 995 (void) Prd_agent(P);
1042 996 } else {
1043 997 fptr->file_map = mptr;
1044 998 }
1045 999
1046 1000 /*
1047 1001 * If librtld_db wasn't able to help us connect the file to a primary
1048 1002 * text mapping, set file_map to the current mapping because we require
1049 1003 * fptr->file_map to be set in Pbuild_file_symtab. librtld_db may be
1050 1004 * unaware of what's going on in the rare case that a legitimate ELF
1051 1005 * file has been mmap(2)ed into the process address space *without*
1052 1006 * the use of dlopen(3x).
1053 1007 */
1054 1008 if (fptr->file_map == NULL)
1055 1009 fptr->file_map = mptr;
1056 1010
1057 1011 Pbuild_file_symtab(P, fptr);
1058 1012
1059 1013 return (fptr);
1060 1014 }
1061 1015
1062 1016 static int
1063 1017 read_ehdr32(struct ps_prochandle *P, Elf32_Ehdr *ehdr, uint_t *phnum,
1064 1018 uintptr_t addr)
1065 1019 {
1066 1020 if (Pread(P, ehdr, sizeof (*ehdr), addr) != sizeof (*ehdr))
1067 1021 return (-1);
1068 1022
1069 1023 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1070 1024 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1071 1025 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1072 1026 ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
1073 1027 ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
1074 1028 #ifdef _BIG_ENDIAN
1075 1029 ehdr->e_ident[EI_DATA] != ELFDATA2MSB ||
1076 1030 #else
1077 1031 ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
1078 1032 #endif
1079 1033 ehdr->e_ident[EI_VERSION] != EV_CURRENT)
1080 1034 return (-1);
1081 1035
1082 1036 if ((*phnum = ehdr->e_phnum) == PN_XNUM) {
1083 1037 Elf32_Shdr shdr0;
1084 1038
1085 1039 if (ehdr->e_shoff == 0 || ehdr->e_shentsize < sizeof (shdr0) ||
1086 1040 Pread(P, &shdr0, sizeof (shdr0), addr + ehdr->e_shoff) !=
1087 1041 sizeof (shdr0))
1088 1042 return (-1);
1089 1043
1090 1044 if (shdr0.sh_info != 0)
1091 1045 *phnum = shdr0.sh_info;
1092 1046 }
1093 1047
1094 1048 return (0);
1095 1049 }
1096 1050
1097 1051 static int
1098 1052 read_dynamic_phdr32(struct ps_prochandle *P, const Elf32_Ehdr *ehdr,
1099 1053 uint_t phnum, Elf32_Phdr *phdr, uintptr_t addr)
1100 1054 {
1101 1055 uint_t i;
1102 1056
1103 1057 for (i = 0; i < phnum; i++) {
1104 1058 uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize;
1105 1059 if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr))
1106 1060 return (-1);
1107 1061
1108 1062 if (phdr->p_type == PT_DYNAMIC)
1109 1063 return (0);
1110 1064 }
1111 1065
1112 1066 return (-1);
1113 1067 }
1114 1068
1115 1069 #ifdef _LP64
1116 1070 static int
1117 1071 read_ehdr64(struct ps_prochandle *P, Elf64_Ehdr *ehdr, uint_t *phnum,
1118 1072 uintptr_t addr)
1119 1073 {
1120 1074 if (Pread(P, ehdr, sizeof (Elf64_Ehdr), addr) != sizeof (Elf64_Ehdr))
1121 1075 return (-1);
1122 1076
1123 1077 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1124 1078 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1125 1079 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1126 1080 ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
1127 1081 ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
1128 1082 #ifdef _BIG_ENDIAN
1129 1083 ehdr->e_ident[EI_DATA] != ELFDATA2MSB ||
1130 1084 #else
1131 1085 ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
1132 1086 #endif
1133 1087 ehdr->e_ident[EI_VERSION] != EV_CURRENT)
1134 1088 return (-1);
1135 1089
1136 1090 if ((*phnum = ehdr->e_phnum) == PN_XNUM) {
1137 1091 Elf64_Shdr shdr0;
1138 1092
1139 1093 if (ehdr->e_shoff == 0 || ehdr->e_shentsize < sizeof (shdr0) ||
1140 1094 Pread(P, &shdr0, sizeof (shdr0), addr + ehdr->e_shoff) !=
1141 1095 sizeof (shdr0))
1142 1096 return (-1);
1143 1097
1144 1098 if (shdr0.sh_info != 0)
1145 1099 *phnum = shdr0.sh_info;
1146 1100 }
1147 1101
1148 1102 return (0);
1149 1103 }
1150 1104
1151 1105 static int
1152 1106 read_dynamic_phdr64(struct ps_prochandle *P, const Elf64_Ehdr *ehdr,
1153 1107 uint_t phnum, Elf64_Phdr *phdr, uintptr_t addr)
1154 1108 {
1155 1109 uint_t i;
1156 1110
1157 1111 for (i = 0; i < phnum; i++) {
1158 1112 uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize;
1159 1113 if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr))
1160 1114 return (-1);
1161 1115
1162 1116 if (phdr->p_type == PT_DYNAMIC)
1163 1117 return (0);
1164 1118 }
1165 1119
1166 1120 return (-1);
1167 1121 }
1168 1122 #endif /* _LP64 */
1169 1123
1170 1124 /*
1171 1125 * The text segment for each load object contains the elf header and
1172 1126 * program headers. We can use this information to determine if the
1173 1127 * file that corresponds to the load object is the same file that
1174 1128 * was loaded into the process's address space. There can be a discrepency
1175 1129 * if a file is recompiled after the process is started or if the target
1176 1130 * represents a core file from a differently configured system -- two
1177 1131 * common examples. The DT_CHECKSUM entry in the dynamic section
1178 1132 * provides an easy method of comparison. It is important to note that
1179 1133 * the dynamic section usually lives in the data segment, but the meta
1180 1134 * data we use to find the dynamic section lives in the text segment so
1181 1135 * if either of those segments is absent we can't proceed.
1182 1136 *
1183 1137 * We're looking through the elf file for several items: the symbol tables
1184 1138 * (both dynsym and symtab), the procedure linkage table (PLT) base,
1185 1139 * size, and relocation base, and the CTF information. Most of this can
1186 1140 * be recovered from the loaded image of the file itself, the exceptions
1187 1141 * being the symtab and CTF data.
1188 1142 *
1189 1143 * First we try to open the file that we think corresponds to the load
1190 1144 * object, if the DT_CHECKSUM values match, we're all set, and can simply
1191 1145 * recover all the information we need from the file. If the values of
1192 1146 * DT_CHECKSUM don't match, or if we can't access the file for whatever
1193 1147 * reasaon, we fake up a elf file to use in its stead. If we can't read
1194 1148 * the elf data in the process's address space, we fall back to using
1195 1149 * the file even though it may give inaccurate information.
1196 1150 *
1197 1151 * The elf file that we fake up has to consist of sections for the
1198 1152 * dynsym, the PLT and the dynamic section. Note that in the case of a
1199 1153 * core file, we'll get the CTF data in the file_info_t later on from
1200 1154 * a section embedded the core file (if it's present).
1201 1155 *
1202 1156 * file_differs() conservatively looks for mismatched files, identifying
1203 1157 * a match when there is any ambiguity (since that's the legacy behavior).
1204 1158 */
1205 1159 static int
1206 1160 file_differs(struct ps_prochandle *P, Elf *elf, file_info_t *fptr)
1207 1161 {
1208 1162 Elf_Scn *scn;
1209 1163 GElf_Shdr shdr;
1210 1164 GElf_Dyn dyn;
1211 1165 Elf_Data *data;
1212 1166 uint_t i, ndyn;
1213 1167 GElf_Xword cksum;
1214 1168 uintptr_t addr;
1215 1169
1216 1170 if (fptr->file_map == NULL)
1217 1171 return (0);
1218 1172
1219 1173 if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) !=
1220 1174 (CC_CONTENT_TEXT | CC_CONTENT_DATA))
1221 1175 return (0);
1222 1176
1223 1177 /*
1224 1178 * First, we find the checksum value in the elf file.
1225 1179 */
1226 1180 scn = NULL;
1227 1181 while ((scn = elf_nextscn(elf, scn)) != NULL) {
1228 1182 if (gelf_getshdr(scn, &shdr) != NULL &&
1229 1183 shdr.sh_type == SHT_DYNAMIC)
1230 1184 goto found_shdr;
1231 1185 }
1232 1186 return (0);
1233 1187
1234 1188 found_shdr:
1235 1189 if ((data = elf_getdata(scn, NULL)) == NULL)
1236 1190 return (0);
1237 1191
1238 1192 if (P->status.pr_dmodel == PR_MODEL_ILP32)
1239 1193 ndyn = shdr.sh_size / sizeof (Elf32_Dyn);
1240 1194 #ifdef _LP64
1241 1195 else if (P->status.pr_dmodel == PR_MODEL_LP64)
1242 1196 ndyn = shdr.sh_size / sizeof (Elf64_Dyn);
1243 1197 #endif
1244 1198 else
1245 1199 return (0);
1246 1200
1247 1201 for (i = 0; i < ndyn; i++) {
1248 1202 if (gelf_getdyn(data, i, &dyn) != NULL &&
1249 1203 dyn.d_tag == DT_CHECKSUM)
1250 1204 goto found_cksum;
1251 1205 }
1252 1206
1253 1207 /*
1254 1208 * The in-memory ELF has no DT_CHECKSUM section, but we will report it
1255 1209 * as matching the file anyhow.
1256 1210 */
1257 1211 return (0);
1258 1212
1259 1213 found_cksum:
1260 1214 cksum = dyn.d_un.d_val;
1261 1215 dprintf("elf cksum value is %llx\n", (u_longlong_t)cksum);
1262 1216
1263 1217 /*
1264 1218 * Get the base of the text mapping that corresponds to this file.
1265 1219 */
1266 1220 addr = fptr->file_map->map_pmap.pr_vaddr;
1267 1221
1268 1222 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1269 1223 Elf32_Ehdr ehdr;
1270 1224 Elf32_Phdr phdr;
1271 1225 Elf32_Dyn dync, *dynp;
1272 1226 uint_t phnum, i;
1273 1227
1274 1228 if (read_ehdr32(P, &ehdr, &phnum, addr) != 0 ||
1275 1229 read_dynamic_phdr32(P, &ehdr, phnum, &phdr, addr) != 0)
1276 1230 return (0);
1277 1231
1278 1232 if (ehdr.e_type == ET_DYN)
1279 1233 phdr.p_vaddr += addr;
1280 1234 if ((dynp = malloc(phdr.p_filesz)) == NULL)
1281 1235 return (0);
1282 1236 dync.d_tag = DT_NULL;
1283 1237 if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) !=
1284 1238 phdr.p_filesz) {
1285 1239 free(dynp);
1286 1240 return (0);
1287 1241 }
1288 1242
1289 1243 for (i = 0; i < phdr.p_filesz / sizeof (Elf32_Dyn); i++) {
1290 1244 if (dynp[i].d_tag == DT_CHECKSUM)
1291 1245 dync = dynp[i];
1292 1246 }
1293 1247
1294 1248 free(dynp);
1295 1249
1296 1250 if (dync.d_tag != DT_CHECKSUM)
1297 1251 return (0);
1298 1252
1299 1253 dprintf("image cksum value is %llx\n",
1300 1254 (u_longlong_t)dync.d_un.d_val);
1301 1255 return (dync.d_un.d_val != cksum);
1302 1256 #ifdef _LP64
1303 1257 } else if (P->status.pr_dmodel == PR_MODEL_LP64) {
1304 1258 Elf64_Ehdr ehdr;
1305 1259 Elf64_Phdr phdr;
1306 1260 Elf64_Dyn dync, *dynp;
1307 1261 uint_t phnum, i;
1308 1262
1309 1263 if (read_ehdr64(P, &ehdr, &phnum, addr) != 0 ||
1310 1264 read_dynamic_phdr64(P, &ehdr, phnum, &phdr, addr) != 0)
1311 1265 return (0);
1312 1266
1313 1267 if (ehdr.e_type == ET_DYN)
1314 1268 phdr.p_vaddr += addr;
1315 1269 if ((dynp = malloc(phdr.p_filesz)) == NULL)
1316 1270 return (0);
1317 1271 dync.d_tag = DT_NULL;
1318 1272 if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) !=
1319 1273 phdr.p_filesz) {
1320 1274 free(dynp);
1321 1275 return (0);
1322 1276 }
1323 1277
1324 1278 for (i = 0; i < phdr.p_filesz / sizeof (Elf64_Dyn); i++) {
1325 1279 if (dynp[i].d_tag == DT_CHECKSUM)
1326 1280 dync = dynp[i];
1327 1281 }
1328 1282
1329 1283 free(dynp);
1330 1284
1331 1285 if (dync.d_tag != DT_CHECKSUM)
1332 1286 return (0);
1333 1287
1334 1288 dprintf("image cksum value is %llx\n",
1335 1289 (u_longlong_t)dync.d_un.d_val);
1336 1290 return (dync.d_un.d_val != cksum);
1337 1291 #endif /* _LP64 */
1338 1292 }
1339 1293
1340 1294 return (0);
1341 1295 }
1342 1296
1343 1297 /*
1344 1298 * Read data from the specified process and construct an in memory
1345 1299 * image of an ELF file that represents it well enough to let
1346 1300 * us probe it for information.
1347 1301 */
1348 1302 static Elf *
1349 1303 fake_elf(struct ps_prochandle *P, file_info_t *fptr)
1350 1304 {
1351 1305 Elf *elf;
1352 1306 uintptr_t addr;
1353 1307 uint_t phnum;
1354 1308
1355 1309 if (fptr->file_map == NULL)
1356 1310 return (NULL);
1357 1311
1358 1312 if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) !=
1359 1313 (CC_CONTENT_TEXT | CC_CONTENT_DATA))
1360 1314 return (NULL);
1361 1315
1362 1316 addr = fptr->file_map->map_pmap.pr_vaddr;
1363 1317
1364 1318 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1365 1319 Elf32_Ehdr ehdr;
1366 1320 Elf32_Phdr phdr;
1367 1321
1368 1322 if ((read_ehdr32(P, &ehdr, &phnum, addr) != 0) ||
1369 1323 read_dynamic_phdr32(P, &ehdr, phnum, &phdr, addr) != 0)
1370 1324 return (NULL);
1371 1325
1372 1326 elf = fake_elf32(P, fptr, addr, &ehdr, phnum, &phdr);
1373 1327 #ifdef _LP64
1374 1328 } else {
1375 1329 Elf64_Ehdr ehdr;
1376 1330 Elf64_Phdr phdr;
1377 1331
1378 1332 if (read_ehdr64(P, &ehdr, &phnum, addr) != 0 ||
1379 1333 read_dynamic_phdr64(P, &ehdr, phnum, &phdr, addr) != 0)
1380 1334 return (NULL);
1381 1335
1382 1336 elf = fake_elf64(P, fptr, addr, &ehdr, phnum, &phdr);
1383 1337 #endif
1384 1338 }
1385 1339
1386 1340 return (elf);
1387 1341 }
1388 1342
1389 1343 /*
1390 1344 * We wouldn't need these if qsort(3C) took an argument for the callback...
1391 1345 */
1392 1346 static mutex_t sort_mtx = DEFAULTMUTEX;
1393 1347 static char *sort_strs;
1394 1348 static GElf_Sym *sort_syms;
1395 1349
1396 1350 int
1397 1351 byaddr_cmp_common(GElf_Sym *a, char *aname, GElf_Sym *b, char *bname)
1398 1352 {
1399 1353 if (a->st_value < b->st_value)
1400 1354 return (-1);
1401 1355 if (a->st_value > b->st_value)
1402 1356 return (1);
1403 1357
1404 1358 /*
1405 1359 * Prefer the function to the non-function.
1406 1360 */
1407 1361 if (GELF_ST_TYPE(a->st_info) != GELF_ST_TYPE(b->st_info)) {
1408 1362 if (GELF_ST_TYPE(a->st_info) == STT_FUNC)
1409 1363 return (-1);
1410 1364 if (GELF_ST_TYPE(b->st_info) == STT_FUNC)
1411 1365 return (1);
1412 1366 }
1413 1367
1414 1368 /*
1415 1369 * Prefer the weak or strong global symbol to the local symbol.
1416 1370 */
1417 1371 if (GELF_ST_BIND(a->st_info) != GELF_ST_BIND(b->st_info)) {
1418 1372 if (GELF_ST_BIND(b->st_info) == STB_LOCAL)
1419 1373 return (-1);
1420 1374 if (GELF_ST_BIND(a->st_info) == STB_LOCAL)
1421 1375 return (1);
1422 1376 }
1423 1377
1424 1378 /*
1425 1379 * Prefer the symbol that doesn't begin with a '$' since compilers and
1426 1380 * other symbol generators often use it as a prefix.
1427 1381 */
1428 1382 if (*bname == '$')
1429 1383 return (-1);
1430 1384 if (*aname == '$')
1431 1385 return (1);
1432 1386
1433 1387 /*
1434 1388 * Prefer the name with fewer leading underscores in the name.
1435 1389 */
1436 1390 while (*aname == '_' && *bname == '_') {
1437 1391 aname++;
1438 1392 bname++;
1439 1393 }
1440 1394
1441 1395 if (*bname == '_')
1442 1396 return (-1);
1443 1397 if (*aname == '_')
1444 1398 return (1);
1445 1399
1446 1400 /*
1447 1401 * Prefer the symbol with the smaller size.
1448 1402 */
1449 1403 if (a->st_size < b->st_size)
1450 1404 return (-1);
1451 1405 if (a->st_size > b->st_size)
1452 1406 return (1);
1453 1407
1454 1408 /*
1455 1409 * All other factors being equal, fall back to lexicographic order.
1456 1410 */
1457 1411 return (strcmp(aname, bname));
1458 1412 }
1459 1413
1460 1414 static int
1461 1415 byaddr_cmp(const void *aa, const void *bb)
1462 1416 {
1463 1417 GElf_Sym *a = &sort_syms[*(uint_t *)aa];
1464 1418 GElf_Sym *b = &sort_syms[*(uint_t *)bb];
1465 1419 char *aname = sort_strs + a->st_name;
1466 1420 char *bname = sort_strs + b->st_name;
1467 1421
1468 1422 return (byaddr_cmp_common(a, aname, b, bname));
1469 1423 }
1470 1424
1471 1425 static int
1472 1426 byname_cmp(const void *aa, const void *bb)
1473 1427 {
1474 1428 GElf_Sym *a = &sort_syms[*(uint_t *)aa];
1475 1429 GElf_Sym *b = &sort_syms[*(uint_t *)bb];
1476 1430 char *aname = sort_strs + a->st_name;
1477 1431 char *bname = sort_strs + b->st_name;
1478 1432
1479 1433 return (strcmp(aname, bname));
1480 1434 }
1481 1435
1482 1436 /*
1483 1437 * Given a symbol index, look up the corresponding symbol from the
1484 1438 * given symbol table.
1485 1439 *
1486 1440 * This function allows the caller to treat the symbol table as a single
1487 1441 * logical entity even though there may be 2 actual ELF symbol tables
1488 1442 * involved. See the comments in Pcontrol.h for details.
1489 1443 */
1490 1444 static GElf_Sym *
1491 1445 symtab_getsym(sym_tbl_t *symtab, int ndx, GElf_Sym *dst)
1492 1446 {
1493 1447 /* If index is in range of primary symtab, look it up there */
1494 1448 if (ndx >= symtab->sym_symn_aux) {
1495 1449 return (gelf_getsym(symtab->sym_data_pri,
1496 1450 ndx - symtab->sym_symn_aux, dst));
1497 1451 }
1498 1452
1499 1453 /* Not in primary: Look it up in the auxiliary symtab */
1500 1454 return (gelf_getsym(symtab->sym_data_aux, ndx, dst));
1501 1455 }
1502 1456
1503 1457 void
1504 1458 optimize_symtab(sym_tbl_t *symtab)
1505 1459 {
1506 1460 GElf_Sym *symp, *syms;
1507 1461 uint_t i, *indexa, *indexb;
1508 1462 size_t symn, strsz, count;
1509 1463
1510 1464 if (symtab == NULL || symtab->sym_data_pri == NULL ||
1511 1465 symtab->sym_byaddr != NULL)
1512 1466 return;
1513 1467
1514 1468 symn = symtab->sym_symn;
1515 1469 strsz = symtab->sym_strsz;
1516 1470
1517 1471 symp = syms = malloc(sizeof (GElf_Sym) * symn);
1518 1472 if (symp == NULL) {
1519 1473 dprintf("optimize_symtab: failed to malloc symbol array");
1520 1474 return;
1521 1475 }
1522 1476
1523 1477 /*
1524 1478 * First record all the symbols into a table and count up the ones
1525 1479 * that we're interested in. We mark symbols as invalid by setting
1526 1480 * the st_name to an illegal value.
1527 1481 */
1528 1482 for (i = 0, count = 0; i < symn; i++, symp++) {
1529 1483 if (symtab_getsym(symtab, i, symp) != NULL &&
1530 1484 symp->st_name < strsz &&
1531 1485 IS_DATA_TYPE(GELF_ST_TYPE(symp->st_info)))
1532 1486 count++;
1533 1487 else
1534 1488 symp->st_name = strsz;
1535 1489 }
1536 1490
1537 1491 /*
1538 1492 * Allocate sufficient space for both tables and populate them
1539 1493 * with the same symbols we just counted.
1540 1494 */
1541 1495 symtab->sym_count = count;
1542 1496 indexa = symtab->sym_byaddr = calloc(sizeof (uint_t), count);
1543 1497 indexb = symtab->sym_byname = calloc(sizeof (uint_t), count);
1544 1498 if (indexa == NULL || indexb == NULL) {
1545 1499 dprintf(
1546 1500 "optimize_symtab: failed to malloc symbol index arrays");
1547 1501 symtab->sym_count = 0;
1548 1502 if (indexa != NULL) { /* First alloc succeeded. Free it */
1549 1503 free(indexa);
1550 1504 symtab->sym_byaddr = NULL;
1551 1505 }
1552 1506 free(syms);
1553 1507 return;
1554 1508 }
1555 1509 for (i = 0, symp = syms; i < symn; i++, symp++) {
1556 1510 if (symp->st_name < strsz)
1557 1511 *indexa++ = *indexb++ = i;
1558 1512 }
1559 1513
1560 1514 /*
1561 1515 * Sort the two tables according to the appropriate criteria,
1562 1516 * unless the user has overridden this behaviour.
1563 1517 *
1564 1518 * An example where we might not sort the tables is the relatively
1565 1519 * unusual case of a process with very large symbol tables in which
1566 1520 * we perform few lookups. In such a case the total time would be
1567 1521 * dominated by the sort. It is difficult to determine a priori
1568 1522 * how many lookups an arbitrary client will perform, and
1569 1523 * hence whether the symbol tables should be sorted. We therefore
1570 1524 * sort the tables by default, but provide the user with a
1571 1525 * "chicken switch" in the form of the LIBPROC_NO_QSORT
1572 1526 * environment variable.
1573 1527 */
1574 1528 if (!_libproc_no_qsort) {
1575 1529 (void) mutex_lock(&sort_mtx);
1576 1530 sort_strs = symtab->sym_strs;
1577 1531 sort_syms = syms;
1578 1532
1579 1533 qsort(symtab->sym_byaddr, count, sizeof (uint_t), byaddr_cmp);
1580 1534 qsort(symtab->sym_byname, count, sizeof (uint_t), byname_cmp);
1581 1535
1582 1536 sort_strs = NULL;
1583 1537 sort_syms = NULL;
1584 1538 (void) mutex_unlock(&sort_mtx);
1585 1539 }
1586 1540
1587 1541 free(syms);
1588 1542 }
1589 1543
1590 1544
1591 1545 static Elf *
1592 1546 build_fake_elf(struct ps_prochandle *P, file_info_t *fptr, GElf_Ehdr *ehdr,
1593 1547 size_t *nshdrs, Elf_Data **shdata)
1594 1548 {
1595 1549 size_t shstrndx;
1596 1550 Elf_Scn *scn;
1597 1551 Elf *elf;
1598 1552
1599 1553 if ((elf = fake_elf(P, fptr)) == NULL ||
1600 1554 elf_kind(elf) != ELF_K_ELF ||
1601 1555 gelf_getehdr(elf, ehdr) == NULL ||
1602 1556 elf_getshdrnum(elf, nshdrs) == -1 ||
1603 1557 elf_getshdrstrndx(elf, &shstrndx) == -1 ||
1604 1558 (scn = elf_getscn(elf, shstrndx)) == NULL ||
1605 1559 (*shdata = elf_getdata(scn, NULL)) == NULL) {
1606 1560 if (elf != NULL)
1607 1561 (void) elf_end(elf);
1608 1562 dprintf("failed to fake up ELF file\n");
1609 1563 return (NULL);
1610 1564 }
1611 1565
1612 1566 return (elf);
1613 1567 }
1614 1568
1615 1569 /*
1616 1570 * Build the symbol table for the given mapped file.
1617 1571 */
1618 1572 void
1619 1573 Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr)
1620 1574 {
1621 1575 char objectfile[PATH_MAX];
1622 1576 uint_t i;
1623 1577
1624 1578 GElf_Ehdr ehdr;
1625 1579 GElf_Sym s;
1626 1580
1627 1581 Elf_Data *shdata;
1628 1582 Elf_Scn *scn;
1629 1583 Elf *elf;
1630 1584 size_t nshdrs, shstrndx;
1631 1585
1632 1586 struct {
1633 1587 GElf_Shdr c_shdr;
1634 1588 Elf_Data *c_data;
1635 1589 const char *c_name;
1636 1590 } *cp, *cache = NULL, *dyn = NULL, *plt = NULL, *ctf = NULL;
1637 1591
1638 1592 if (fptr->file_init)
1639 1593 return; /* We've already processed this file */
1640 1594
1641 1595 /*
1642 1596 * Mark the file_info struct as having the symbol table initialized
1643 1597 * even if we fail below. We tried once; we don't try again.
1644 1598 */
1645 1599 fptr->file_init = 1;
1646 1600
1647 1601 if (elf_version(EV_CURRENT) == EV_NONE) {
1648 1602 dprintf("libproc ELF version is more recent than libelf\n");
1649 1603 return;
1650 1604 }
1651 1605
1652 1606 if (P->state == PS_DEAD || P->state == PS_IDLE) {
1653 1607 char *name;
1654 1608 /*
1655 1609 * If we're a not live, we can't open files from the /proc
1656 1610 * object directory; we have only the mapping and file names
1657 1611 * to guide us. We prefer the file_lname, but need to handle
1658 1612 * the case of it being NULL in order to bootstrap: we first
1659 1613 * come here during rd_new() when the only information we have
1660 1614 * is interpreter name associated with the AT_BASE mapping.
1661 1615 *
1662 1616 * Also, if the zone associated with the core file seems
1663 1617 * to exists on this machine we'll try to open the object
1664 1618 * file within the zone.
1665 1619 */
1666 1620 if (fptr->file_rname != NULL)
1667 1621 name = fptr->file_rname;
1668 1622 else if (fptr->file_lname != NULL)
1669 1623 name = fptr->file_lname;
1670 1624 else
1671 1625 name = fptr->file_pname;
1672 1626 (void) strlcpy(objectfile, name, sizeof (objectfile));
1673 1627 } else {
1674 1628 (void) snprintf(objectfile, sizeof (objectfile),
1675 1629 "%s/%d/object/%s",
↓ open down ↓ |
770 lines elided |
↑ open up ↑ |
1676 1630 procfs_path, (int)P->pid, fptr->file_pname);
1677 1631 }
1678 1632
1679 1633 /*
1680 1634 * Open the object file, create the elf file, and then get the elf
1681 1635 * header and .shstrtab data buffer so we can process sections by
1682 1636 * name. If anything goes wrong try to fake up an elf file from
1683 1637 * the in-core elf image.
1684 1638 */
1685 1639
1686 - if (_libproc_incore_elf) {
1640 + if (_libproc_incore_elf || (P->flags & INCORE)) {
1687 1641 dprintf("Pbuild_file_symtab: using in-core data for: %s\n",
1688 1642 fptr->file_pname);
1689 1643
1690 1644 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1691 1645 NULL)
1692 1646 return;
1693 1647
1694 1648 } else if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) {
1695 1649 dprintf("Pbuild_file_symtab: failed to open %s: %s\n",
1696 1650 objectfile, strerror(errno));
1697 1651
1698 1652 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1699 1653 NULL)
1700 1654 return;
1701 1655
1702 1656 } else if ((elf = elf_begin(fptr->file_fd, ELF_C_READ, NULL)) == NULL ||
1703 1657 elf_kind(elf) != ELF_K_ELF ||
1704 1658 gelf_getehdr(elf, &ehdr) == NULL ||
1705 1659 elf_getshdrnum(elf, &nshdrs) == -1 ||
1706 1660 elf_getshdrstrndx(elf, &shstrndx) == -1 ||
1707 1661 (scn = elf_getscn(elf, shstrndx)) == NULL ||
1708 1662 (shdata = elf_getdata(scn, NULL)) == NULL) {
1709 1663 int err = elf_errno();
1710 1664
1711 1665 dprintf("failed to process ELF file %s: %s\n",
1712 1666 objectfile, (err == 0) ? "<null>" : elf_errmsg(err));
1713 1667 (void) elf_end(elf);
1714 1668
1715 1669 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1716 1670 NULL)
1717 1671 return;
1718 1672
1719 1673 } else if (file_differs(P, elf, fptr)) {
1720 1674 Elf *newelf;
1721 1675
1722 1676 /*
1723 1677 * Before we get too excited about this elf file, we'll check
1724 1678 * its checksum value against the value we have in memory. If
1725 1679 * they don't agree, we try to fake up a new elf file and
1726 1680 * proceed with that instead.
1727 1681 */
1728 1682 dprintf("ELF file %s (%lx) doesn't match in-core image\n",
1729 1683 fptr->file_pname,
1730 1684 (ulong_t)fptr->file_map->map_pmap.pr_vaddr);
1731 1685
1732 1686 if ((newelf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata))
1733 1687 != NULL) {
1734 1688 (void) elf_end(elf);
1735 1689 elf = newelf;
1736 1690 dprintf("switched to faked up ELF file\n");
1737 1691
1738 1692 /*
1739 1693 * Check to see if the file that we just discovered
1740 1694 * to be an imposter matches the execname that was
1741 1695 * determined by Pfindexec(). If it does, we (clearly)
1742 1696 * don't have the right binary, and we zero out
1743 1697 * execname before anyone gets hurt.
1744 1698 */
1745 1699 if (fptr->file_rname != NULL && P->execname != NULL &&
1746 1700 strcmp(fptr->file_rname, P->execname) == 0) {
1747 1701 dprintf("file/in-core image mismatch was "
1748 1702 "on P->execname; discarding\n");
1749 1703 free(P->execname);
1750 1704 P->execname = NULL;
1751 1705 }
1752 1706 }
1753 1707 }
1754 1708
1755 1709 if ((cache = malloc(nshdrs * sizeof (*cache))) == NULL) {
1756 1710 dprintf("failed to malloc section cache for %s\n", objectfile);
1757 1711 goto bad;
1758 1712 }
1759 1713
1760 1714 dprintf("processing ELF file %s\n", objectfile);
1761 1715 fptr->file_class = ehdr.e_ident[EI_CLASS];
1762 1716 fptr->file_etype = ehdr.e_type;
1763 1717 fptr->file_elf = elf;
1764 1718 fptr->file_shstrs = shdata->d_buf;
1765 1719 fptr->file_shstrsz = shdata->d_size;
1766 1720
1767 1721 /*
1768 1722 * Iterate through each section, caching its section header, data
1769 1723 * pointer, and name. We use this for handling sh_link values below.
1770 1724 */
1771 1725 for (cp = cache + 1, scn = NULL; scn = elf_nextscn(elf, scn); cp++) {
1772 1726 if (gelf_getshdr(scn, &cp->c_shdr) == NULL) {
1773 1727 dprintf("Pbuild_file_symtab: Failed to get section "
1774 1728 "header\n");
1775 1729 goto bad; /* Failed to get section header */
1776 1730 }
1777 1731
1778 1732 if ((cp->c_data = elf_getdata(scn, NULL)) == NULL) {
1779 1733 dprintf("Pbuild_file_symtab: Failed to get section "
1780 1734 "data\n");
1781 1735 goto bad; /* Failed to get section data */
1782 1736 }
1783 1737
1784 1738 if (cp->c_shdr.sh_name >= shdata->d_size) {
1785 1739 dprintf("Pbuild_file_symtab: corrupt section name");
1786 1740 goto bad; /* Corrupt section name */
1787 1741 }
1788 1742
1789 1743 cp->c_name = (const char *)shdata->d_buf + cp->c_shdr.sh_name;
1790 1744 }
1791 1745
1792 1746 /*
1793 1747 * Now iterate through the section cache in order to locate info
1794 1748 * for the .symtab, .dynsym, .SUNW_ldynsym, .dynamic, .plt,
1795 1749 * and .SUNW_ctf sections:
1796 1750 */
1797 1751 for (i = 1, cp = cache + 1; i < nshdrs; i++, cp++) {
1798 1752 GElf_Shdr *shp = &cp->c_shdr;
1799 1753
1800 1754 if (shp->sh_type == SHT_SYMTAB || shp->sh_type == SHT_DYNSYM) {
1801 1755 sym_tbl_t *symp = shp->sh_type == SHT_SYMTAB ?
1802 1756 &fptr->file_symtab : &fptr->file_dynsym;
1803 1757 /*
1804 1758 * It's possible that the we already got the symbol
1805 1759 * table from the core file itself. Either the file
1806 1760 * differs in which case our faked up elf file will
1807 1761 * only contain the dynsym (not the symtab) or the
1808 1762 * file matches in which case we'll just be replacing
1809 1763 * the symbol table we pulled out of the core file
1810 1764 * with an equivalent one. In either case, this
1811 1765 * check isn't essential, but it's a good idea.
1812 1766 */
1813 1767 if (symp->sym_data_pri == NULL) {
1814 1768 dprintf("Symbol table found for %s\n",
1815 1769 objectfile);
1816 1770 symp->sym_data_pri = cp->c_data;
1817 1771 symp->sym_symn +=
1818 1772 shp->sh_size / shp->sh_entsize;
1819 1773 symp->sym_strs =
1820 1774 cache[shp->sh_link].c_data->d_buf;
1821 1775 symp->sym_strsz =
1822 1776 cache[shp->sh_link].c_data->d_size;
1823 1777 symp->sym_hdr_pri = cp->c_shdr;
1824 1778 symp->sym_strhdr = cache[shp->sh_link].c_shdr;
1825 1779 } else {
1826 1780 dprintf("Symbol table already there for %s\n",
1827 1781 objectfile);
1828 1782 }
1829 1783 } else if (shp->sh_type == SHT_SUNW_LDYNSYM) {
1830 1784 /* .SUNW_ldynsym section is auxiliary to .dynsym */
1831 1785 if (fptr->file_dynsym.sym_data_aux == NULL) {
1832 1786 dprintf(".SUNW_ldynsym symbol table"
1833 1787 " found for %s\n", objectfile);
1834 1788 fptr->file_dynsym.sym_data_aux = cp->c_data;
1835 1789 fptr->file_dynsym.sym_symn_aux =
1836 1790 shp->sh_size / shp->sh_entsize;
1837 1791 fptr->file_dynsym.sym_symn +=
1838 1792 fptr->file_dynsym.sym_symn_aux;
1839 1793 fptr->file_dynsym.sym_hdr_aux = cp->c_shdr;
1840 1794 } else {
1841 1795 dprintf(".SUNW_ldynsym symbol table already"
1842 1796 " there for %s\n", objectfile);
1843 1797 }
1844 1798 } else if (shp->sh_type == SHT_DYNAMIC) {
1845 1799 dyn = cp;
1846 1800 } else if (strcmp(cp->c_name, ".plt") == 0) {
1847 1801 plt = cp;
1848 1802 } else if (strcmp(cp->c_name, ".SUNW_ctf") == 0) {
1849 1803 /*
1850 1804 * Skip over bogus CTF sections so they don't come back
1851 1805 * to haunt us later.
1852 1806 */
1853 1807 if (shp->sh_link == 0 ||
1854 1808 shp->sh_link >= nshdrs ||
1855 1809 (cache[shp->sh_link].c_shdr.sh_type != SHT_DYNSYM &&
1856 1810 cache[shp->sh_link].c_shdr.sh_type != SHT_SYMTAB)) {
1857 1811 dprintf("Bad sh_link %d for "
1858 1812 "CTF\n", shp->sh_link);
1859 1813 continue;
1860 1814 }
1861 1815 ctf = cp;
1862 1816 }
1863 1817 }
1864 1818
1865 1819 /*
1866 1820 * At this point, we've found all the symbol tables we're ever going
1867 1821 * to find: the ones in the loop above and possibly the symtab that
1868 1822 * was included in the core file. Before we perform any lookups, we
1869 1823 * create sorted versions to optimize for lookups.
1870 1824 */
1871 1825 optimize_symtab(&fptr->file_symtab);
1872 1826 optimize_symtab(&fptr->file_dynsym);
1873 1827
1874 1828 /*
1875 1829 * Fill in the base address of the text mapping for shared libraries.
1876 1830 * This allows us to translate symbols before librtld_db is ready.
1877 1831 */
1878 1832 if (fptr->file_etype == ET_DYN) {
1879 1833 fptr->file_dyn_base = fptr->file_map->map_pmap.pr_vaddr -
1880 1834 fptr->file_map->map_pmap.pr_offset;
1881 1835 dprintf("setting file_dyn_base for %s to %lx\n",
1882 1836 objectfile, (long)fptr->file_dyn_base);
1883 1837 }
1884 1838
1885 1839 /*
1886 1840 * Record the CTF section information in the file info structure.
1887 1841 */
1888 1842 if (ctf != NULL) {
1889 1843 fptr->file_ctf_off = ctf->c_shdr.sh_offset;
1890 1844 fptr->file_ctf_size = ctf->c_shdr.sh_size;
1891 1845 if (ctf->c_shdr.sh_link != 0 &&
1892 1846 cache[ctf->c_shdr.sh_link].c_shdr.sh_type == SHT_DYNSYM)
1893 1847 fptr->file_ctf_dyn = 1;
1894 1848 }
1895 1849
1896 1850 if (fptr->file_lo == NULL)
1897 1851 goto done; /* Nothing else to do if no load object info */
1898 1852
1899 1853 /*
1900 1854 * If the object is a shared library and we have a different rl_base
1901 1855 * value, reset file_dyn_base according to librtld_db's information.
1902 1856 */
1903 1857 if (fptr->file_etype == ET_DYN &&
1904 1858 fptr->file_lo->rl_base != fptr->file_dyn_base) {
1905 1859 dprintf("resetting file_dyn_base for %s to %lx\n",
1906 1860 objectfile, (long)fptr->file_lo->rl_base);
1907 1861 fptr->file_dyn_base = fptr->file_lo->rl_base;
1908 1862 }
1909 1863
1910 1864 /*
1911 1865 * Fill in the PLT information for this file if a PLT symbol is found.
1912 1866 */
1913 1867 if (sym_by_name(&fptr->file_dynsym, "_PROCEDURE_LINKAGE_TABLE_", &s,
1914 1868 NULL) != NULL) {
1915 1869 fptr->file_plt_base = s.st_value + fptr->file_dyn_base;
1916 1870 fptr->file_plt_size = (plt != NULL) ? plt->c_shdr.sh_size : 0;
1917 1871
1918 1872 /*
1919 1873 * Bring the load object up to date; it is the only way the
1920 1874 * user has to access the PLT data. The PLT information in the
1921 1875 * rd_loadobj_t is not set in the call to map_iter() (the
1922 1876 * callback for rd_loadobj_iter) where we set file_lo.
1923 1877 */
1924 1878 fptr->file_lo->rl_plt_base = fptr->file_plt_base;
1925 1879 fptr->file_lo->rl_plt_size = fptr->file_plt_size;
1926 1880
1927 1881 dprintf("PLT found at %p, size = %lu\n",
1928 1882 (void *)fptr->file_plt_base, (ulong_t)fptr->file_plt_size);
1929 1883 }
1930 1884
1931 1885 /*
1932 1886 * Fill in the PLT information.
1933 1887 */
1934 1888 if (dyn != NULL) {
1935 1889 uintptr_t dynaddr = dyn->c_shdr.sh_addr + fptr->file_dyn_base;
1936 1890 size_t ndyn = dyn->c_shdr.sh_size / dyn->c_shdr.sh_entsize;
1937 1891 GElf_Dyn d;
1938 1892
1939 1893 for (i = 0; i < ndyn; i++) {
1940 1894 if (gelf_getdyn(dyn->c_data, i, &d) == NULL)
1941 1895 continue;
1942 1896
1943 1897 switch (d.d_tag) {
1944 1898 case DT_JMPREL:
1945 1899 dprintf("DT_JMPREL is %p\n",
1946 1900 (void *)(uintptr_t)d.d_un.d_ptr);
1947 1901 fptr->file_jmp_rel =
1948 1902 d.d_un.d_ptr + fptr->file_dyn_base;
1949 1903 break;
1950 1904 case DT_STRTAB:
1951 1905 dprintf("DT_STRTAB is %p\n",
1952 1906 (void *)(uintptr_t)d.d_un.d_ptr);
1953 1907 break;
1954 1908 case DT_PLTGOT:
1955 1909 dprintf("DT_PLTGOT is %p\n",
1956 1910 (void *)(uintptr_t)d.d_un.d_ptr);
1957 1911 break;
1958 1912 case DT_SUNW_SYMTAB:
1959 1913 dprintf("DT_SUNW_SYMTAB is %p\n",
1960 1914 (void *)(uintptr_t)d.d_un.d_ptr);
1961 1915 break;
1962 1916 case DT_SYMTAB:
1963 1917 dprintf("DT_SYMTAB is %p\n",
1964 1918 (void *)(uintptr_t)d.d_un.d_ptr);
1965 1919 break;
1966 1920 case DT_HASH:
1967 1921 dprintf("DT_HASH is %p\n",
1968 1922 (void *)(uintptr_t)d.d_un.d_ptr);
1969 1923 break;
1970 1924 }
1971 1925 }
1972 1926
1973 1927 dprintf("_DYNAMIC found at %p, %lu entries, DT_JMPREL = %p\n",
1974 1928 (void *)dynaddr, (ulong_t)ndyn, (void *)fptr->file_jmp_rel);
1975 1929 }
1976 1930
1977 1931 done:
1978 1932 free(cache);
1979 1933 return;
1980 1934
1981 1935 bad:
1982 1936 if (cache != NULL)
1983 1937 free(cache);
1984 1938
1985 1939 (void) elf_end(elf);
1986 1940 fptr->file_elf = NULL;
1987 1941 if (fptr->file_elfmem != NULL) {
1988 1942 free(fptr->file_elfmem);
1989 1943 fptr->file_elfmem = NULL;
1990 1944 }
1991 1945 (void) close(fptr->file_fd);
1992 1946 fptr->file_fd = -1;
1993 1947 }
1994 1948
1995 1949 /*
1996 1950 * Given a process virtual address, return the map_info_t containing it.
1997 1951 * If none found, return NULL.
1998 1952 */
1999 1953 map_info_t *
2000 1954 Paddr2mptr(struct ps_prochandle *P, uintptr_t addr)
2001 1955 {
2002 1956 int lo = 0;
2003 1957 int hi = P->map_count - 1;
2004 1958 int mid;
2005 1959 map_info_t *mp;
2006 1960
2007 1961 while (lo <= hi) {
2008 1962
2009 1963 mid = (lo + hi) / 2;
2010 1964 mp = &P->mappings[mid];
2011 1965
2012 1966 /* check that addr is in [vaddr, vaddr + size) */
2013 1967 if ((addr - mp->map_pmap.pr_vaddr) < mp->map_pmap.pr_size)
2014 1968 return (mp);
2015 1969
2016 1970 if (addr < mp->map_pmap.pr_vaddr)
2017 1971 hi = mid - 1;
2018 1972 else
2019 1973 lo = mid + 1;
2020 1974 }
2021 1975
2022 1976 return (NULL);
2023 1977 }
2024 1978
2025 1979 /*
2026 1980 * Return the map_info_t for the executable file.
2027 1981 * If not found, return NULL.
2028 1982 */
2029 1983 static map_info_t *
2030 1984 exec_map(struct ps_prochandle *P)
2031 1985 {
2032 1986 uint_t i;
2033 1987 map_info_t *mptr;
2034 1988 map_info_t *mold = NULL;
2035 1989 file_info_t *fptr;
2036 1990 uintptr_t base;
2037 1991
2038 1992 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) {
2039 1993 if (mptr->map_pmap.pr_mapname[0] == '\0')
2040 1994 continue;
2041 1995 if (strcmp(mptr->map_pmap.pr_mapname, "a.out") == 0) {
2042 1996 if ((fptr = mptr->map_file) != NULL &&
2043 1997 fptr->file_lo != NULL) {
2044 1998 base = fptr->file_lo->rl_base;
2045 1999 if (base >= mptr->map_pmap.pr_vaddr &&
2046 2000 base < mptr->map_pmap.pr_vaddr +
2047 2001 mptr->map_pmap.pr_size) /* text space */
2048 2002 return (mptr);
2049 2003 mold = mptr; /* must be the data */
2050 2004 continue;
2051 2005 }
2052 2006 /* This is a poor way to test for text space */
2053 2007 if (!(mptr->map_pmap.pr_mflags & MA_EXEC) ||
2054 2008 (mptr->map_pmap.pr_mflags & MA_WRITE)) {
2055 2009 mold = mptr;
2056 2010 continue;
2057 2011 }
2058 2012 return (mptr);
2059 2013 }
2060 2014 }
2061 2015
2062 2016 return (mold);
2063 2017 }
2064 2018
2065 2019 /*
2066 2020 * Given a shared object name, return the map_info_t for it. If no matching
2067 2021 * object is found, return NULL. Normally, the link maps contain the full
2068 2022 * object pathname, e.g. /usr/lib/libc.so.1. We allow the object name to
2069 2023 * take one of the following forms:
2070 2024 *
2071 2025 * 1. An exact match (i.e. a full pathname): "/usr/lib/libc.so.1"
2072 2026 * 2. An exact basename match: "libc.so.1"
2073 2027 * 3. An initial basename match up to a '.' suffix: "libc.so" or "libc"
2074 2028 * 4. The literal string "a.out" is an alias for the executable mapping
2075 2029 *
2076 2030 * The third case is a convenience for callers and may not be necessary.
2077 2031 *
2078 2032 * As the exact same object name may be loaded on different link maps (see
2079 2033 * dlmopen(3DL)), we also allow the caller to resolve the object name by
2080 2034 * specifying a particular link map id. If lmid is PR_LMID_EVERY, the
2081 2035 * first matching name will be returned, regardless of the link map id.
2082 2036 */
2083 2037 static map_info_t *
2084 2038 object_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *objname)
2085 2039 {
2086 2040 map_info_t *mp;
2087 2041 file_info_t *fp;
2088 2042 size_t objlen;
2089 2043 uint_t i;
2090 2044
2091 2045 /*
2092 2046 * If we have no rtld_db, then always treat a request as one for all
2093 2047 * link maps.
2094 2048 */
2095 2049 if (P->rap == NULL)
2096 2050 lmid = PR_LMID_EVERY;
2097 2051
2098 2052 /*
2099 2053 * First pass: look for exact matches of the entire pathname or
2100 2054 * basename (cases 1 and 2 above):
2101 2055 */
2102 2056 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) {
2103 2057
2104 2058 if (mp->map_pmap.pr_mapname[0] == '\0' ||
2105 2059 (fp = mp->map_file) == NULL ||
2106 2060 ((fp->file_lname == NULL) && (fp->file_rname == NULL)))
2107 2061 continue;
2108 2062
2109 2063 if (lmid != PR_LMID_EVERY &&
2110 2064 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident))
2111 2065 continue;
2112 2066
2113 2067 /*
2114 2068 * If we match, return the primary text mapping; otherwise
2115 2069 * just return the mapping we matched.
2116 2070 */
2117 2071 if ((fp->file_lbase && strcmp(fp->file_lbase, objname) == 0) ||
2118 2072 (fp->file_rbase && strcmp(fp->file_rbase, objname) == 0) ||
2119 2073 (fp->file_lname && strcmp(fp->file_lname, objname) == 0) ||
2120 2074 (fp->file_rname && strcmp(fp->file_rname, objname) == 0))
2121 2075 return (fp->file_map ? fp->file_map : mp);
2122 2076 }
2123 2077
2124 2078 objlen = strlen(objname);
2125 2079
2126 2080 /*
2127 2081 * Second pass: look for partial matches (case 3 above):
2128 2082 */
2129 2083 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) {
2130 2084
2131 2085 if (mp->map_pmap.pr_mapname[0] == '\0' ||
2132 2086 (fp = mp->map_file) == NULL ||
2133 2087 ((fp->file_lname == NULL) && (fp->file_rname == NULL)))
2134 2088 continue;
2135 2089
2136 2090 if (lmid != PR_LMID_EVERY &&
2137 2091 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident))
2138 2092 continue;
2139 2093
2140 2094 /*
2141 2095 * If we match, return the primary text mapping; otherwise
2142 2096 * just return the mapping we matched.
2143 2097 */
2144 2098 if ((fp->file_lbase != NULL) &&
2145 2099 (strncmp(fp->file_lbase, objname, objlen) == 0) &&
2146 2100 (fp->file_lbase[objlen] == '.'))
2147 2101 return (fp->file_map ? fp->file_map : mp);
2148 2102 if ((fp->file_rbase != NULL) &&
2149 2103 (strncmp(fp->file_rbase, objname, objlen) == 0) &&
2150 2104 (fp->file_rbase[objlen] == '.'))
2151 2105 return (fp->file_map ? fp->file_map : mp);
2152 2106 }
2153 2107
2154 2108 /*
2155 2109 * One last check: we allow "a.out" to always alias the executable,
2156 2110 * assuming this name was not in use for something else.
2157 2111 */
2158 2112 if ((lmid == PR_LMID_EVERY || lmid == LM_ID_BASE) &&
2159 2113 (strcmp(objname, "a.out") == 0))
2160 2114 return (P->map_exec);
2161 2115
2162 2116 return (NULL);
2163 2117 }
2164 2118
2165 2119 static map_info_t *
2166 2120 object_name_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name)
2167 2121 {
2168 2122 map_info_t *mptr;
2169 2123
2170 2124 if (!P->info_valid)
2171 2125 Pupdate_maps(P);
2172 2126
2173 2127 if (P->map_exec == NULL && ((mptr = Paddr2mptr(P,
2174 2128 Pgetauxval(P, AT_ENTRY))) != NULL || (mptr = exec_map(P)) != NULL))
2175 2129 P->map_exec = mptr;
2176 2130
2177 2131 if (P->map_ldso == NULL && (mptr = Paddr2mptr(P,
2178 2132 Pgetauxval(P, AT_BASE))) != NULL)
2179 2133 P->map_ldso = mptr;
2180 2134
2181 2135 if (name == PR_OBJ_EXEC)
2182 2136 mptr = P->map_exec;
2183 2137 else if (name == PR_OBJ_LDSO)
2184 2138 mptr = P->map_ldso;
2185 2139 else if (Prd_agent(P) != NULL || P->state == PS_IDLE)
2186 2140 mptr = object_to_map(P, lmid, name);
2187 2141 else
2188 2142 mptr = NULL;
2189 2143
2190 2144 return (mptr);
2191 2145 }
2192 2146
2193 2147 /*
2194 2148 * When two symbols are found by address, decide which one is to be preferred.
2195 2149 */
2196 2150 static GElf_Sym *
2197 2151 sym_prefer(GElf_Sym *sym1, char *name1, GElf_Sym *sym2, char *name2)
2198 2152 {
2199 2153 /*
2200 2154 * Prefer the non-NULL symbol.
2201 2155 */
2202 2156 if (sym1 == NULL)
2203 2157 return (sym2);
2204 2158 if (sym2 == NULL)
2205 2159 return (sym1);
2206 2160
2207 2161 /*
2208 2162 * Defer to the sort ordering...
2209 2163 */
2210 2164 return (byaddr_cmp_common(sym1, name1, sym2, name2) <= 0 ? sym1 : sym2);
2211 2165 }
2212 2166
2213 2167 /*
2214 2168 * Use a binary search to do the work of sym_by_addr().
2215 2169 */
2216 2170 static GElf_Sym *
2217 2171 sym_by_addr_binary(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp,
2218 2172 uint_t *idp)
2219 2173 {
2220 2174 GElf_Sym sym, osym;
2221 2175 uint_t i, oid, *byaddr = symtab->sym_byaddr;
2222 2176 int min, max, mid, omid, found = 0;
2223 2177
2224 2178 if (symtab->sym_data_pri == NULL || symtab->sym_count == 0)
2225 2179 return (NULL);
2226 2180
2227 2181 min = 0;
2228 2182 max = symtab->sym_count - 1;
2229 2183 osym.st_value = 0;
2230 2184
2231 2185 /*
2232 2186 * We can't return when we've found a match, we have to continue
2233 2187 * searching for the closest matching symbol.
2234 2188 */
2235 2189 while (min <= max) {
2236 2190 mid = (max + min) / 2;
2237 2191
2238 2192 i = byaddr[mid];
2239 2193 (void) symtab_getsym(symtab, i, &sym);
2240 2194
2241 2195 if (addr >= sym.st_value &&
2242 2196 addr < sym.st_value + sym.st_size &&
2243 2197 (!found || sym.st_value > osym.st_value)) {
2244 2198 osym = sym;
2245 2199 omid = mid;
2246 2200 oid = i;
2247 2201 found = 1;
2248 2202 }
2249 2203
2250 2204 if (addr < sym.st_value)
2251 2205 max = mid - 1;
2252 2206 else
2253 2207 min = mid + 1;
2254 2208 }
2255 2209
2256 2210 if (!found)
2257 2211 return (NULL);
2258 2212
2259 2213 /*
2260 2214 * There may be many symbols with identical values so we walk
2261 2215 * backward in the byaddr table to find the best match.
2262 2216 */
2263 2217 do {
2264 2218 sym = osym;
2265 2219 i = oid;
2266 2220
2267 2221 if (omid == 0)
2268 2222 break;
2269 2223
2270 2224 oid = byaddr[--omid];
2271 2225 (void) symtab_getsym(symtab, oid, &osym);
2272 2226 } while (addr >= osym.st_value &&
2273 2227 addr < sym.st_value + osym.st_size &&
2274 2228 osym.st_value == sym.st_value);
2275 2229
2276 2230 *symp = sym;
2277 2231 if (idp != NULL)
2278 2232 *idp = i;
2279 2233 return (symp);
2280 2234 }
2281 2235
2282 2236 /*
2283 2237 * Use a linear search to do the work of sym_by_addr().
2284 2238 */
2285 2239 static GElf_Sym *
2286 2240 sym_by_addr_linear(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symbolp,
2287 2241 uint_t *idp)
2288 2242 {
2289 2243 size_t symn = symtab->sym_symn;
2290 2244 char *strs = symtab->sym_strs;
2291 2245 GElf_Sym sym, *symp = NULL;
2292 2246 GElf_Sym osym, *osymp = NULL;
2293 2247 int i, id;
2294 2248
2295 2249 if (symtab->sym_data_pri == NULL || symn == 0 || strs == NULL)
2296 2250 return (NULL);
2297 2251
2298 2252 for (i = 0; i < symn; i++) {
2299 2253 if ((symp = symtab_getsym(symtab, i, &sym)) != NULL) {
2300 2254 if (addr >= sym.st_value &&
2301 2255 addr < sym.st_value + sym.st_size) {
2302 2256 if (osymp)
2303 2257 symp = sym_prefer(
2304 2258 symp, strs + symp->st_name,
2305 2259 osymp, strs + osymp->st_name);
2306 2260 if (symp != osymp) {
2307 2261 osym = sym;
2308 2262 osymp = &osym;
2309 2263 id = i;
2310 2264 }
2311 2265 }
2312 2266 }
2313 2267 }
2314 2268 if (osymp) {
2315 2269 *symbolp = osym;
2316 2270 if (idp)
2317 2271 *idp = id;
2318 2272 return (symbolp);
2319 2273 }
2320 2274 return (NULL);
2321 2275 }
2322 2276
2323 2277 /*
2324 2278 * Look up a symbol by address in the specified symbol table.
2325 2279 * Adjustment to 'addr' must already have been made for the
2326 2280 * offset of the symbol if this is a dynamic library symbol table.
2327 2281 *
2328 2282 * Use a linear or a binary search depending on whether or not we
2329 2283 * chose to sort the table in optimize_symtab().
2330 2284 */
2331 2285 static GElf_Sym *
2332 2286 sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp)
2333 2287 {
2334 2288 if (_libproc_no_qsort) {
2335 2289 return (sym_by_addr_linear(symtab, addr, symp, idp));
2336 2290 } else {
2337 2291 return (sym_by_addr_binary(symtab, addr, symp, idp));
2338 2292 }
2339 2293 }
2340 2294
2341 2295 /*
2342 2296 * Use a binary search to do the work of sym_by_name().
2343 2297 */
2344 2298 static GElf_Sym *
2345 2299 sym_by_name_binary(sym_tbl_t *symtab, const char *name, GElf_Sym *symp,
2346 2300 uint_t *idp)
2347 2301 {
2348 2302 char *strs = symtab->sym_strs;
2349 2303 uint_t i, *byname = symtab->sym_byname;
2350 2304 int min, mid, max, cmp;
2351 2305
2352 2306 if (symtab->sym_data_pri == NULL || strs == NULL ||
2353 2307 symtab->sym_count == 0)
2354 2308 return (NULL);
2355 2309
2356 2310 min = 0;
2357 2311 max = symtab->sym_count - 1;
2358 2312
2359 2313 while (min <= max) {
2360 2314 mid = (max + min) / 2;
2361 2315
2362 2316 i = byname[mid];
2363 2317 (void) symtab_getsym(symtab, i, symp);
2364 2318
2365 2319 if ((cmp = strcmp(name, strs + symp->st_name)) == 0) {
2366 2320 if (idp != NULL)
2367 2321 *idp = i;
2368 2322 return (symp);
2369 2323 }
2370 2324
2371 2325 if (cmp < 0)
2372 2326 max = mid - 1;
2373 2327 else
2374 2328 min = mid + 1;
2375 2329 }
2376 2330
2377 2331 return (NULL);
2378 2332 }
2379 2333
2380 2334 /*
2381 2335 * Use a linear search to do the work of sym_by_name().
2382 2336 */
2383 2337 static GElf_Sym *
2384 2338 sym_by_name_linear(sym_tbl_t *symtab, const char *name, GElf_Sym *symp,
2385 2339 uint_t *idp)
2386 2340 {
2387 2341 size_t symn = symtab->sym_symn;
2388 2342 char *strs = symtab->sym_strs;
2389 2343 int i;
2390 2344
2391 2345 if (symtab->sym_data_pri == NULL || symn == 0 || strs == NULL)
2392 2346 return (NULL);
2393 2347
2394 2348 for (i = 0; i < symn; i++) {
2395 2349 if (symtab_getsym(symtab, i, symp) &&
2396 2350 strcmp(name, strs + symp->st_name) == 0) {
2397 2351 if (idp)
2398 2352 *idp = i;
2399 2353 return (symp);
2400 2354 }
2401 2355 }
2402 2356
2403 2357 return (NULL);
2404 2358 }
2405 2359
2406 2360 /*
2407 2361 * Look up a symbol by name in the specified symbol table.
2408 2362 *
2409 2363 * Use a linear or a binary search depending on whether or not we
2410 2364 * chose to sort the table in optimize_symtab().
2411 2365 */
2412 2366 static GElf_Sym *
2413 2367 sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp)
2414 2368 {
2415 2369 if (_libproc_no_qsort) {
2416 2370 return (sym_by_name_linear(symtab, name, symp, idp));
2417 2371 } else {
2418 2372 return (sym_by_name_binary(symtab, name, symp, idp));
2419 2373 }
2420 2374 }
2421 2375
2422 2376 /*
2423 2377 * Search the process symbol tables looking for a symbol whose
2424 2378 * value to value+size contain the address specified by addr.
2425 2379 * Return values are:
2426 2380 * sym_name_buffer containing the symbol name
2427 2381 * GElf_Sym symbol table entry
2428 2382 * prsyminfo_t ancillary symbol information
2429 2383 * Returns 0 on success, -1 on failure.
2430 2384 */
2431 2385 static int
2432 2386 i_Pxlookup_by_addr(
2433 2387 struct ps_prochandle *P,
2434 2388 int lmresolve, /* use resolve linker object names */
2435 2389 uintptr_t addr, /* process address being sought */
2436 2390 char *sym_name_buffer, /* buffer for the symbol name */
2437 2391 size_t bufsize, /* size of sym_name_buffer */
2438 2392 GElf_Sym *symbolp, /* returned symbol table entry */
2439 2393 prsyminfo_t *sip) /* returned symbol info */
2440 2394 {
2441 2395 GElf_Sym *symp;
2442 2396 char *name;
2443 2397 GElf_Sym sym1, *sym1p = NULL;
2444 2398 GElf_Sym sym2, *sym2p = NULL;
2445 2399 char *name1 = NULL;
2446 2400 char *name2 = NULL;
2447 2401 uint_t i1;
2448 2402 uint_t i2;
2449 2403 map_info_t *mptr;
2450 2404 file_info_t *fptr;
2451 2405
2452 2406 (void) Prd_agent(P);
2453 2407
2454 2408 if ((mptr = Paddr2mptr(P, addr)) == NULL || /* no such address */
2455 2409 (fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */
2456 2410 fptr->file_elf == NULL) /* not an ELF file */
2457 2411 return (-1);
2458 2412
2459 2413 /*
2460 2414 * Adjust the address by the load object base address in
2461 2415 * case the address turns out to be in a shared library.
2462 2416 */
2463 2417 addr -= fptr->file_dyn_base;
2464 2418
2465 2419 /*
2466 2420 * Search both symbol tables, symtab first, then dynsym.
2467 2421 */
2468 2422 if ((sym1p = sym_by_addr(&fptr->file_symtab, addr, &sym1, &i1)) != NULL)
2469 2423 name1 = fptr->file_symtab.sym_strs + sym1.st_name;
2470 2424 if ((sym2p = sym_by_addr(&fptr->file_dynsym, addr, &sym2, &i2)) != NULL)
2471 2425 name2 = fptr->file_dynsym.sym_strs + sym2.st_name;
2472 2426
2473 2427 if ((symp = sym_prefer(sym1p, name1, sym2p, name2)) == NULL)
2474 2428 return (-1);
2475 2429
2476 2430 name = (symp == sym1p) ? name1 : name2;
2477 2431 if (bufsize > 0) {
2478 2432 (void) strncpy(sym_name_buffer, name, bufsize);
2479 2433 sym_name_buffer[bufsize - 1] = '\0';
2480 2434 }
2481 2435
2482 2436 *symbolp = *symp;
2483 2437 if (sip != NULL) {
2484 2438 sip->prs_name = bufsize == 0 ? NULL : sym_name_buffer;
2485 2439 if (lmresolve && (fptr->file_rname != NULL))
2486 2440 sip->prs_object = fptr->file_rbase;
2487 2441 else
2488 2442 sip->prs_object = fptr->file_lbase;
2489 2443 sip->prs_id = (symp == sym1p) ? i1 : i2;
2490 2444 sip->prs_table = (symp == sym1p) ? PR_SYMTAB : PR_DYNSYM;
2491 2445 sip->prs_lmid = (fptr->file_lo == NULL) ? LM_ID_BASE :
2492 2446 fptr->file_lo->rl_lmident;
2493 2447 }
2494 2448
2495 2449 if (GELF_ST_TYPE(symbolp->st_info) != STT_TLS)
2496 2450 symbolp->st_value += fptr->file_dyn_base;
2497 2451
2498 2452 return (0);
2499 2453 }
2500 2454
2501 2455 int
2502 2456 Pxlookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf,
2503 2457 size_t bufsize, GElf_Sym *symp, prsyminfo_t *sip)
2504 2458 {
2505 2459 return (i_Pxlookup_by_addr(P, B_FALSE, addr, buf, bufsize, symp, sip));
2506 2460 }
2507 2461
2508 2462 int
2509 2463 Pxlookup_by_addr_resolved(struct ps_prochandle *P, uintptr_t addr, char *buf,
2510 2464 size_t bufsize, GElf_Sym *symp, prsyminfo_t *sip)
2511 2465 {
2512 2466 return (i_Pxlookup_by_addr(P, B_TRUE, addr, buf, bufsize, symp, sip));
2513 2467 }
2514 2468
2515 2469 int
2516 2470 Plookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf,
2517 2471 size_t size, GElf_Sym *symp)
2518 2472 {
2519 2473 return (i_Pxlookup_by_addr(P, B_FALSE, addr, buf, size, symp, NULL));
2520 2474 }
2521 2475
2522 2476 /*
2523 2477 * Search the process symbol tables looking for a symbol whose name matches the
2524 2478 * specified name and whose object and link map optionally match the specified
2525 2479 * parameters. On success, the function returns 0 and fills in the GElf_Sym
2526 2480 * symbol table entry. On failure, -1 is returned.
2527 2481 */
2528 2482 int
2529 2483 Pxlookup_by_name(
2530 2484 struct ps_prochandle *P,
2531 2485 Lmid_t lmid, /* link map to match, or -1 for any */
2532 2486 const char *oname, /* load object name */
2533 2487 const char *sname, /* symbol name */
2534 2488 GElf_Sym *symp, /* returned symbol table entry */
2535 2489 prsyminfo_t *sip) /* returned symbol info */
2536 2490 {
2537 2491 map_info_t *mptr;
2538 2492 file_info_t *fptr;
2539 2493 int cnt;
2540 2494
2541 2495 GElf_Sym sym;
2542 2496 prsyminfo_t si;
2543 2497 int rv = -1;
2544 2498 uint_t id;
2545 2499
2546 2500 if (oname == PR_OBJ_EVERY) {
2547 2501 /* create all the file_info_t's for all the mappings */
2548 2502 (void) Prd_agent(P);
2549 2503 cnt = P->num_files;
2550 2504 fptr = list_next(&P->file_head);
2551 2505 } else {
2552 2506 cnt = 1;
2553 2507 if ((mptr = object_name_to_map(P, lmid, oname)) == NULL ||
2554 2508 (fptr = build_map_symtab(P, mptr)) == NULL)
2555 2509 return (-1);
2556 2510 }
2557 2511
2558 2512 /*
2559 2513 * Iterate through the loaded object files and look for the symbol
2560 2514 * name in the .symtab and .dynsym of each. If we encounter a match
2561 2515 * with SHN_UNDEF, keep looking in hopes of finding a better match.
2562 2516 * This means that a name such as "puts" will match the puts function
2563 2517 * in libc instead of matching the puts PLT entry in the a.out file.
2564 2518 */
2565 2519 for (; cnt > 0; cnt--, fptr = list_next(fptr)) {
2566 2520 Pbuild_file_symtab(P, fptr);
2567 2521
2568 2522 if (fptr->file_elf == NULL)
2569 2523 continue;
2570 2524
2571 2525 if (lmid != PR_LMID_EVERY && fptr->file_lo != NULL &&
2572 2526 lmid != fptr->file_lo->rl_lmident)
2573 2527 continue;
2574 2528
2575 2529 if (fptr->file_symtab.sym_data_pri != NULL &&
2576 2530 sym_by_name(&fptr->file_symtab, sname, symp, &id)) {
2577 2531 if (sip != NULL) {
2578 2532 sip->prs_id = id;
2579 2533 sip->prs_table = PR_SYMTAB;
2580 2534 sip->prs_object = oname;
2581 2535 sip->prs_name = sname;
2582 2536 sip->prs_lmid = fptr->file_lo == NULL ?
2583 2537 LM_ID_BASE : fptr->file_lo->rl_lmident;
2584 2538 }
2585 2539 } else if (fptr->file_dynsym.sym_data_pri != NULL &&
2586 2540 sym_by_name(&fptr->file_dynsym, sname, symp, &id)) {
2587 2541 if (sip != NULL) {
2588 2542 sip->prs_id = id;
2589 2543 sip->prs_table = PR_DYNSYM;
2590 2544 sip->prs_object = oname;
2591 2545 sip->prs_name = sname;
2592 2546 sip->prs_lmid = fptr->file_lo == NULL ?
2593 2547 LM_ID_BASE : fptr->file_lo->rl_lmident;
2594 2548 }
2595 2549 } else {
2596 2550 continue;
2597 2551 }
2598 2552
2599 2553 if (GELF_ST_TYPE(symp->st_info) != STT_TLS)
2600 2554 symp->st_value += fptr->file_dyn_base;
2601 2555
2602 2556 if (symp->st_shndx != SHN_UNDEF)
2603 2557 return (0);
2604 2558
2605 2559 if (rv != 0) {
2606 2560 if (sip != NULL)
2607 2561 si = *sip;
2608 2562 sym = *symp;
2609 2563 rv = 0;
2610 2564 }
2611 2565 }
2612 2566
2613 2567 if (rv == 0) {
2614 2568 if (sip != NULL)
2615 2569 *sip = si;
2616 2570 *symp = sym;
2617 2571 }
2618 2572
2619 2573 return (rv);
2620 2574 }
2621 2575
2622 2576 /*
2623 2577 * Search the process symbol tables looking for a symbol whose name matches the
2624 2578 * specified name, but without any restriction on the link map id.
2625 2579 */
2626 2580 int
2627 2581 Plookup_by_name(struct ps_prochandle *P, const char *object,
2628 2582 const char *symbol, GElf_Sym *symp)
2629 2583 {
2630 2584 return (Pxlookup_by_name(P, PR_LMID_EVERY, object, symbol, symp, NULL));
2631 2585 }
2632 2586
2633 2587 /*
2634 2588 * Iterate over the process's address space mappings.
2635 2589 */
2636 2590 static int
2637 2591 i_Pmapping_iter(struct ps_prochandle *P, boolean_t lmresolve,
2638 2592 proc_map_f *func, void *cd)
2639 2593 {
2640 2594 map_info_t *mptr;
2641 2595 file_info_t *fptr;
2642 2596 char *object_name;
2643 2597 int rc = 0;
2644 2598 int i;
2645 2599
2646 2600 /* create all the file_info_t's for all the mappings */
2647 2601 (void) Prd_agent(P);
2648 2602
2649 2603 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) {
2650 2604 if ((fptr = mptr->map_file) == NULL)
2651 2605 object_name = NULL;
2652 2606 else if (lmresolve && (fptr->file_rname != NULL))
2653 2607 object_name = fptr->file_rname;
2654 2608 else
2655 2609 object_name = fptr->file_lname;
2656 2610 if ((rc = func(cd, &mptr->map_pmap, object_name)) != 0)
2657 2611 return (rc);
2658 2612 }
2659 2613 return (0);
2660 2614 }
2661 2615
2662 2616 int
2663 2617 Pmapping_iter(struct ps_prochandle *P, proc_map_f *func, void *cd)
2664 2618 {
2665 2619 return (i_Pmapping_iter(P, B_FALSE, func, cd));
2666 2620 }
2667 2621
2668 2622 int
2669 2623 Pmapping_iter_resolved(struct ps_prochandle *P, proc_map_f *func, void *cd)
2670 2624 {
2671 2625 return (i_Pmapping_iter(P, B_TRUE, func, cd));
2672 2626 }
2673 2627
2674 2628 /*
2675 2629 * Iterate over the process's mapped objects.
2676 2630 */
2677 2631 static int
2678 2632 i_Pobject_iter(struct ps_prochandle *P, boolean_t lmresolve,
2679 2633 proc_map_f *func, void *cd)
2680 2634 {
2681 2635 map_info_t *mptr;
2682 2636 file_info_t *fptr;
2683 2637 uint_t cnt;
2684 2638 int rc = 0;
2685 2639
2686 2640 (void) Prd_agent(P); /* create file_info_t's for all the mappings */
2687 2641 Pupdate_maps(P);
2688 2642
2689 2643 for (cnt = P->num_files, fptr = list_next(&P->file_head);
2690 2644 cnt; cnt--, fptr = list_next(fptr)) {
2691 2645 const char *lname;
2692 2646
2693 2647 if (lmresolve && (fptr->file_rname != NULL))
2694 2648 lname = fptr->file_rname;
2695 2649 else if (fptr->file_lname != NULL)
2696 2650 lname = fptr->file_lname;
2697 2651 else
2698 2652 lname = "";
2699 2653
2700 2654 if ((mptr = fptr->file_map) == NULL)
2701 2655 continue;
2702 2656
2703 2657 if ((rc = func(cd, &mptr->map_pmap, lname)) != 0)
2704 2658 return (rc);
2705 2659
2706 2660 if (!P->info_valid)
2707 2661 Pupdate_maps(P);
2708 2662 }
2709 2663 return (0);
2710 2664 }
2711 2665
2712 2666 int
2713 2667 Pobject_iter(struct ps_prochandle *P, proc_map_f *func, void *cd)
2714 2668 {
2715 2669 return (i_Pobject_iter(P, B_FALSE, func, cd));
2716 2670 }
2717 2671
2718 2672 int
2719 2673 Pobject_iter_resolved(struct ps_prochandle *P, proc_map_f *func, void *cd)
2720 2674 {
2721 2675 return (i_Pobject_iter(P, B_TRUE, func, cd));
2722 2676 }
2723 2677
2724 2678 static char *
2725 2679 i_Pobjname(struct ps_prochandle *P, boolean_t lmresolve, uintptr_t addr,
2726 2680 char *buffer, size_t bufsize)
2727 2681 {
2728 2682 map_info_t *mptr;
2729 2683 file_info_t *fptr;
2730 2684
2731 2685 /* create all the file_info_t's for all the mappings */
2732 2686 (void) Prd_agent(P);
2733 2687
2734 2688 if ((mptr = Paddr2mptr(P, addr)) == NULL)
2735 2689 return (NULL);
2736 2690
2737 2691 if (!lmresolve) {
2738 2692 if (((fptr = mptr->map_file) == NULL) ||
2739 2693 (fptr->file_lname == NULL))
2740 2694 return (NULL);
2741 2695 (void) strlcpy(buffer, fptr->file_lname, bufsize);
2742 2696 return (buffer);
2743 2697 }
2744 2698
2745 2699 /* Check for a cached copy of the resolved path */
2746 2700 if (Pfindmap(P, mptr, buffer, bufsize) != NULL)
2747 2701 return (buffer);
2748 2702
2749 2703 return (NULL);
2750 2704 }
2751 2705
2752 2706 /*
2753 2707 * Given a virtual address, return the name of the underlying
2754 2708 * mapped object (file) as provided by the dynamic linker.
2755 2709 * Return NULL if we can't find any name information for the object.
2756 2710 */
2757 2711 char *
2758 2712 Pobjname(struct ps_prochandle *P, uintptr_t addr,
2759 2713 char *buffer, size_t bufsize)
2760 2714 {
2761 2715 return (i_Pobjname(P, B_FALSE, addr, buffer, bufsize));
2762 2716 }
2763 2717
2764 2718 /*
2765 2719 * Given a virtual address, try to return a filesystem path to the
2766 2720 * underlying mapped object (file). If we're in the global zone,
2767 2721 * this path could resolve to an object in another zone. If we're
2768 2722 * unable return a valid filesystem path, we'll fall back to providing
2769 2723 * the mapped object (file) name provided by the dynamic linker in
2770 2724 * the target process (ie, the object reported by Pobjname()).
2771 2725 */
2772 2726 char *
2773 2727 Pobjname_resolved(struct ps_prochandle *P, uintptr_t addr,
2774 2728 char *buffer, size_t bufsize)
2775 2729 {
2776 2730 return (i_Pobjname(P, B_TRUE, addr, buffer, bufsize));
2777 2731 }
2778 2732
2779 2733 /*
2780 2734 * Given a virtual address, return the link map id of the underlying mapped
2781 2735 * object (file), as provided by the dynamic linker. Return -1 on failure.
2782 2736 */
2783 2737 int
2784 2738 Plmid(struct ps_prochandle *P, uintptr_t addr, Lmid_t *lmidp)
2785 2739 {
2786 2740 map_info_t *mptr;
2787 2741 file_info_t *fptr;
2788 2742
2789 2743 /* create all the file_info_t's for all the mappings */
2790 2744 (void) Prd_agent(P);
2791 2745
2792 2746 if ((mptr = Paddr2mptr(P, addr)) != NULL &&
2793 2747 (fptr = mptr->map_file) != NULL && fptr->file_lo != NULL) {
2794 2748 *lmidp = fptr->file_lo->rl_lmident;
2795 2749 return (0);
2796 2750 }
2797 2751
2798 2752 return (-1);
2799 2753 }
2800 2754
2801 2755 /*
2802 2756 * Given an object name and optional lmid, iterate over the object's symbols.
2803 2757 * If which == PR_SYMTAB, search the normal symbol table.
2804 2758 * If which == PR_DYNSYM, search the dynamic symbol table.
2805 2759 */
2806 2760 static int
2807 2761 Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
2808 2762 int which, int mask, pr_order_t order, proc_xsym_f *func, void *cd)
2809 2763 {
2810 2764 #if STT_NUM != (STT_TLS + 1)
2811 2765 #error "STT_NUM has grown. update Psymbol_iter_com()"
2812 2766 #endif
2813 2767
2814 2768 GElf_Sym sym;
2815 2769 GElf_Shdr shdr;
2816 2770 map_info_t *mptr;
2817 2771 file_info_t *fptr;
2818 2772 sym_tbl_t *symtab;
2819 2773 size_t symn;
2820 2774 const char *strs;
2821 2775 size_t strsz;
2822 2776 prsyminfo_t si;
2823 2777 int rv;
2824 2778 uint_t *map, i, count, ndx;
2825 2779
2826 2780 if ((mptr = object_name_to_map(P, lmid, object_name)) == NULL)
2827 2781 return (-1);
2828 2782
2829 2783 if ((fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */
2830 2784 fptr->file_elf == NULL) /* not an ELF file */
2831 2785 return (-1);
2832 2786
2833 2787 /*
2834 2788 * Search the specified symbol table.
2835 2789 */
2836 2790 switch (which) {
2837 2791 case PR_SYMTAB:
2838 2792 symtab = &fptr->file_symtab;
2839 2793 si.prs_table = PR_SYMTAB;
2840 2794 break;
2841 2795 case PR_DYNSYM:
2842 2796 symtab = &fptr->file_dynsym;
2843 2797 si.prs_table = PR_DYNSYM;
2844 2798 break;
2845 2799 default:
2846 2800 return (-1);
2847 2801 }
2848 2802
2849 2803 si.prs_object = object_name;
2850 2804 si.prs_lmid = fptr->file_lo == NULL ?
2851 2805 LM_ID_BASE : fptr->file_lo->rl_lmident;
2852 2806
2853 2807 symn = symtab->sym_symn;
2854 2808 strs = symtab->sym_strs;
2855 2809 strsz = symtab->sym_strsz;
2856 2810
2857 2811 switch (order) {
2858 2812 case PRO_NATURAL:
2859 2813 map = NULL;
2860 2814 count = symn;
2861 2815 break;
2862 2816 case PRO_BYNAME:
2863 2817 map = symtab->sym_byname;
2864 2818 count = symtab->sym_count;
2865 2819 break;
2866 2820 case PRO_BYADDR:
2867 2821 map = symtab->sym_byaddr;
2868 2822 count = symtab->sym_count;
2869 2823 break;
2870 2824 default:
2871 2825 return (-1);
2872 2826 }
2873 2827
2874 2828 if (symtab->sym_data_pri == NULL || strs == NULL || count == 0)
2875 2829 return (-1);
2876 2830
2877 2831 rv = 0;
2878 2832
2879 2833 for (i = 0; i < count; i++) {
2880 2834 ndx = map == NULL ? i : map[i];
2881 2835 if (symtab_getsym(symtab, ndx, &sym) != NULL) {
2882 2836 uint_t s_bind, s_type, type;
2883 2837
2884 2838 if (sym.st_name >= strsz) /* invalid st_name */
2885 2839 continue;
2886 2840
2887 2841 s_bind = GELF_ST_BIND(sym.st_info);
2888 2842 s_type = GELF_ST_TYPE(sym.st_info);
2889 2843
2890 2844 /*
2891 2845 * In case you haven't already guessed, this relies on
2892 2846 * the bitmask used in <libproc.h> for encoding symbol
2893 2847 * type and binding matching the order of STB and STT
2894 2848 * constants in <sys/elf.h>. Changes to ELF must
2895 2849 * maintain binary compatibility, so I think this is
2896 2850 * reasonably fair game.
2897 2851 */
2898 2852 if (s_bind < STB_NUM && s_type < STT_NUM) {
2899 2853 type = (1 << (s_type + 8)) | (1 << s_bind);
2900 2854 if ((type & ~mask) != 0)
2901 2855 continue;
2902 2856 } else
2903 2857 continue; /* Invalid type or binding */
2904 2858
2905 2859 if (GELF_ST_TYPE(sym.st_info) != STT_TLS)
2906 2860 sym.st_value += fptr->file_dyn_base;
2907 2861
2908 2862 si.prs_name = strs + sym.st_name;
2909 2863
2910 2864 /*
2911 2865 * If symbol's type is STT_SECTION, then try to lookup
2912 2866 * the name of the corresponding section.
2913 2867 */
2914 2868 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
2915 2869 fptr->file_shstrs != NULL &&
2916 2870 gelf_getshdr(elf_getscn(fptr->file_elf,
2917 2871 sym.st_shndx), &shdr) != NULL &&
2918 2872 shdr.sh_name != 0 &&
2919 2873 shdr.sh_name < fptr->file_shstrsz)
2920 2874 si.prs_name = fptr->file_shstrs + shdr.sh_name;
2921 2875
2922 2876 si.prs_id = ndx;
2923 2877 if ((rv = func(cd, &sym, si.prs_name, &si)) != 0)
2924 2878 break;
2925 2879 }
2926 2880 }
2927 2881
2928 2882 return (rv);
2929 2883 }
2930 2884
2931 2885 int
2932 2886 Pxsymbol_iter(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
2933 2887 int which, int mask, proc_xsym_f *func, void *cd)
2934 2888 {
2935 2889 return (Psymbol_iter_com(P, lmid, object_name, which, mask,
2936 2890 PRO_NATURAL, func, cd));
2937 2891 }
2938 2892
2939 2893 int
2940 2894 Psymbol_iter_by_lmid(struct ps_prochandle *P, Lmid_t lmid,
2941 2895 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2942 2896 {
2943 2897 return (Psymbol_iter_com(P, lmid, object_name, which, mask,
2944 2898 PRO_NATURAL, (proc_xsym_f *)func, cd));
2945 2899 }
2946 2900
2947 2901 int
2948 2902 Psymbol_iter(struct ps_prochandle *P,
2949 2903 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2950 2904 {
2951 2905 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2952 2906 PRO_NATURAL, (proc_xsym_f *)func, cd));
2953 2907 }
2954 2908
2955 2909 int
2956 2910 Psymbol_iter_by_addr(struct ps_prochandle *P,
2957 2911 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2958 2912 {
2959 2913 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2960 2914 PRO_BYADDR, (proc_xsym_f *)func, cd));
2961 2915 }
↓ open down ↓ |
1265 lines elided |
↑ open up ↑ |
2962 2916
2963 2917 int
2964 2918 Psymbol_iter_by_name(struct ps_prochandle *P,
2965 2919 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2966 2920 {
2967 2921 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2968 2922 PRO_BYNAME, (proc_xsym_f *)func, cd));
2969 2923 }
2970 2924
2971 2925 /*
2972 - * Get the platform string from the core file if we have it;
2973 - * just perform the system call for the caller if this is a live process.
2926 + * Get the platform string.
2974 2927 */
2975 2928 char *
2976 2929 Pplatform(struct ps_prochandle *P, char *s, size_t n)
2977 2930 {
2978 - if (P->state == PS_IDLE) {
2979 - errno = ENODATA;
2980 - return (NULL);
2981 - }
2982 -
2983 - if (P->state == PS_DEAD) {
2984 - if (P->core->core_platform == NULL) {
2985 - errno = ENODATA;
2986 - return (NULL);
2987 - }
2988 - (void) strncpy(s, P->core->core_platform, n - 1);
2989 - s[n - 1] = '\0';
2990 -
2991 - } else if (sysinfo(SI_PLATFORM, s, n) == -1)
2992 - return (NULL);
2993 -
2994 - return (s);
2931 + return (P->ops.pop_platform(P, s, n, P->data));
2995 2932 }
2996 2933
2997 2934 /*
2998 - * Get the uname(2) information from the core file if we have it;
2999 - * just perform the system call for the caller if this is a live process.
2935 + * Get the uname(2) information.
3000 2936 */
3001 2937 int
3002 2938 Puname(struct ps_prochandle *P, struct utsname *u)
3003 2939 {
3004 - if (P->state == PS_IDLE) {
3005 - errno = ENODATA;
3006 - return (-1);
3007 - }
3008 -
3009 - if (P->state == PS_DEAD) {
3010 - if (P->core->core_uts == NULL) {
3011 - errno = ENODATA;
3012 - return (-1);
3013 - }
3014 - (void) memcpy(u, P->core->core_uts, sizeof (struct utsname));
3015 - return (0);
3016 - }
3017 - return (uname(u));
2940 + return (P->ops.pop_uname(P, u, P->data));
3018 2941 }
3019 2942
3020 2943 /*
3021 2944 * Called from Pcreate(), Pgrab(), and Pfgrab_core() to initialize
3022 2945 * the symbol table heads in the new ps_prochandle.
3023 2946 */
3024 2947 void
3025 2948 Pinitsym(struct ps_prochandle *P)
3026 2949 {
3027 2950 P->num_files = 0;
3028 2951 list_link(&P->file_head, NULL);
3029 2952 }
3030 2953
3031 2954 /*
3032 2955 * Called from Prelease() to destroy the symbol tables.
3033 2956 * Must be called by the client after an exec() in the victim process.
3034 2957 */
3035 2958 void
3036 2959 Preset_maps(struct ps_prochandle *P)
3037 2960 {
3038 2961 int i;
3039 2962
3040 2963 if (P->rap != NULL) {
3041 2964 rd_delete(P->rap);
3042 2965 P->rap = NULL;
3043 2966 }
3044 2967
3045 2968 if (P->execname != NULL) {
3046 2969 free(P->execname);
3047 2970 P->execname = NULL;
3048 2971 }
3049 2972
3050 2973 if (P->auxv != NULL) {
3051 2974 free(P->auxv);
3052 2975 P->auxv = NULL;
3053 2976 P->nauxv = 0;
3054 2977 }
3055 2978
3056 2979 for (i = 0; i < P->map_count; i++)
3057 2980 map_info_free(P, &P->mappings[i]);
3058 2981
3059 2982 if (P->mappings != NULL) {
3060 2983 free(P->mappings);
3061 2984 P->mappings = NULL;
3062 2985 }
3063 2986 P->map_count = P->map_alloc = 0;
3064 2987
3065 2988 P->info_valid = 0;
3066 2989 }
3067 2990
3068 2991 typedef struct getenv_data {
3069 2992 char *buf;
3070 2993 size_t bufsize;
3071 2994 const char *search;
3072 2995 size_t searchlen;
3073 2996 } getenv_data_t;
3074 2997
3075 2998 /*ARGSUSED*/
3076 2999 static int
3077 3000 getenv_func(void *data, struct ps_prochandle *P, uintptr_t addr,
3078 3001 const char *nameval)
3079 3002 {
3080 3003 getenv_data_t *d = data;
3081 3004 size_t len;
3082 3005
3083 3006 if (nameval == NULL)
3084 3007 return (0);
3085 3008
3086 3009 if (d->searchlen < strlen(nameval) &&
3087 3010 strncmp(nameval, d->search, d->searchlen) == 0 &&
3088 3011 nameval[d->searchlen] == '=') {
3089 3012 len = MIN(strlen(nameval), d->bufsize - 1);
3090 3013 (void) strncpy(d->buf, nameval, len);
3091 3014 d->buf[len] = '\0';
3092 3015 return (1);
3093 3016 }
3094 3017
3095 3018 return (0);
3096 3019 }
3097 3020
3098 3021 char *
3099 3022 Pgetenv(struct ps_prochandle *P, const char *name, char *buf, size_t buflen)
3100 3023 {
3101 3024 getenv_data_t d;
3102 3025
3103 3026 d.buf = buf;
3104 3027 d.bufsize = buflen;
3105 3028 d.search = name;
3106 3029 d.searchlen = strlen(name);
3107 3030
3108 3031 if (Penv_iter(P, getenv_func, &d) == 1) {
3109 3032 char *equals = strchr(d.buf, '=');
3110 3033
3111 3034 if (equals != NULL) {
3112 3035 (void) memmove(d.buf, equals + 1,
3113 3036 d.buf + buflen - equals - 1);
3114 3037 d.buf[d.buf + buflen - equals] = '\0';
3115 3038
3116 3039 return (buf);
3117 3040 }
3118 3041 }
3119 3042
3120 3043 return (NULL);
3121 3044 }
3122 3045
3123 3046 /* number of argument or environment pointers to read all at once */
3124 3047 #define NARG 100
3125 3048
3126 3049 int
3127 3050 Penv_iter(struct ps_prochandle *P, proc_env_f *func, void *data)
3128 3051 {
3129 3052 const psinfo_t *psp;
3130 3053 uintptr_t envpoff;
3131 3054 GElf_Sym sym;
3132 3055 int ret;
3133 3056 char *buf, *nameval;
3134 3057 size_t buflen;
3135 3058
3136 3059 int nenv = NARG;
3137 3060 long envp[NARG];
3138 3061
3139 3062 /*
3140 3063 * Attempt to find the "_environ" variable in the process.
3141 3064 * Failing that, use the original value provided by Ppsinfo().
3142 3065 */
3143 3066 if ((psp = Ppsinfo(P)) == NULL)
3144 3067 return (-1);
3145 3068
3146 3069 envpoff = psp->pr_envp; /* Default if no _environ found */
3147 3070
3148 3071 if (Plookup_by_name(P, PR_OBJ_EXEC, "_environ", &sym) == 0) {
3149 3072 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
3150 3073 if (Pread(P, &envpoff, sizeof (envpoff),
3151 3074 sym.st_value) != sizeof (envpoff))
3152 3075 envpoff = psp->pr_envp;
3153 3076 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) {
3154 3077 uint32_t envpoff32;
3155 3078
3156 3079 if (Pread(P, &envpoff32, sizeof (envpoff32),
3157 3080 sym.st_value) != sizeof (envpoff32))
3158 3081 envpoff = psp->pr_envp;
3159 3082 else
3160 3083 envpoff = envpoff32;
3161 3084 }
3162 3085 }
3163 3086
3164 3087 buflen = 128;
3165 3088 buf = malloc(buflen);
3166 3089
3167 3090 ret = 0;
3168 3091 for (;;) {
3169 3092 uintptr_t envoff;
3170 3093
3171 3094 if (nenv == NARG) {
3172 3095 (void) memset(envp, 0, sizeof (envp));
3173 3096 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
3174 3097 if (Pread(P, envp,
3175 3098 sizeof (envp), envpoff) <= 0) {
3176 3099 ret = -1;
3177 3100 break;
3178 3101 }
3179 3102 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) {
3180 3103 uint32_t e32[NARG];
3181 3104 int i;
3182 3105
3183 3106 (void) memset(e32, 0, sizeof (e32));
3184 3107 if (Pread(P, e32, sizeof (e32), envpoff) <= 0) {
3185 3108 ret = -1;
3186 3109 break;
3187 3110 }
3188 3111 for (i = 0; i < NARG; i++)
3189 3112 envp[i] = e32[i];
3190 3113 }
3191 3114 nenv = 0;
3192 3115 }
3193 3116
3194 3117 if ((envoff = envp[nenv++]) == NULL)
3195 3118 break;
3196 3119
3197 3120 /*
3198 3121 * Attempt to read the string from the process.
3199 3122 */
3200 3123 again:
3201 3124 ret = Pread_string(P, buf, buflen, envoff);
3202 3125
3203 3126 if (ret <= 0) {
3204 3127 nameval = NULL;
3205 3128 } else if (ret == buflen - 1) {
3206 3129 free(buf);
3207 3130 /*
3208 3131 * Bail if we have a corrupted environment
3209 3132 */
3210 3133 if (buflen >= ARG_MAX)
3211 3134 return (-1);
3212 3135 buflen *= 2;
3213 3136 buf = malloc(buflen);
3214 3137 goto again;
3215 3138 } else {
3216 3139 nameval = buf;
3217 3140 }
3218 3141
3219 3142 if ((ret = func(data, P, envoff, nameval)) != 0)
3220 3143 break;
3221 3144
3222 3145 envpoff += (P->status.pr_dmodel == PR_MODEL_LP64)? 8 : 4;
3223 3146 }
3224 3147
3225 3148 free(buf);
3226 3149
3227 3150 return (ret);
3228 3151 }
↓ open down ↓ |
201 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX