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