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