dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libproc / common / Psymtab.c
blob4f38d4cc3083934d0ff3bcc9631ab5e9b26ff0ff
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013 by Delphix. All rights reserved.
25 * Copyright 2016 Joyent, Inc.
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <memory.h>
38 #include <errno.h>
39 #include <dirent.h>
40 #include <signal.h>
41 #include <limits.h>
42 #include <libgen.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <sys/sysmacros.h>
47 #include "libproc.h"
48 #include "Pcontrol.h"
49 #include "Putil.h"
50 #include "Psymtab_machelf.h"
52 static file_info_t *build_map_symtab(struct ps_prochandle *, map_info_t *);
53 static map_info_t *exec_map(struct ps_prochandle *);
54 static map_info_t *object_to_map(struct ps_prochandle *, Lmid_t, const char *);
55 static map_info_t *object_name_to_map(struct ps_prochandle *,
56 Lmid_t, const char *);
57 static GElf_Sym *sym_by_name(sym_tbl_t *, const char *, GElf_Sym *, uint_t *);
58 static int read_ehdr32(struct ps_prochandle *, Elf32_Ehdr *, uint_t *,
59 uintptr_t);
60 #ifdef _LP64
61 static int read_ehdr64(struct ps_prochandle *, Elf64_Ehdr *, uint_t *,
62 uintptr_t);
63 #endif
65 #define DATA_TYPES \
66 ((1 << STT_OBJECT) | (1 << STT_FUNC) | \
67 (1 << STT_COMMON) | (1 << STT_TLS))
68 #define IS_DATA_TYPE(tp) (((1 << (tp)) & DATA_TYPES) != 0)
70 #define MA_RWX (MA_READ | MA_WRITE | MA_EXEC)
72 typedef enum {
73 PRO_NATURAL,
74 PRO_BYADDR,
75 PRO_BYNAME
76 } pr_order_t;
78 static int
79 addr_cmp(const void *aa, const void *bb)
81 uintptr_t a = *((uintptr_t *)aa);
82 uintptr_t b = *((uintptr_t *)bb);
84 if (a > b)
85 return (1);
86 if (a < b)
87 return (-1);
88 return (0);
92 * This function creates a list of addresses for a load object's sections.
93 * The list is in ascending address order and alternates start address
94 * then end address for each section we're interested in. The function
95 * returns a pointer to the list, which must be freed by the caller.
97 static uintptr_t *
98 get_saddrs(struct ps_prochandle *P, uintptr_t ehdr_start, uint_t *n)
100 uintptr_t a, addr, *addrs, last = 0;
101 uint_t i, naddrs = 0, unordered = 0;
103 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
104 Elf32_Ehdr ehdr;
105 Elf32_Phdr phdr;
106 uint_t phnum;
108 if (read_ehdr32(P, &ehdr, &phnum, ehdr_start) != 0)
109 return (NULL);
111 addrs = malloc(sizeof (uintptr_t) * phnum * 2);
112 a = ehdr_start + ehdr.e_phoff;
113 for (i = 0; i < phnum; i++, a += ehdr.e_phentsize) {
114 if (Pread(P, &phdr, sizeof (phdr), a) !=
115 sizeof (phdr)) {
116 free(addrs);
117 return (NULL);
119 if (phdr.p_type != PT_LOAD || phdr.p_memsz == 0)
120 continue;
122 addr = phdr.p_vaddr;
123 if (ehdr.e_type == ET_DYN)
124 addr += ehdr_start;
125 if (last > addr)
126 unordered = 1;
127 addrs[naddrs++] = addr;
128 addrs[naddrs++] = last = addr + phdr.p_memsz - 1;
130 #ifdef _LP64
131 } else {
132 Elf64_Ehdr ehdr;
133 Elf64_Phdr phdr;
134 uint_t phnum;
136 if (read_ehdr64(P, &ehdr, &phnum, ehdr_start) != 0)
137 return (NULL);
139 addrs = malloc(sizeof (uintptr_t) * phnum * 2);
140 a = ehdr_start + ehdr.e_phoff;
141 for (i = 0; i < phnum; i++, a += ehdr.e_phentsize) {
142 if (Pread(P, &phdr, sizeof (phdr), a) !=
143 sizeof (phdr)) {
144 free(addrs);
145 return (NULL);
147 if (phdr.p_type != PT_LOAD || phdr.p_memsz == 0)
148 continue;
150 addr = phdr.p_vaddr;
151 if (ehdr.e_type == ET_DYN)
152 addr += ehdr_start;
153 if (last > addr)
154 unordered = 1;
155 addrs[naddrs++] = addr;
156 addrs[naddrs++] = last = addr + phdr.p_memsz - 1;
158 #endif
161 if (unordered)
162 qsort(addrs, naddrs, sizeof (uintptr_t), addr_cmp);
164 *n = naddrs;
165 return (addrs);
169 * Allocation function for a new file_info_t
171 file_info_t *
172 file_info_new(struct ps_prochandle *P, map_info_t *mptr)
174 file_info_t *fptr;
175 map_info_t *mp;
176 uintptr_t mstart, mend, sstart, send;
177 uint_t i;
179 if ((fptr = calloc(1, sizeof (file_info_t))) == NULL)
180 return (NULL);
182 list_link(fptr, &P->file_head);
183 (void) strcpy(fptr->file_pname, mptr->map_pmap.pr_mapname);
184 mptr->map_file = fptr;
185 fptr->file_ref = 1;
186 fptr->file_fd = -1;
187 P->num_files++;
190 * To figure out which map_info_t instances correspond to the mappings
191 * for this load object we try to obtain the start and end address
192 * for each section of our in-memory ELF image. If successful, we
193 * walk down the list of addresses and the list of map_info_t
194 * instances in lock step to correctly find the mappings that
195 * correspond to this load object.
197 if ((fptr->file_saddrs = get_saddrs(P, mptr->map_pmap.pr_vaddr,
198 &fptr->file_nsaddrs)) == NULL)
199 return (fptr);
201 mp = P->mappings;
202 i = 0;
203 while (mp < P->mappings + P->map_count && i < fptr->file_nsaddrs) {
205 /* Calculate the start and end of the mapping and section */
206 mstart = mp->map_pmap.pr_vaddr;
207 mend = mp->map_pmap.pr_vaddr + mp->map_pmap.pr_size;
208 sstart = fptr->file_saddrs[i];
209 send = fptr->file_saddrs[i + 1];
211 if (mend <= sstart) {
212 /* This mapping is below the current section */
213 mp++;
214 } else if (mstart >= send) {
215 /* This mapping is above the current section */
216 i += 2;
217 } else {
218 /* This mapping overlaps the current section */
219 if (mp->map_file == NULL) {
220 dprintf("file_info_new: associating "
221 "segment at %p\n",
222 (void *)mp->map_pmap.pr_vaddr);
223 mp->map_file = fptr;
224 fptr->file_ref++;
225 } else {
226 dprintf("file_info_new: segment at %p "
227 "already associated with %s\n",
228 (void *)mp->map_pmap.pr_vaddr,
229 (mp == mptr ? "this file" :
230 mp->map_file->file_pname));
232 mp++;
236 return (fptr);
240 * Deallocation function for a file_info_t
242 static void
243 file_info_free(struct ps_prochandle *P, file_info_t *fptr)
245 if (--fptr->file_ref == 0) {
246 list_unlink(fptr);
247 if (fptr->file_symtab.sym_elf) {
248 (void) elf_end(fptr->file_symtab.sym_elf);
249 free(fptr->file_symtab.sym_elfmem);
251 free(fptr->file_symtab.sym_byname);
252 free(fptr->file_symtab.sym_byaddr);
254 if (fptr->file_dynsym.sym_elf) {
255 (void) elf_end(fptr->file_dynsym.sym_elf);
256 free(fptr->file_dynsym.sym_elfmem);
258 free(fptr->file_dynsym.sym_byname);
259 free(fptr->file_dynsym.sym_byaddr);
261 free(fptr->file_lo);
262 free(fptr->file_lname);
263 free(fptr->file_rname);
264 if (fptr->file_elf)
265 (void) elf_end(fptr->file_elf);
266 free(fptr->file_elfmem);
267 if (fptr->file_fd >= 0)
268 (void) close(fptr->file_fd);
269 if (fptr->file_ctfp) {
270 ctf_close(fptr->file_ctfp);
271 free(fptr->file_ctf_buf);
273 free(fptr->file_saddrs);
274 free(fptr);
275 P->num_files--;
280 * Deallocation function for a map_info_t
282 static void
283 map_info_free(struct ps_prochandle *P, map_info_t *mptr)
285 file_info_t *fptr;
287 if ((fptr = mptr->map_file) != NULL) {
288 if (fptr->file_map == mptr)
289 fptr->file_map = NULL;
290 file_info_free(P, fptr);
292 if (P->execname && mptr == P->map_exec) {
293 free(P->execname);
294 P->execname = NULL;
296 if (P->auxv && (mptr == P->map_exec || mptr == P->map_ldso)) {
297 free(P->auxv);
298 P->auxv = NULL;
299 P->nauxv = 0;
301 if (mptr == P->map_exec)
302 P->map_exec = NULL;
303 if (mptr == P->map_ldso)
304 P->map_ldso = NULL;
308 * Call-back function for librtld_db to iterate through all of its shared
309 * libraries. We use this to get the load object names for the mappings.
311 static int
312 map_iter(const rd_loadobj_t *lop, void *cd)
314 char buf[PATH_MAX];
315 struct ps_prochandle *P = cd;
316 map_info_t *mptr;
317 file_info_t *fptr;
319 dprintf("encountered rd object at %p\n", (void *)lop->rl_base);
321 if ((mptr = Paddr2mptr(P, lop->rl_base)) == NULL) {
322 dprintf("map_iter: base address doesn't match any mapping\n");
323 return (1); /* Base address does not match any mapping */
326 if ((fptr = mptr->map_file) == NULL &&
327 (fptr = file_info_new(P, mptr)) == NULL) {
328 dprintf("map_iter: failed to allocate a new file_info_t\n");
329 return (1); /* Failed to allocate a new file_info_t */
332 if ((fptr->file_lo == NULL) &&
333 (fptr->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) {
334 dprintf("map_iter: failed to allocate rd_loadobj_t\n");
335 file_info_free(P, fptr);
336 return (1); /* Failed to allocate rd_loadobj_t */
339 fptr->file_map = mptr;
340 *fptr->file_lo = *lop;
342 fptr->file_lo->rl_plt_base = fptr->file_plt_base;
343 fptr->file_lo->rl_plt_size = fptr->file_plt_size;
345 if (fptr->file_lname) {
346 free(fptr->file_lname);
347 fptr->file_lname = NULL;
348 fptr->file_lbase = NULL;
350 if (fptr->file_rname) {
351 free(fptr->file_rname);
352 fptr->file_rname = NULL;
353 fptr->file_rbase = NULL;
356 if (Pread_string(P, buf, sizeof (buf), lop->rl_nameaddr) > 0) {
357 if ((fptr->file_lname = strdup(buf)) != NULL)
358 fptr->file_lbase = basename(fptr->file_lname);
359 } else {
360 dprintf("map_iter: failed to read string at %p\n",
361 (void *)lop->rl_nameaddr);
364 if ((Pfindmap(P, mptr, buf, sizeof (buf)) != NULL) &&
365 ((fptr->file_rname = strdup(buf)) != NULL))
366 fptr->file_rbase = basename(fptr->file_rname);
368 dprintf("loaded rd object %s lmid %lx\n",
369 fptr->file_lname ? buf : "<NULL>", lop->rl_lmident);
370 return (1);
373 static void
374 map_set(struct ps_prochandle *P, map_info_t *mptr, const char *lname)
376 file_info_t *fptr;
377 char buf[PATH_MAX];
379 if ((fptr = mptr->map_file) == NULL &&
380 (fptr = file_info_new(P, mptr)) == NULL)
381 return; /* Failed to allocate a new file_info_t */
383 fptr->file_map = mptr;
385 if ((fptr->file_lo == NULL) &&
386 (fptr->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) {
387 file_info_free(P, fptr);
388 return; /* Failed to allocate rd_loadobj_t */
391 (void) memset(fptr->file_lo, 0, sizeof (rd_loadobj_t));
392 fptr->file_lo->rl_base = mptr->map_pmap.pr_vaddr;
393 fptr->file_lo->rl_bend =
394 mptr->map_pmap.pr_vaddr + mptr->map_pmap.pr_size;
396 fptr->file_lo->rl_plt_base = fptr->file_plt_base;
397 fptr->file_lo->rl_plt_size = fptr->file_plt_size;
399 if ((fptr->file_lname == NULL) &&
400 (fptr->file_lname = strdup(lname)) != NULL)
401 fptr->file_lbase = basename(fptr->file_lname);
403 if ((Pfindmap(P, mptr, buf, sizeof (buf)) != NULL) &&
404 ((fptr->file_rname = strdup(buf)) != NULL))
405 fptr->file_rbase = basename(fptr->file_rname);
408 static void
409 load_static_maps(struct ps_prochandle *P)
411 map_info_t *mptr;
414 * Construct the map for the a.out.
416 if ((mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_EXEC)) != NULL)
417 map_set(P, mptr, "a.out");
420 * If the dynamic linker exists for this process,
421 * construct the map for it.
423 if (Pgetauxval(P, AT_BASE) != -1L &&
424 (mptr = object_name_to_map(P, PR_LMID_EVERY, PR_OBJ_LDSO)) != NULL)
425 map_set(P, mptr, "ld.so.1");
429 Preadmaps(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp)
431 return (P->ops.pop_read_maps(P, Pmapp, nmapp, P->data));
435 * Go through all the address space mappings, validating or updating
436 * the information already gathered, or gathering new information.
438 * This function is only called when we suspect that the mappings have changed
439 * because this is the first time we're calling it or because of rtld activity.
441 void
442 Pupdate_maps(struct ps_prochandle *P)
444 prmap_t *Pmap = NULL;
445 prmap_t *pmap;
446 ssize_t nmap;
447 int i;
448 uint_t oldmapcount;
449 map_info_t *newmap, *newp;
450 map_info_t *mptr;
452 if (P->info_valid || P->state == PS_UNDEAD)
453 return;
455 Preadauxvec(P);
457 if (Preadmaps(P, &Pmap, &nmap) != 0)
458 return;
460 if ((newmap = calloc(1, nmap * sizeof (map_info_t))) == NULL)
461 return;
464 * We try to merge any file information we may have for existing
465 * mappings, to avoid having to rebuild the file info.
467 mptr = P->mappings;
468 pmap = Pmap;
469 newp = newmap;
470 oldmapcount = P->map_count;
471 for (i = 0; i < nmap; i++, pmap++, newp++) {
473 if (oldmapcount == 0) {
475 * We've exhausted all the old mappings. Every new
476 * mapping should be added.
478 newp->map_pmap = *pmap;
480 } else if (pmap->pr_vaddr == mptr->map_pmap.pr_vaddr &&
481 pmap->pr_size == mptr->map_pmap.pr_size &&
482 pmap->pr_offset == mptr->map_pmap.pr_offset &&
483 (pmap->pr_mflags & ~(MA_BREAK | MA_STACK)) ==
484 (mptr->map_pmap.pr_mflags & ~(MA_BREAK | MA_STACK)) &&
485 pmap->pr_pagesize == mptr->map_pmap.pr_pagesize &&
486 pmap->pr_shmid == mptr->map_pmap.pr_shmid &&
487 strcmp(pmap->pr_mapname, mptr->map_pmap.pr_mapname) == 0) {
490 * This mapping matches exactly. Copy over the old
491 * mapping, taking care to get the latest flags.
492 * Make sure the associated file_info_t is updated
493 * appropriately.
495 *newp = *mptr;
496 if (P->map_exec == mptr)
497 P->map_exec = newp;
498 if (P->map_ldso == mptr)
499 P->map_ldso = newp;
500 newp->map_pmap.pr_mflags = pmap->pr_mflags;
501 if (mptr->map_file != NULL &&
502 mptr->map_file->file_map == mptr)
503 mptr->map_file->file_map = newp;
504 oldmapcount--;
505 mptr++;
507 } else if (pmap->pr_vaddr + pmap->pr_size >
508 mptr->map_pmap.pr_vaddr) {
511 * The old mapping doesn't exist any more, remove it
512 * from the list.
514 map_info_free(P, mptr);
515 oldmapcount--;
516 i--;
517 newp--;
518 pmap--;
519 mptr++;
521 } else {
524 * This is a new mapping, add it directly.
526 newp->map_pmap = *pmap;
531 * Free any old maps
533 while (oldmapcount) {
534 map_info_free(P, mptr);
535 oldmapcount--;
536 mptr++;
539 free(Pmap);
540 free(P->mappings);
541 P->mappings = newmap;
542 P->map_count = P->map_alloc = nmap;
543 P->info_valid = 1;
546 * Consult librtld_db to get the load object
547 * names for all of the shared libraries.
549 if (P->rap != NULL)
550 (void) rd_loadobj_iter(P->rap, map_iter, P);
554 * Update all of the mappings and rtld_db as if by Pupdate_maps(), and then
555 * forcibly cache all of the symbol tables associated with all object files.
557 void
558 Pupdate_syms(struct ps_prochandle *P)
560 file_info_t *fptr;
561 int i;
563 Pupdate_maps(P);
565 for (i = 0, fptr = list_next(&P->file_head); i < P->num_files;
566 i++, fptr = list_next(fptr)) {
567 Pbuild_file_symtab(P, fptr);
568 (void) Pbuild_file_ctf(P, fptr);
573 * Return the librtld_db agent handle for the victim process.
574 * The handle will become invalid at the next successful exec() and the
575 * client (caller of proc_rd_agent()) must not use it beyond that point.
576 * If the process is already dead, we've already tried our best to
577 * create the agent during core file initialization.
579 rd_agent_t *
580 Prd_agent(struct ps_prochandle *P)
582 if (P->rap == NULL && P->state != PS_DEAD && P->state != PS_IDLE) {
583 Pupdate_maps(P);
584 if (P->num_files == 0)
585 load_static_maps(P);
586 rd_log(_libproc_debug);
587 if ((P->rap = rd_new(P)) != NULL)
588 (void) rd_loadobj_iter(P->rap, map_iter, P);
590 return (P->rap);
594 * Return the prmap_t structure containing 'addr', but only if it
595 * is in the dynamic linker's link map and is the text section.
597 const prmap_t *
598 Paddr_to_text_map(struct ps_prochandle *P, uintptr_t addr)
600 map_info_t *mptr;
602 if (!P->info_valid)
603 Pupdate_maps(P);
605 if ((mptr = Paddr2mptr(P, addr)) != NULL) {
606 file_info_t *fptr = build_map_symtab(P, mptr);
607 const prmap_t *pmp = &mptr->map_pmap;
610 * Assume that if rl_data_base is NULL, it means that no
611 * data section was found for this load object, and that
612 * a section must be text. Otherwise, a section will be
613 * text unless it ends above the start of the data
614 * section.
616 if (fptr != NULL && fptr->file_lo != NULL &&
617 (fptr->file_lo->rl_data_base == 0 ||
618 pmp->pr_vaddr + pmp->pr_size <=
619 fptr->file_lo->rl_data_base))
620 return (pmp);
623 return (NULL);
627 * Return the prmap_t structure containing 'addr' (no restrictions on
628 * the type of mapping).
630 const prmap_t *
631 Paddr_to_map(struct ps_prochandle *P, uintptr_t addr)
633 map_info_t *mptr;
635 if (!P->info_valid)
636 Pupdate_maps(P);
638 if ((mptr = Paddr2mptr(P, addr)) != NULL)
639 return (&mptr->map_pmap);
641 return (NULL);
645 * Convert a full or partial load object name to the prmap_t for its
646 * corresponding primary text mapping.
648 const prmap_t *
649 Plmid_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name)
651 map_info_t *mptr;
653 if (name == PR_OBJ_EVERY)
654 return (NULL); /* A reasonable mistake */
656 if ((mptr = object_name_to_map(P, lmid, name)) != NULL)
657 return (&mptr->map_pmap);
659 return (NULL);
662 const prmap_t *
663 Pname_to_map(struct ps_prochandle *P, const char *name)
665 return (Plmid_to_map(P, PR_LMID_EVERY, name));
668 const rd_loadobj_t *
669 Paddr_to_loadobj(struct ps_prochandle *P, uintptr_t addr)
671 map_info_t *mptr;
673 if (!P->info_valid)
674 Pupdate_maps(P);
676 if ((mptr = Paddr2mptr(P, addr)) == NULL)
677 return (NULL);
680 * By building the symbol table, we implicitly bring the PLT
681 * information up to date in the load object.
683 (void) build_map_symtab(P, mptr);
685 return (mptr->map_file->file_lo);
688 const rd_loadobj_t *
689 Plmid_to_loadobj(struct ps_prochandle *P, Lmid_t lmid, const char *name)
691 map_info_t *mptr;
693 if (name == PR_OBJ_EVERY)
694 return (NULL);
696 if ((mptr = object_name_to_map(P, lmid, name)) == NULL)
697 return (NULL);
700 * By building the symbol table, we implicitly bring the PLT
701 * information up to date in the load object.
703 (void) build_map_symtab(P, mptr);
705 return (mptr->map_file->file_lo);
708 const rd_loadobj_t *
709 Pname_to_loadobj(struct ps_prochandle *P, const char *name)
711 return (Plmid_to_loadobj(P, PR_LMID_EVERY, name));
715 * We've been given a file_info_t which doesn't have any CTF. However, it may
716 * have information that's in a format that we could convert if on the fly.
718 static ctf_file_t *
719 Pconvert_file_ctf(file_info_t *fptr)
721 int err;
722 ctf_file_t *fp;
723 char errmsg[1024];
726 * Provide an opt in.
728 if (getenv("LIBPROC_CTFCONVERT") == NULL)
729 return (NULL);
732 * If we've already attempted to call this, then that's it. No reason to
733 * pretend we'll be more successful again another time.
735 if (fptr->file_cvt == B_TRUE)
736 return (NULL);
737 fptr->file_cvt = B_TRUE;
739 fp = ctf_elfconvert(fptr->file_fd, fptr->file_elf, NULL, 1,
740 0, &err, errmsg, sizeof (errmsg));
741 if (fp == NULL)
742 dprintf("failed to convert %s: %s\n", fptr->file_pname,
743 err == ECTF_CONVBKERR ? errmsg : ctf_errmsg(err));
744 else
745 fptr->file_ctfp = fp;
747 return (NULL);
750 ctf_file_t *
751 Pbuild_file_ctf(struct ps_prochandle *P, file_info_t *fptr)
753 ctf_sect_t ctdata, symtab, strtab;
754 sym_tbl_t *symp;
755 int err;
757 if (fptr->file_ctfp != NULL)
758 return (fptr->file_ctfp);
760 Pbuild_file_symtab(P, fptr);
762 if (fptr->file_ctf_size == 0) {
763 return (Pconvert_file_ctf(fptr));
766 symp = fptr->file_ctf_dyn ? &fptr->file_dynsym : &fptr->file_symtab;
767 if (symp->sym_data_pri == NULL)
768 return (NULL);
771 * The buffer may alread be allocated if this is a core file that
772 * contained CTF data for this file.
774 if (fptr->file_ctf_buf == NULL) {
775 fptr->file_ctf_buf = malloc(fptr->file_ctf_size);
776 if (fptr->file_ctf_buf == NULL) {
777 dprintf("failed to allocate ctf buffer\n");
778 return (NULL);
781 if (pread(fptr->file_fd, fptr->file_ctf_buf,
782 fptr->file_ctf_size, fptr->file_ctf_off) !=
783 fptr->file_ctf_size) {
784 free(fptr->file_ctf_buf);
785 fptr->file_ctf_buf = NULL;
786 dprintf("failed to read ctf data\n");
787 return (NULL);
791 ctdata.cts_name = ".SUNW_ctf";
792 ctdata.cts_type = SHT_PROGBITS;
793 ctdata.cts_flags = 0;
794 ctdata.cts_data = fptr->file_ctf_buf;
795 ctdata.cts_size = fptr->file_ctf_size;
796 ctdata.cts_entsize = 1;
797 ctdata.cts_offset = 0;
799 symtab.cts_name = fptr->file_ctf_dyn ? ".dynsym" : ".symtab";
800 symtab.cts_type = symp->sym_hdr_pri.sh_type;
801 symtab.cts_flags = symp->sym_hdr_pri.sh_flags;
802 symtab.cts_data = symp->sym_data_pri->d_buf;
803 symtab.cts_size = symp->sym_hdr_pri.sh_size;
804 symtab.cts_entsize = symp->sym_hdr_pri.sh_entsize;
805 symtab.cts_offset = symp->sym_hdr_pri.sh_offset;
807 strtab.cts_name = fptr->file_ctf_dyn ? ".dynstr" : ".strtab";
808 strtab.cts_type = symp->sym_strhdr.sh_type;
809 strtab.cts_flags = symp->sym_strhdr.sh_flags;
810 strtab.cts_data = symp->sym_strs;
811 strtab.cts_size = symp->sym_strhdr.sh_size;
812 strtab.cts_entsize = symp->sym_strhdr.sh_entsize;
813 strtab.cts_offset = symp->sym_strhdr.sh_offset;
815 fptr->file_ctfp = ctf_bufopen(&ctdata, &symtab, &strtab, &err);
816 if (fptr->file_ctfp == NULL) {
817 dprintf("ctf_bufopen() failed, error code %d\n", err);
818 free(fptr->file_ctf_buf);
819 fptr->file_ctf_buf = NULL;
820 return (NULL);
823 dprintf("loaded %lu bytes of CTF data for %s\n",
824 (ulong_t)fptr->file_ctf_size, fptr->file_pname);
826 return (fptr->file_ctfp);
829 ctf_file_t *
830 Paddr_to_ctf(struct ps_prochandle *P, uintptr_t addr)
832 map_info_t *mptr;
833 file_info_t *fptr;
835 if (!P->info_valid)
836 Pupdate_maps(P);
838 if ((mptr = Paddr2mptr(P, addr)) == NULL ||
839 (fptr = mptr->map_file) == NULL)
840 return (NULL);
842 return (Pbuild_file_ctf(P, fptr));
845 ctf_file_t *
846 Plmid_to_ctf(struct ps_prochandle *P, Lmid_t lmid, const char *name)
848 map_info_t *mptr;
849 file_info_t *fptr = NULL;
851 if (name == PR_OBJ_EVERY)
852 return (NULL);
855 * While most idle files are all ELF objects, not all of them have
856 * mapping information available. There's nothing which would make
857 * sense to fake up for ET_REL. Instead, if we're being asked for their
858 * executable object and we know that the information is valid and they
859 * only have a single file, we jump straight to that file pointer.
861 if (P->state == PS_IDLE && name == PR_OBJ_EXEC && P->info_valid == 1 &&
862 P->num_files == 1 && P->mappings == NULL) {
863 fptr = list_next(&P->file_head);
866 if (fptr == NULL) {
867 if ((mptr = object_name_to_map(P, lmid, name)) == NULL ||
868 (fptr = mptr->map_file) == NULL)
869 return (NULL);
872 return (Pbuild_file_ctf(P, fptr));
875 ctf_file_t *
876 Pname_to_ctf(struct ps_prochandle *P, const char *name)
878 return (Plmid_to_ctf(P, PR_LMID_EVERY, name));
881 void
882 Preadauxvec(struct ps_prochandle *P)
884 if (P->auxv != NULL) {
885 free(P->auxv);
886 P->auxv = NULL;
887 P->nauxv = 0;
890 P->ops.pop_read_aux(P, &P->auxv, &P->nauxv, P->data);
894 * Return a requested element from the process's aux vector.
895 * Return -1 on failure (this is adequate for our purposes).
897 long
898 Pgetauxval(struct ps_prochandle *P, int type)
900 auxv_t *auxv;
902 if (P->auxv == NULL)
903 Preadauxvec(P);
905 if (P->auxv == NULL)
906 return (-1);
908 for (auxv = P->auxv; auxv->a_type != AT_NULL; auxv++) {
909 if (auxv->a_type == type)
910 return (auxv->a_un.a_val);
913 return (-1);
917 * Return a pointer to our internal copy of the process's aux vector.
918 * The caller should not hold on to this pointer across any libproc calls.
920 const auxv_t *
921 Pgetauxvec(struct ps_prochandle *P)
923 static const auxv_t empty = { AT_NULL, 0L };
925 if (P->auxv == NULL)
926 Preadauxvec(P);
928 if (P->auxv == NULL)
929 return (&empty);
931 return (P->auxv);
935 * Return 1 if the given mapping corresponds to the given file_info_t's
936 * load object; return 0 otherwise.
938 static int
939 is_mapping_in_file(struct ps_prochandle *P, map_info_t *mptr, file_info_t *fptr)
941 prmap_t *pmap = &mptr->map_pmap;
942 rd_loadobj_t *lop = fptr->file_lo;
943 uint_t i;
944 uintptr_t mstart, mend, sstart, send;
947 * We can get for free the start address of the text and data
948 * sections of the load object. Start by seeing if the mapping
949 * encloses either of these.
951 if ((pmap->pr_vaddr <= lop->rl_base &&
952 lop->rl_base < pmap->pr_vaddr + pmap->pr_size) ||
953 (pmap->pr_vaddr <= lop->rl_data_base &&
954 lop->rl_data_base < pmap->pr_vaddr + pmap->pr_size))
955 return (1);
958 * It's still possible that this mapping correponds to the load
959 * object. Consider the example of a mapping whose start and end
960 * addresses correspond to those of the load object's text section.
961 * If the mapping splits, e.g. as a result of a segment demotion,
962 * then although both mappings are still backed by the same section,
963 * only one will be seen to enclose that section's start address.
964 * Thus, to be rigorous, we ask not whether this mapping encloses
965 * the start of a section, but whether there exists a section that
966 * overlaps this mapping.
968 * If we don't already have the section addresses, and we successfully
969 * get them, then we cache them in case we come here again.
971 if (fptr->file_saddrs == NULL &&
972 (fptr->file_saddrs = get_saddrs(P,
973 fptr->file_map->map_pmap.pr_vaddr, &fptr->file_nsaddrs)) == NULL)
974 return (0);
976 mstart = mptr->map_pmap.pr_vaddr;
977 mend = mptr->map_pmap.pr_vaddr + mptr->map_pmap.pr_size;
978 for (i = 0; i < fptr->file_nsaddrs; i += 2) {
979 /* Does this section overlap the mapping? */
980 sstart = fptr->file_saddrs[i];
981 send = fptr->file_saddrs[i + 1];
982 if (!(mend <= sstart || mstart >= send))
983 return (1);
986 return (0);
990 * Find or build the symbol table for the given mapping.
992 static file_info_t *
993 build_map_symtab(struct ps_prochandle *P, map_info_t *mptr)
995 prmap_t *pmap = &mptr->map_pmap;
996 file_info_t *fptr;
997 uint_t i;
999 if ((fptr = mptr->map_file) != NULL) {
1000 Pbuild_file_symtab(P, fptr);
1001 return (fptr);
1004 if (pmap->pr_mapname[0] == '\0')
1005 return (NULL);
1008 * Attempt to find a matching file.
1009 * (A file can be mapped at several different addresses.)
1011 for (i = 0, fptr = list_next(&P->file_head); i < P->num_files;
1012 i++, fptr = list_next(fptr)) {
1013 if (strcmp(fptr->file_pname, pmap->pr_mapname) == 0 &&
1014 fptr->file_lo && is_mapping_in_file(P, mptr, fptr)) {
1015 mptr->map_file = fptr;
1016 fptr->file_ref++;
1017 Pbuild_file_symtab(P, fptr);
1018 return (fptr);
1023 * If we need to create a new file_info structure, iterate
1024 * through the load objects in order to attempt to connect
1025 * this new file with its primary text mapping. We again
1026 * need to handle ld.so as a special case because we need
1027 * to be able to bootstrap librtld_db.
1029 if ((fptr = file_info_new(P, mptr)) == NULL)
1030 return (NULL);
1032 if (P->map_ldso != mptr) {
1033 if (P->rap != NULL)
1034 (void) rd_loadobj_iter(P->rap, map_iter, P);
1035 else
1036 (void) Prd_agent(P);
1037 } else {
1038 fptr->file_map = mptr;
1042 * If librtld_db wasn't able to help us connect the file to a primary
1043 * text mapping, set file_map to the current mapping because we require
1044 * fptr->file_map to be set in Pbuild_file_symtab. librtld_db may be
1045 * unaware of what's going on in the rare case that a legitimate ELF
1046 * file has been mmap(2)ed into the process address space *without*
1047 * the use of dlopen(3x).
1049 if (fptr->file_map == NULL)
1050 fptr->file_map = mptr;
1052 Pbuild_file_symtab(P, fptr);
1054 return (fptr);
1057 static int
1058 read_ehdr32(struct ps_prochandle *P, Elf32_Ehdr *ehdr, uint_t *phnum,
1059 uintptr_t addr)
1061 if (Pread(P, ehdr, sizeof (*ehdr), addr) != sizeof (*ehdr))
1062 return (-1);
1064 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1065 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1066 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1067 ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
1068 ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
1069 #ifdef _BIG_ENDIAN
1070 ehdr->e_ident[EI_DATA] != ELFDATA2MSB ||
1071 #else
1072 ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
1073 #endif
1074 ehdr->e_ident[EI_VERSION] != EV_CURRENT)
1075 return (-1);
1077 if ((*phnum = ehdr->e_phnum) == PN_XNUM) {
1078 Elf32_Shdr shdr0;
1080 if (ehdr->e_shoff == 0 || ehdr->e_shentsize < sizeof (shdr0) ||
1081 Pread(P, &shdr0, sizeof (shdr0), addr + ehdr->e_shoff) !=
1082 sizeof (shdr0))
1083 return (-1);
1085 if (shdr0.sh_info != 0)
1086 *phnum = shdr0.sh_info;
1089 return (0);
1092 static int
1093 read_dynamic_phdr32(struct ps_prochandle *P, const Elf32_Ehdr *ehdr,
1094 uint_t phnum, Elf32_Phdr *phdr, uintptr_t addr)
1096 uint_t i;
1098 for (i = 0; i < phnum; i++) {
1099 uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize;
1100 if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr))
1101 return (-1);
1103 if (phdr->p_type == PT_DYNAMIC)
1104 return (0);
1107 return (-1);
1110 #ifdef _LP64
1111 static int
1112 read_ehdr64(struct ps_prochandle *P, Elf64_Ehdr *ehdr, uint_t *phnum,
1113 uintptr_t addr)
1115 if (Pread(P, ehdr, sizeof (Elf64_Ehdr), addr) != sizeof (Elf64_Ehdr))
1116 return (-1);
1118 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1119 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1120 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1121 ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
1122 ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
1123 #ifdef _BIG_ENDIAN
1124 ehdr->e_ident[EI_DATA] != ELFDATA2MSB ||
1125 #else
1126 ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
1127 #endif
1128 ehdr->e_ident[EI_VERSION] != EV_CURRENT)
1129 return (-1);
1131 if ((*phnum = ehdr->e_phnum) == PN_XNUM) {
1132 Elf64_Shdr shdr0;
1134 if (ehdr->e_shoff == 0 || ehdr->e_shentsize < sizeof (shdr0) ||
1135 Pread(P, &shdr0, sizeof (shdr0), addr + ehdr->e_shoff) !=
1136 sizeof (shdr0))
1137 return (-1);
1139 if (shdr0.sh_info != 0)
1140 *phnum = shdr0.sh_info;
1143 return (0);
1146 static int
1147 read_dynamic_phdr64(struct ps_prochandle *P, const Elf64_Ehdr *ehdr,
1148 uint_t phnum, Elf64_Phdr *phdr, uintptr_t addr)
1150 uint_t i;
1152 for (i = 0; i < phnum; i++) {
1153 uintptr_t a = addr + ehdr->e_phoff + i * ehdr->e_phentsize;
1154 if (Pread(P, phdr, sizeof (*phdr), a) != sizeof (*phdr))
1155 return (-1);
1157 if (phdr->p_type == PT_DYNAMIC)
1158 return (0);
1161 return (-1);
1163 #endif /* _LP64 */
1166 * The text segment for each load object contains the elf header and
1167 * program headers. We can use this information to determine if the
1168 * file that corresponds to the load object is the same file that
1169 * was loaded into the process's address space. There can be a discrepency
1170 * if a file is recompiled after the process is started or if the target
1171 * represents a core file from a differently configured system -- two
1172 * common examples. The DT_CHECKSUM entry in the dynamic section
1173 * provides an easy method of comparison. It is important to note that
1174 * the dynamic section usually lives in the data segment, but the meta
1175 * data we use to find the dynamic section lives in the text segment so
1176 * if either of those segments is absent we can't proceed.
1178 * We're looking through the elf file for several items: the symbol tables
1179 * (both dynsym and symtab), the procedure linkage table (PLT) base,
1180 * size, and relocation base, and the CTF information. Most of this can
1181 * be recovered from the loaded image of the file itself, the exceptions
1182 * being the symtab and CTF data.
1184 * First we try to open the file that we think corresponds to the load
1185 * object, if the DT_CHECKSUM values match, we're all set, and can simply
1186 * recover all the information we need from the file. If the values of
1187 * DT_CHECKSUM don't match, or if we can't access the file for whatever
1188 * reasaon, we fake up a elf file to use in its stead. If we can't read
1189 * the elf data in the process's address space, we fall back to using
1190 * the file even though it may give inaccurate information.
1192 * The elf file that we fake up has to consist of sections for the
1193 * dynsym, the PLT and the dynamic section. Note that in the case of a
1194 * core file, we'll get the CTF data in the file_info_t later on from
1195 * a section embedded the core file (if it's present).
1197 * file_differs() conservatively looks for mismatched files, identifying
1198 * a match when there is any ambiguity (since that's the legacy behavior).
1200 static int
1201 file_differs(struct ps_prochandle *P, Elf *elf, file_info_t *fptr)
1203 Elf_Scn *scn;
1204 GElf_Shdr shdr;
1205 GElf_Dyn dyn;
1206 Elf_Data *data;
1207 uint_t i, ndyn;
1208 GElf_Xword cksum;
1209 uintptr_t addr;
1211 if (fptr->file_map == NULL)
1212 return (0);
1214 if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) !=
1215 (CC_CONTENT_TEXT | CC_CONTENT_DATA))
1216 return (0);
1219 * First, we find the checksum value in the elf file.
1221 scn = NULL;
1222 while ((scn = elf_nextscn(elf, scn)) != NULL) {
1223 if (gelf_getshdr(scn, &shdr) != NULL &&
1224 shdr.sh_type == SHT_DYNAMIC)
1225 goto found_shdr;
1227 return (0);
1229 found_shdr:
1230 if ((data = elf_getdata(scn, NULL)) == NULL)
1231 return (0);
1233 if (P->status.pr_dmodel == PR_MODEL_ILP32)
1234 ndyn = shdr.sh_size / sizeof (Elf32_Dyn);
1235 #ifdef _LP64
1236 else if (P->status.pr_dmodel == PR_MODEL_LP64)
1237 ndyn = shdr.sh_size / sizeof (Elf64_Dyn);
1238 #endif
1239 else
1240 return (0);
1242 for (i = 0; i < ndyn; i++) {
1243 if (gelf_getdyn(data, i, &dyn) != NULL &&
1244 dyn.d_tag == DT_CHECKSUM)
1245 goto found_cksum;
1249 * The in-memory ELF has no DT_CHECKSUM section, but we will report it
1250 * as matching the file anyhow.
1252 return (0);
1254 found_cksum:
1255 cksum = dyn.d_un.d_val;
1256 dprintf("elf cksum value is %llx\n", (u_longlong_t)cksum);
1259 * Get the base of the text mapping that corresponds to this file.
1261 addr = fptr->file_map->map_pmap.pr_vaddr;
1263 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1264 Elf32_Ehdr ehdr;
1265 Elf32_Phdr phdr;
1266 Elf32_Dyn dync, *dynp;
1267 uint_t phnum, i;
1269 if (read_ehdr32(P, &ehdr, &phnum, addr) != 0 ||
1270 read_dynamic_phdr32(P, &ehdr, phnum, &phdr, addr) != 0)
1271 return (0);
1273 if (ehdr.e_type == ET_DYN)
1274 phdr.p_vaddr += addr;
1275 if ((dynp = malloc(phdr.p_filesz)) == NULL)
1276 return (0);
1277 dync.d_tag = DT_NULL;
1278 if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) !=
1279 phdr.p_filesz) {
1280 free(dynp);
1281 return (0);
1284 for (i = 0; i < phdr.p_filesz / sizeof (Elf32_Dyn); i++) {
1285 if (dynp[i].d_tag == DT_CHECKSUM)
1286 dync = dynp[i];
1289 free(dynp);
1291 if (dync.d_tag != DT_CHECKSUM)
1292 return (0);
1294 dprintf("image cksum value is %llx\n",
1295 (u_longlong_t)dync.d_un.d_val);
1296 return (dync.d_un.d_val != cksum);
1297 #ifdef _LP64
1298 } else if (P->status.pr_dmodel == PR_MODEL_LP64) {
1299 Elf64_Ehdr ehdr;
1300 Elf64_Phdr phdr;
1301 Elf64_Dyn dync, *dynp;
1302 uint_t phnum, i;
1304 if (read_ehdr64(P, &ehdr, &phnum, addr) != 0 ||
1305 read_dynamic_phdr64(P, &ehdr, phnum, &phdr, addr) != 0)
1306 return (0);
1308 if (ehdr.e_type == ET_DYN)
1309 phdr.p_vaddr += addr;
1310 if ((dynp = malloc(phdr.p_filesz)) == NULL)
1311 return (0);
1312 dync.d_tag = DT_NULL;
1313 if (Pread(P, dynp, phdr.p_filesz, phdr.p_vaddr) !=
1314 phdr.p_filesz) {
1315 free(dynp);
1316 return (0);
1319 for (i = 0; i < phdr.p_filesz / sizeof (Elf64_Dyn); i++) {
1320 if (dynp[i].d_tag == DT_CHECKSUM)
1321 dync = dynp[i];
1324 free(dynp);
1326 if (dync.d_tag != DT_CHECKSUM)
1327 return (0);
1329 dprintf("image cksum value is %llx\n",
1330 (u_longlong_t)dync.d_un.d_val);
1331 return (dync.d_un.d_val != cksum);
1332 #endif /* _LP64 */
1335 return (0);
1339 * Read data from the specified process and construct an in memory
1340 * image of an ELF file that represents it well enough to let
1341 * us probe it for information.
1343 static Elf *
1344 fake_elf(struct ps_prochandle *P, file_info_t *fptr)
1346 Elf *elf;
1347 uintptr_t addr;
1348 uint_t phnum;
1350 if (fptr->file_map == NULL)
1351 return (NULL);
1353 if ((Pcontent(P) & (CC_CONTENT_TEXT | CC_CONTENT_DATA)) !=
1354 (CC_CONTENT_TEXT | CC_CONTENT_DATA))
1355 return (NULL);
1357 addr = fptr->file_map->map_pmap.pr_vaddr;
1359 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1360 Elf32_Ehdr ehdr;
1361 Elf32_Phdr phdr;
1363 if ((read_ehdr32(P, &ehdr, &phnum, addr) != 0) ||
1364 read_dynamic_phdr32(P, &ehdr, phnum, &phdr, addr) != 0)
1365 return (NULL);
1367 elf = fake_elf32(P, fptr, addr, &ehdr, phnum, &phdr);
1368 #ifdef _LP64
1369 } else {
1370 Elf64_Ehdr ehdr;
1371 Elf64_Phdr phdr;
1373 if (read_ehdr64(P, &ehdr, &phnum, addr) != 0 ||
1374 read_dynamic_phdr64(P, &ehdr, phnum, &phdr, addr) != 0)
1375 return (NULL);
1377 elf = fake_elf64(P, fptr, addr, &ehdr, phnum, &phdr);
1378 #endif
1381 return (elf);
1385 * We wouldn't need these if qsort(3C) took an argument for the callback...
1387 static mutex_t sort_mtx = DEFAULTMUTEX;
1388 static char *sort_strs;
1389 static GElf_Sym *sort_syms;
1392 byaddr_cmp_common(GElf_Sym *a, char *aname, GElf_Sym *b, char *bname)
1394 if (a->st_value < b->st_value)
1395 return (-1);
1396 if (a->st_value > b->st_value)
1397 return (1);
1400 * Prefer the function to the non-function.
1402 if (GELF_ST_TYPE(a->st_info) != GELF_ST_TYPE(b->st_info)) {
1403 if (GELF_ST_TYPE(a->st_info) == STT_FUNC)
1404 return (-1);
1405 if (GELF_ST_TYPE(b->st_info) == STT_FUNC)
1406 return (1);
1410 * Prefer the weak or strong global symbol to the local symbol.
1412 if (GELF_ST_BIND(a->st_info) != GELF_ST_BIND(b->st_info)) {
1413 if (GELF_ST_BIND(b->st_info) == STB_LOCAL)
1414 return (-1);
1415 if (GELF_ST_BIND(a->st_info) == STB_LOCAL)
1416 return (1);
1420 * Prefer the symbol that doesn't begin with a '$' since compilers and
1421 * other symbol generators often use it as a prefix.
1423 if (*bname == '$')
1424 return (-1);
1425 if (*aname == '$')
1426 return (1);
1429 * Prefer the name with fewer leading underscores in the name.
1431 while (*aname == '_' && *bname == '_') {
1432 aname++;
1433 bname++;
1436 if (*bname == '_')
1437 return (-1);
1438 if (*aname == '_')
1439 return (1);
1442 * Prefer the symbol with the smaller size.
1444 if (a->st_size < b->st_size)
1445 return (-1);
1446 if (a->st_size > b->st_size)
1447 return (1);
1450 * All other factors being equal, fall back to lexicographic order.
1452 return (strcmp(aname, bname));
1455 static int
1456 byaddr_cmp(const void *aa, const void *bb)
1458 GElf_Sym *a = &sort_syms[*(uint_t *)aa];
1459 GElf_Sym *b = &sort_syms[*(uint_t *)bb];
1460 char *aname = sort_strs + a->st_name;
1461 char *bname = sort_strs + b->st_name;
1463 return (byaddr_cmp_common(a, aname, b, bname));
1466 static int
1467 byname_cmp(const void *aa, const void *bb)
1469 GElf_Sym *a = &sort_syms[*(uint_t *)aa];
1470 GElf_Sym *b = &sort_syms[*(uint_t *)bb];
1471 char *aname = sort_strs + a->st_name;
1472 char *bname = sort_strs + b->st_name;
1474 return (strcmp(aname, bname));
1478 * Given a symbol index, look up the corresponding symbol from the
1479 * given symbol table.
1481 * This function allows the caller to treat the symbol table as a single
1482 * logical entity even though there may be 2 actual ELF symbol tables
1483 * involved. See the comments in Pcontrol.h for details.
1485 static GElf_Sym *
1486 symtab_getsym(sym_tbl_t *symtab, int ndx, GElf_Sym *dst)
1488 /* If index is in range of primary symtab, look it up there */
1489 if (ndx >= symtab->sym_symn_aux) {
1490 return (gelf_getsym(symtab->sym_data_pri,
1491 ndx - symtab->sym_symn_aux, dst));
1494 /* Not in primary: Look it up in the auxiliary symtab */
1495 return (gelf_getsym(symtab->sym_data_aux, ndx, dst));
1498 void
1499 optimize_symtab(sym_tbl_t *symtab)
1501 GElf_Sym *symp, *syms;
1502 uint_t i, *indexa, *indexb;
1503 size_t symn, strsz, count;
1505 if (symtab == NULL || symtab->sym_data_pri == NULL ||
1506 symtab->sym_byaddr != NULL)
1507 return;
1509 symn = symtab->sym_symn;
1510 strsz = symtab->sym_strsz;
1512 symp = syms = malloc(sizeof (GElf_Sym) * symn);
1513 if (symp == NULL) {
1514 dprintf("optimize_symtab: failed to malloc symbol array");
1515 return;
1519 * First record all the symbols into a table and count up the ones
1520 * that we're interested in. We mark symbols as invalid by setting
1521 * the st_name to an illegal value.
1523 for (i = 0, count = 0; i < symn; i++, symp++) {
1524 if (symtab_getsym(symtab, i, symp) != NULL &&
1525 symp->st_name < strsz &&
1526 IS_DATA_TYPE(GELF_ST_TYPE(symp->st_info)))
1527 count++;
1528 else
1529 symp->st_name = strsz;
1533 * Allocate sufficient space for both tables and populate them
1534 * with the same symbols we just counted.
1536 symtab->sym_count = count;
1537 indexa = symtab->sym_byaddr = calloc(sizeof (uint_t), count);
1538 indexb = symtab->sym_byname = calloc(sizeof (uint_t), count);
1539 if (indexa == NULL || indexb == NULL) {
1540 dprintf(
1541 "optimize_symtab: failed to malloc symbol index arrays");
1542 symtab->sym_count = 0;
1543 if (indexa != NULL) { /* First alloc succeeded. Free it */
1544 free(indexa);
1545 symtab->sym_byaddr = NULL;
1547 free(syms);
1548 return;
1550 for (i = 0, symp = syms; i < symn; i++, symp++) {
1551 if (symp->st_name < strsz)
1552 *indexa++ = *indexb++ = i;
1556 * Sort the two tables according to the appropriate criteria,
1557 * unless the user has overridden this behaviour.
1559 * An example where we might not sort the tables is the relatively
1560 * unusual case of a process with very large symbol tables in which
1561 * we perform few lookups. In such a case the total time would be
1562 * dominated by the sort. It is difficult to determine a priori
1563 * how many lookups an arbitrary client will perform, and
1564 * hence whether the symbol tables should be sorted. We therefore
1565 * sort the tables by default, but provide the user with a
1566 * "chicken switch" in the form of the LIBPROC_NO_QSORT
1567 * environment variable.
1569 if (!_libproc_no_qsort) {
1570 (void) mutex_lock(&sort_mtx);
1571 sort_strs = symtab->sym_strs;
1572 sort_syms = syms;
1574 qsort(symtab->sym_byaddr, count, sizeof (uint_t), byaddr_cmp);
1575 qsort(symtab->sym_byname, count, sizeof (uint_t), byname_cmp);
1577 sort_strs = NULL;
1578 sort_syms = NULL;
1579 (void) mutex_unlock(&sort_mtx);
1582 free(syms);
1586 static Elf *
1587 build_fake_elf(struct ps_prochandle *P, file_info_t *fptr, GElf_Ehdr *ehdr,
1588 size_t *nshdrs, Elf_Data **shdata)
1590 size_t shstrndx;
1591 Elf_Scn *scn;
1592 Elf *elf;
1594 if ((elf = fake_elf(P, fptr)) == NULL ||
1595 elf_kind(elf) != ELF_K_ELF ||
1596 gelf_getehdr(elf, ehdr) == NULL ||
1597 elf_getshdrnum(elf, nshdrs) == -1 ||
1598 elf_getshdrstrndx(elf, &shstrndx) == -1 ||
1599 (scn = elf_getscn(elf, shstrndx)) == NULL ||
1600 (*shdata = elf_getdata(scn, NULL)) == NULL) {
1601 if (elf != NULL)
1602 (void) elf_end(elf);
1603 dprintf("failed to fake up ELF file\n");
1604 return (NULL);
1607 return (elf);
1611 * Build the symbol table for the given mapped file.
1613 void
1614 Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr)
1616 char objectfile[PATH_MAX];
1617 uint_t i;
1619 GElf_Ehdr ehdr;
1620 GElf_Sym s;
1622 Elf_Data *shdata;
1623 Elf_Scn *scn;
1624 Elf *elf;
1625 size_t nshdrs, shstrndx;
1627 struct {
1628 GElf_Shdr c_shdr;
1629 Elf_Data *c_data;
1630 const char *c_name;
1631 } *cp, *cache = NULL, *dyn = NULL, *plt = NULL, *ctf = NULL;
1633 if (fptr->file_init)
1634 return; /* We've already processed this file */
1637 * Mark the file_info struct as having the symbol table initialized
1638 * even if we fail below. We tried once; we don't try again.
1640 fptr->file_init = 1;
1642 if (elf_version(EV_CURRENT) == EV_NONE) {
1643 dprintf("libproc ELF version is more recent than libelf\n");
1644 return;
1647 if (P->state == PS_DEAD || P->state == PS_IDLE) {
1648 char *name;
1650 * If we're a not live, we can't open files from the /proc
1651 * object directory; we have only the mapping and file names
1652 * to guide us. We prefer the file_lname, but need to handle
1653 * the case of it being NULL in order to bootstrap: we first
1654 * come here during rd_new() when the only information we have
1655 * is interpreter name associated with the AT_BASE mapping.
1657 * Also, if the zone associated with the core file seems
1658 * to exists on this machine we'll try to open the object
1659 * file within the zone.
1661 if (fptr->file_rname != NULL)
1662 name = fptr->file_rname;
1663 else if (fptr->file_lname != NULL)
1664 name = fptr->file_lname;
1665 else
1666 name = fptr->file_pname;
1667 (void) strlcpy(objectfile, name, sizeof (objectfile));
1668 } else {
1669 (void) snprintf(objectfile, sizeof (objectfile),
1670 "%s/%d/object/%s",
1671 procfs_path, (int)P->pid, fptr->file_pname);
1675 * Open the object file, create the elf file, and then get the elf
1676 * header and .shstrtab data buffer so we can process sections by
1677 * name. If anything goes wrong try to fake up an elf file from
1678 * the in-core elf image.
1681 if (_libproc_incore_elf || (P->flags & INCORE)) {
1682 dprintf("Pbuild_file_symtab: using in-core data for: %s\n",
1683 fptr->file_pname);
1685 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1686 NULL)
1687 return;
1689 } else if ((fptr->file_fd = open(objectfile, O_RDONLY)) < 0) {
1690 dprintf("Pbuild_file_symtab: failed to open %s: %s\n",
1691 objectfile, strerror(errno));
1693 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1694 NULL)
1695 return;
1697 } else if ((elf = elf_begin(fptr->file_fd, ELF_C_READ, NULL)) == NULL ||
1698 elf_kind(elf) != ELF_K_ELF ||
1699 gelf_getehdr(elf, &ehdr) == NULL ||
1700 elf_getshdrnum(elf, &nshdrs) == -1 ||
1701 elf_getshdrstrndx(elf, &shstrndx) == -1 ||
1702 (scn = elf_getscn(elf, shstrndx)) == NULL ||
1703 (shdata = elf_getdata(scn, NULL)) == NULL) {
1704 int err = elf_errno();
1706 dprintf("failed to process ELF file %s: %s\n",
1707 objectfile, (err == 0) ? "<null>" : elf_errmsg(err));
1708 (void) elf_end(elf);
1710 if ((elf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata)) ==
1711 NULL)
1712 return;
1714 } else if (file_differs(P, elf, fptr)) {
1715 Elf *newelf;
1718 * Before we get too excited about this elf file, we'll check
1719 * its checksum value against the value we have in memory. If
1720 * they don't agree, we try to fake up a new elf file and
1721 * proceed with that instead.
1723 dprintf("ELF file %s (%lx) doesn't match in-core image\n",
1724 fptr->file_pname,
1725 (ulong_t)fptr->file_map->map_pmap.pr_vaddr);
1727 if ((newelf = build_fake_elf(P, fptr, &ehdr, &nshdrs, &shdata))
1728 != NULL) {
1729 (void) elf_end(elf);
1730 elf = newelf;
1731 dprintf("switched to faked up ELF file\n");
1734 * Check to see if the file that we just discovered
1735 * to be an imposter matches the execname that was
1736 * determined by Pfindexec(). If it does, we (clearly)
1737 * don't have the right binary, and we zero out
1738 * execname before anyone gets hurt.
1740 if (fptr->file_rname != NULL && P->execname != NULL &&
1741 strcmp(fptr->file_rname, P->execname) == 0) {
1742 dprintf("file/in-core image mismatch was "
1743 "on P->execname; discarding\n");
1744 free(P->execname);
1745 P->execname = NULL;
1750 if ((cache = malloc(nshdrs * sizeof (*cache))) == NULL) {
1751 dprintf("failed to malloc section cache for %s\n", objectfile);
1752 goto bad;
1755 dprintf("processing ELF file %s\n", objectfile);
1756 fptr->file_class = ehdr.e_ident[EI_CLASS];
1757 fptr->file_etype = ehdr.e_type;
1758 fptr->file_elf = elf;
1759 fptr->file_shstrs = shdata->d_buf;
1760 fptr->file_shstrsz = shdata->d_size;
1763 * Iterate through each section, caching its section header, data
1764 * pointer, and name. We use this for handling sh_link values below.
1766 for (cp = cache + 1, scn = NULL; scn = elf_nextscn(elf, scn); cp++) {
1767 if (gelf_getshdr(scn, &cp->c_shdr) == NULL) {
1768 dprintf("Pbuild_file_symtab: Failed to get section "
1769 "header\n");
1770 goto bad; /* Failed to get section header */
1773 if ((cp->c_data = elf_getdata(scn, NULL)) == NULL) {
1774 dprintf("Pbuild_file_symtab: Failed to get section "
1775 "data\n");
1776 goto bad; /* Failed to get section data */
1779 if (cp->c_shdr.sh_name >= shdata->d_size) {
1780 dprintf("Pbuild_file_symtab: corrupt section name");
1781 goto bad; /* Corrupt section name */
1784 cp->c_name = (const char *)shdata->d_buf + cp->c_shdr.sh_name;
1788 * Now iterate through the section cache in order to locate info
1789 * for the .symtab, .dynsym, .SUNW_ldynsym, .dynamic, .plt,
1790 * and .SUNW_ctf sections:
1792 for (i = 1, cp = cache + 1; i < nshdrs; i++, cp++) {
1793 GElf_Shdr *shp = &cp->c_shdr;
1795 if (shp->sh_type == SHT_SYMTAB || shp->sh_type == SHT_DYNSYM) {
1796 sym_tbl_t *symp = shp->sh_type == SHT_SYMTAB ?
1797 &fptr->file_symtab : &fptr->file_dynsym;
1799 * It's possible that the we already got the symbol
1800 * table from the core file itself. Either the file
1801 * differs in which case our faked up elf file will
1802 * only contain the dynsym (not the symtab) or the
1803 * file matches in which case we'll just be replacing
1804 * the symbol table we pulled out of the core file
1805 * with an equivalent one. In either case, this
1806 * check isn't essential, but it's a good idea.
1808 if (symp->sym_data_pri == NULL) {
1809 dprintf("Symbol table found for %s\n",
1810 objectfile);
1811 symp->sym_data_pri = cp->c_data;
1812 symp->sym_symn +=
1813 shp->sh_size / shp->sh_entsize;
1814 symp->sym_strs =
1815 cache[shp->sh_link].c_data->d_buf;
1816 symp->sym_strsz =
1817 cache[shp->sh_link].c_data->d_size;
1818 symp->sym_hdr_pri = cp->c_shdr;
1819 symp->sym_strhdr = cache[shp->sh_link].c_shdr;
1820 } else {
1821 dprintf("Symbol table already there for %s\n",
1822 objectfile);
1824 } else if (shp->sh_type == SHT_SUNW_LDYNSYM) {
1825 /* .SUNW_ldynsym section is auxiliary to .dynsym */
1826 if (fptr->file_dynsym.sym_data_aux == NULL) {
1827 dprintf(".SUNW_ldynsym symbol table"
1828 " found for %s\n", objectfile);
1829 fptr->file_dynsym.sym_data_aux = cp->c_data;
1830 fptr->file_dynsym.sym_symn_aux =
1831 shp->sh_size / shp->sh_entsize;
1832 fptr->file_dynsym.sym_symn +=
1833 fptr->file_dynsym.sym_symn_aux;
1834 fptr->file_dynsym.sym_hdr_aux = cp->c_shdr;
1835 } else {
1836 dprintf(".SUNW_ldynsym symbol table already"
1837 " there for %s\n", objectfile);
1839 } else if (shp->sh_type == SHT_DYNAMIC) {
1840 dyn = cp;
1841 } else if (strcmp(cp->c_name, ".plt") == 0) {
1842 plt = cp;
1843 } else if (strcmp(cp->c_name, ".SUNW_ctf") == 0) {
1845 * Skip over bogus CTF sections so they don't come back
1846 * to haunt us later.
1848 if (shp->sh_link == 0 ||
1849 shp->sh_link >= nshdrs ||
1850 (cache[shp->sh_link].c_shdr.sh_type != SHT_DYNSYM &&
1851 cache[shp->sh_link].c_shdr.sh_type != SHT_SYMTAB)) {
1852 dprintf("Bad sh_link %d for "
1853 "CTF\n", shp->sh_link);
1854 continue;
1856 ctf = cp;
1861 * At this point, we've found all the symbol tables we're ever going
1862 * to find: the ones in the loop above and possibly the symtab that
1863 * was included in the core file. Before we perform any lookups, we
1864 * create sorted versions to optimize for lookups.
1866 optimize_symtab(&fptr->file_symtab);
1867 optimize_symtab(&fptr->file_dynsym);
1870 * Fill in the base address of the text mapping for shared libraries.
1871 * This allows us to translate symbols before librtld_db is ready.
1873 if (fptr->file_etype == ET_DYN) {
1874 fptr->file_dyn_base = fptr->file_map->map_pmap.pr_vaddr -
1875 fptr->file_map->map_pmap.pr_offset;
1876 dprintf("setting file_dyn_base for %s to %lx\n",
1877 objectfile, (long)fptr->file_dyn_base);
1881 * Record the CTF section information in the file info structure.
1883 if (ctf != NULL) {
1884 fptr->file_ctf_off = ctf->c_shdr.sh_offset;
1885 fptr->file_ctf_size = ctf->c_shdr.sh_size;
1886 if (ctf->c_shdr.sh_link != 0 &&
1887 cache[ctf->c_shdr.sh_link].c_shdr.sh_type == SHT_DYNSYM)
1888 fptr->file_ctf_dyn = 1;
1891 if (fptr->file_lo == NULL)
1892 goto done; /* Nothing else to do if no load object info */
1895 * If the object is a shared library and we have a different rl_base
1896 * value, reset file_dyn_base according to librtld_db's information.
1898 if (fptr->file_etype == ET_DYN &&
1899 fptr->file_lo->rl_base != fptr->file_dyn_base) {
1900 dprintf("resetting file_dyn_base for %s to %lx\n",
1901 objectfile, (long)fptr->file_lo->rl_base);
1902 fptr->file_dyn_base = fptr->file_lo->rl_base;
1906 * Fill in the PLT information for this file if a PLT symbol is found.
1908 if (sym_by_name(&fptr->file_dynsym, "_PROCEDURE_LINKAGE_TABLE_", &s,
1909 NULL) != NULL) {
1910 fptr->file_plt_base = s.st_value + fptr->file_dyn_base;
1911 fptr->file_plt_size = (plt != NULL) ? plt->c_shdr.sh_size : 0;
1914 * Bring the load object up to date; it is the only way the
1915 * user has to access the PLT data. The PLT information in the
1916 * rd_loadobj_t is not set in the call to map_iter() (the
1917 * callback for rd_loadobj_iter) where we set file_lo.
1919 fptr->file_lo->rl_plt_base = fptr->file_plt_base;
1920 fptr->file_lo->rl_plt_size = fptr->file_plt_size;
1922 dprintf("PLT found at %p, size = %lu\n",
1923 (void *)fptr->file_plt_base, (ulong_t)fptr->file_plt_size);
1927 * Fill in the PLT information.
1929 if (dyn != NULL) {
1930 uintptr_t dynaddr = dyn->c_shdr.sh_addr + fptr->file_dyn_base;
1931 size_t ndyn = dyn->c_shdr.sh_size / dyn->c_shdr.sh_entsize;
1932 GElf_Dyn d;
1934 for (i = 0; i < ndyn; i++) {
1935 if (gelf_getdyn(dyn->c_data, i, &d) == NULL)
1936 continue;
1938 switch (d.d_tag) {
1939 case DT_JMPREL:
1940 dprintf("DT_JMPREL is %p\n",
1941 (void *)(uintptr_t)d.d_un.d_ptr);
1942 fptr->file_jmp_rel =
1943 d.d_un.d_ptr + fptr->file_dyn_base;
1944 break;
1945 case DT_STRTAB:
1946 dprintf("DT_STRTAB is %p\n",
1947 (void *)(uintptr_t)d.d_un.d_ptr);
1948 break;
1949 case DT_PLTGOT:
1950 dprintf("DT_PLTGOT is %p\n",
1951 (void *)(uintptr_t)d.d_un.d_ptr);
1952 break;
1953 case DT_SUNW_SYMTAB:
1954 dprintf("DT_SUNW_SYMTAB is %p\n",
1955 (void *)(uintptr_t)d.d_un.d_ptr);
1956 break;
1957 case DT_SYMTAB:
1958 dprintf("DT_SYMTAB is %p\n",
1959 (void *)(uintptr_t)d.d_un.d_ptr);
1960 break;
1961 case DT_HASH:
1962 dprintf("DT_HASH is %p\n",
1963 (void *)(uintptr_t)d.d_un.d_ptr);
1964 break;
1968 dprintf("_DYNAMIC found at %p, %lu entries, DT_JMPREL = %p\n",
1969 (void *)dynaddr, (ulong_t)ndyn, (void *)fptr->file_jmp_rel);
1972 done:
1973 free(cache);
1974 return;
1976 bad:
1977 free(cache);
1979 (void) elf_end(elf);
1980 fptr->file_elf = NULL;
1981 if (fptr->file_elfmem != NULL) {
1982 free(fptr->file_elfmem);
1983 fptr->file_elfmem = NULL;
1985 (void) close(fptr->file_fd);
1986 fptr->file_fd = -1;
1990 * Given a process virtual address, return the map_info_t containing it.
1991 * If none found, return NULL.
1993 map_info_t *
1994 Paddr2mptr(struct ps_prochandle *P, uintptr_t addr)
1996 int lo = 0;
1997 int hi = P->map_count - 1;
1998 int mid;
1999 map_info_t *mp;
2001 while (lo <= hi) {
2003 mid = (lo + hi) / 2;
2004 mp = &P->mappings[mid];
2006 /* check that addr is in [vaddr, vaddr + size) */
2007 if ((addr - mp->map_pmap.pr_vaddr) < mp->map_pmap.pr_size)
2008 return (mp);
2010 if (addr < mp->map_pmap.pr_vaddr)
2011 hi = mid - 1;
2012 else
2013 lo = mid + 1;
2016 return (NULL);
2020 * Return the map_info_t for the executable file.
2021 * If not found, return NULL.
2023 static map_info_t *
2024 exec_map(struct ps_prochandle *P)
2026 uint_t i;
2027 map_info_t *mptr;
2028 map_info_t *mold = NULL;
2029 file_info_t *fptr;
2030 uintptr_t base;
2032 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) {
2033 if (mptr->map_pmap.pr_mapname[0] == '\0')
2034 continue;
2035 if (strcmp(mptr->map_pmap.pr_mapname, "a.out") == 0) {
2036 if ((fptr = mptr->map_file) != NULL &&
2037 fptr->file_lo != NULL) {
2038 base = fptr->file_lo->rl_base;
2039 if (base >= mptr->map_pmap.pr_vaddr &&
2040 base < mptr->map_pmap.pr_vaddr +
2041 mptr->map_pmap.pr_size) /* text space */
2042 return (mptr);
2043 mold = mptr; /* must be the data */
2044 continue;
2046 /* This is a poor way to test for text space */
2047 if (!(mptr->map_pmap.pr_mflags & MA_EXEC) ||
2048 (mptr->map_pmap.pr_mflags & MA_WRITE)) {
2049 mold = mptr;
2050 continue;
2052 return (mptr);
2056 return (mold);
2060 * Given a shared object name, return the map_info_t for it. If no matching
2061 * object is found, return NULL. Normally, the link maps contain the full
2062 * object pathname, e.g. /usr/lib/libc.so.1. We allow the object name to
2063 * take one of the following forms:
2065 * 1. An exact match (i.e. a full pathname): "/usr/lib/libc.so.1"
2066 * 2. An exact basename match: "libc.so.1"
2067 * 3. An initial basename match up to a '.' suffix: "libc.so" or "libc"
2068 * 4. The literal string "a.out" is an alias for the executable mapping
2070 * The third case is a convenience for callers and may not be necessary.
2072 * As the exact same object name may be loaded on different link maps (see
2073 * dlmopen(3DL)), we also allow the caller to resolve the object name by
2074 * specifying a particular link map id. If lmid is PR_LMID_EVERY, the
2075 * first matching name will be returned, regardless of the link map id.
2077 static map_info_t *
2078 object_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *objname)
2080 map_info_t *mp;
2081 file_info_t *fp;
2082 size_t objlen;
2083 uint_t i;
2086 * If we have no rtld_db, then always treat a request as one for all
2087 * link maps.
2089 if (P->rap == NULL)
2090 lmid = PR_LMID_EVERY;
2093 * First pass: look for exact matches of the entire pathname or
2094 * basename (cases 1 and 2 above):
2096 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) {
2098 if (mp->map_pmap.pr_mapname[0] == '\0' ||
2099 (fp = mp->map_file) == NULL ||
2100 ((fp->file_lname == NULL) && (fp->file_rname == NULL)))
2101 continue;
2103 if (lmid != PR_LMID_EVERY &&
2104 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident))
2105 continue;
2108 * If we match, return the primary text mapping; otherwise
2109 * just return the mapping we matched.
2111 if ((fp->file_lbase && strcmp(fp->file_lbase, objname) == 0) ||
2112 (fp->file_rbase && strcmp(fp->file_rbase, objname) == 0) ||
2113 (fp->file_lname && strcmp(fp->file_lname, objname) == 0) ||
2114 (fp->file_rname && strcmp(fp->file_rname, objname) == 0))
2115 return (fp->file_map ? fp->file_map : mp);
2118 objlen = strlen(objname);
2121 * Second pass: look for partial matches (case 3 above):
2123 for (i = 0, mp = P->mappings; i < P->map_count; i++, mp++) {
2125 if (mp->map_pmap.pr_mapname[0] == '\0' ||
2126 (fp = mp->map_file) == NULL ||
2127 ((fp->file_lname == NULL) && (fp->file_rname == NULL)))
2128 continue;
2130 if (lmid != PR_LMID_EVERY &&
2131 (fp->file_lo == NULL || lmid != fp->file_lo->rl_lmident))
2132 continue;
2135 * If we match, return the primary text mapping; otherwise
2136 * just return the mapping we matched.
2138 if ((fp->file_lbase != NULL) &&
2139 (strncmp(fp->file_lbase, objname, objlen) == 0) &&
2140 (fp->file_lbase[objlen] == '.'))
2141 return (fp->file_map ? fp->file_map : mp);
2142 if ((fp->file_rbase != NULL) &&
2143 (strncmp(fp->file_rbase, objname, objlen) == 0) &&
2144 (fp->file_rbase[objlen] == '.'))
2145 return (fp->file_map ? fp->file_map : mp);
2149 * One last check: we allow "a.out" to always alias the executable,
2150 * assuming this name was not in use for something else.
2152 if ((lmid == PR_LMID_EVERY || lmid == LM_ID_BASE) &&
2153 (strcmp(objname, "a.out") == 0))
2154 return (P->map_exec);
2156 return (NULL);
2159 static map_info_t *
2160 object_name_to_map(struct ps_prochandle *P, Lmid_t lmid, const char *name)
2162 map_info_t *mptr;
2164 if (!P->info_valid)
2165 Pupdate_maps(P);
2167 if (P->map_exec == NULL && ((mptr = Paddr2mptr(P,
2168 Pgetauxval(P, AT_ENTRY))) != NULL || (mptr = exec_map(P)) != NULL))
2169 P->map_exec = mptr;
2171 if (P->map_ldso == NULL && (mptr = Paddr2mptr(P,
2172 Pgetauxval(P, AT_BASE))) != NULL)
2173 P->map_ldso = mptr;
2175 if (name == PR_OBJ_EXEC)
2176 mptr = P->map_exec;
2177 else if (name == PR_OBJ_LDSO)
2178 mptr = P->map_ldso;
2179 else if (Prd_agent(P) != NULL || P->state == PS_IDLE)
2180 mptr = object_to_map(P, lmid, name);
2181 else
2182 mptr = NULL;
2184 return (mptr);
2188 * When two symbols are found by address, decide which one is to be preferred.
2190 static GElf_Sym *
2191 sym_prefer(GElf_Sym *sym1, char *name1, GElf_Sym *sym2, char *name2)
2194 * Prefer the non-NULL symbol.
2196 if (sym1 == NULL)
2197 return (sym2);
2198 if (sym2 == NULL)
2199 return (sym1);
2202 * Defer to the sort ordering...
2204 return (byaddr_cmp_common(sym1, name1, sym2, name2) <= 0 ? sym1 : sym2);
2208 * Use a binary search to do the work of sym_by_addr().
2210 static GElf_Sym *
2211 sym_by_addr_binary(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp,
2212 uint_t *idp)
2214 GElf_Sym sym, osym;
2215 uint_t i, oid, *byaddr = symtab->sym_byaddr;
2216 int min, max, mid, omid, found = 0;
2218 if (symtab->sym_data_pri == NULL || symtab->sym_count == 0)
2219 return (NULL);
2221 min = 0;
2222 max = symtab->sym_count - 1;
2223 osym.st_value = 0;
2226 * We can't return when we've found a match, we have to continue
2227 * searching for the closest matching symbol.
2229 while (min <= max) {
2230 mid = (max + min) / 2;
2232 i = byaddr[mid];
2233 (void) symtab_getsym(symtab, i, &sym);
2235 if (addr >= sym.st_value &&
2236 addr < sym.st_value + sym.st_size &&
2237 (!found || sym.st_value > osym.st_value)) {
2238 osym = sym;
2239 omid = mid;
2240 oid = i;
2241 found = 1;
2244 if (addr < sym.st_value)
2245 max = mid - 1;
2246 else
2247 min = mid + 1;
2250 if (!found)
2251 return (NULL);
2254 * There may be many symbols with identical values so we walk
2255 * backward in the byaddr table to find the best match.
2257 do {
2258 sym = osym;
2259 i = oid;
2261 if (omid == 0)
2262 break;
2264 oid = byaddr[--omid];
2265 (void) symtab_getsym(symtab, oid, &osym);
2266 } while (addr >= osym.st_value &&
2267 addr < sym.st_value + osym.st_size &&
2268 osym.st_value == sym.st_value);
2270 *symp = sym;
2271 if (idp != NULL)
2272 *idp = i;
2273 return (symp);
2277 * Use a linear search to do the work of sym_by_addr().
2279 static GElf_Sym *
2280 sym_by_addr_linear(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symbolp,
2281 uint_t *idp)
2283 size_t symn = symtab->sym_symn;
2284 char *strs = symtab->sym_strs;
2285 GElf_Sym sym, *symp = NULL;
2286 GElf_Sym osym, *osymp = NULL;
2287 int i, id;
2289 if (symtab->sym_data_pri == NULL || symn == 0 || strs == NULL)
2290 return (NULL);
2292 for (i = 0; i < symn; i++) {
2293 if ((symp = symtab_getsym(symtab, i, &sym)) != NULL) {
2294 if (addr >= sym.st_value &&
2295 addr < sym.st_value + sym.st_size) {
2296 if (osymp)
2297 symp = sym_prefer(
2298 symp, strs + symp->st_name,
2299 osymp, strs + osymp->st_name);
2300 if (symp != osymp) {
2301 osym = sym;
2302 osymp = &osym;
2303 id = i;
2308 if (osymp) {
2309 *symbolp = osym;
2310 if (idp)
2311 *idp = id;
2312 return (symbolp);
2314 return (NULL);
2318 * Look up a symbol by address in the specified symbol table.
2319 * Adjustment to 'addr' must already have been made for the
2320 * offset of the symbol if this is a dynamic library symbol table.
2322 * Use a linear or a binary search depending on whether or not we
2323 * chose to sort the table in optimize_symtab().
2325 static GElf_Sym *
2326 sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp)
2328 if (_libproc_no_qsort) {
2329 return (sym_by_addr_linear(symtab, addr, symp, idp));
2330 } else {
2331 return (sym_by_addr_binary(symtab, addr, symp, idp));
2336 * Use a binary search to do the work of sym_by_name().
2338 static GElf_Sym *
2339 sym_by_name_binary(sym_tbl_t *symtab, const char *name, GElf_Sym *symp,
2340 uint_t *idp)
2342 char *strs = symtab->sym_strs;
2343 uint_t i, *byname = symtab->sym_byname;
2344 int min, mid, max, cmp;
2346 if (symtab->sym_data_pri == NULL || strs == NULL ||
2347 symtab->sym_count == 0)
2348 return (NULL);
2350 min = 0;
2351 max = symtab->sym_count - 1;
2353 while (min <= max) {
2354 mid = (max + min) / 2;
2356 i = byname[mid];
2357 (void) symtab_getsym(symtab, i, symp);
2359 if ((cmp = strcmp(name, strs + symp->st_name)) == 0) {
2360 if (idp != NULL)
2361 *idp = i;
2362 return (symp);
2365 if (cmp < 0)
2366 max = mid - 1;
2367 else
2368 min = mid + 1;
2371 return (NULL);
2375 * Use a linear search to do the work of sym_by_name().
2377 static GElf_Sym *
2378 sym_by_name_linear(sym_tbl_t *symtab, const char *name, GElf_Sym *symp,
2379 uint_t *idp)
2381 size_t symn = symtab->sym_symn;
2382 char *strs = symtab->sym_strs;
2383 int i;
2385 if (symtab->sym_data_pri == NULL || symn == 0 || strs == NULL)
2386 return (NULL);
2388 for (i = 0; i < symn; i++) {
2389 if (symtab_getsym(symtab, i, symp) &&
2390 strcmp(name, strs + symp->st_name) == 0) {
2391 if (idp)
2392 *idp = i;
2393 return (symp);
2397 return (NULL);
2401 * Look up a symbol by name in the specified symbol table.
2403 * Use a linear or a binary search depending on whether or not we
2404 * chose to sort the table in optimize_symtab().
2406 static GElf_Sym *
2407 sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp)
2409 if (_libproc_no_qsort) {
2410 return (sym_by_name_linear(symtab, name, symp, idp));
2411 } else {
2412 return (sym_by_name_binary(symtab, name, symp, idp));
2417 * Search the process symbol tables looking for a symbol whose
2418 * value to value+size contain the address specified by addr.
2419 * Return values are:
2420 * sym_name_buffer containing the symbol name
2421 * GElf_Sym symbol table entry
2422 * prsyminfo_t ancillary symbol information
2423 * Returns 0 on success, -1 on failure.
2425 static int
2426 i_Pxlookup_by_addr(
2427 struct ps_prochandle *P,
2428 int lmresolve, /* use resolve linker object names */
2429 uintptr_t addr, /* process address being sought */
2430 char *sym_name_buffer, /* buffer for the symbol name */
2431 size_t bufsize, /* size of sym_name_buffer */
2432 GElf_Sym *symbolp, /* returned symbol table entry */
2433 prsyminfo_t *sip) /* returned symbol info */
2435 GElf_Sym *symp;
2436 char *name;
2437 GElf_Sym sym1, *sym1p = NULL;
2438 GElf_Sym sym2, *sym2p = NULL;
2439 char *name1 = NULL;
2440 char *name2 = NULL;
2441 uint_t i1;
2442 uint_t i2;
2443 map_info_t *mptr;
2444 file_info_t *fptr;
2446 (void) Prd_agent(P);
2448 if ((mptr = Paddr2mptr(P, addr)) == NULL || /* no such address */
2449 (fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */
2450 fptr->file_elf == NULL) /* not an ELF file */
2451 return (-1);
2454 * Adjust the address by the load object base address in
2455 * case the address turns out to be in a shared library.
2457 addr -= fptr->file_dyn_base;
2460 * Search both symbol tables, symtab first, then dynsym.
2462 if ((sym1p = sym_by_addr(&fptr->file_symtab, addr, &sym1, &i1)) != NULL)
2463 name1 = fptr->file_symtab.sym_strs + sym1.st_name;
2464 if ((sym2p = sym_by_addr(&fptr->file_dynsym, addr, &sym2, &i2)) != NULL)
2465 name2 = fptr->file_dynsym.sym_strs + sym2.st_name;
2467 if ((symp = sym_prefer(sym1p, name1, sym2p, name2)) == NULL)
2468 return (-1);
2470 name = (symp == sym1p) ? name1 : name2;
2471 if (bufsize > 0) {
2472 (void) strncpy(sym_name_buffer, name, bufsize);
2473 sym_name_buffer[bufsize - 1] = '\0';
2476 *symbolp = *symp;
2477 if (sip != NULL) {
2478 sip->prs_name = bufsize == 0 ? NULL : sym_name_buffer;
2479 if (lmresolve && (fptr->file_rname != NULL))
2480 sip->prs_object = fptr->file_rbase;
2481 else
2482 sip->prs_object = fptr->file_lbase;
2483 sip->prs_id = (symp == sym1p) ? i1 : i2;
2484 sip->prs_table = (symp == sym1p) ? PR_SYMTAB : PR_DYNSYM;
2485 sip->prs_lmid = (fptr->file_lo == NULL) ? LM_ID_BASE :
2486 fptr->file_lo->rl_lmident;
2489 if (GELF_ST_TYPE(symbolp->st_info) != STT_TLS)
2490 symbolp->st_value += fptr->file_dyn_base;
2492 return (0);
2496 Pxlookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf,
2497 size_t bufsize, GElf_Sym *symp, prsyminfo_t *sip)
2499 return (i_Pxlookup_by_addr(P, B_FALSE, addr, buf, bufsize, symp, sip));
2503 Pxlookup_by_addr_resolved(struct ps_prochandle *P, uintptr_t addr, char *buf,
2504 size_t bufsize, GElf_Sym *symp, prsyminfo_t *sip)
2506 return (i_Pxlookup_by_addr(P, B_TRUE, addr, buf, bufsize, symp, sip));
2510 Plookup_by_addr(struct ps_prochandle *P, uintptr_t addr, char *buf,
2511 size_t size, GElf_Sym *symp)
2513 return (i_Pxlookup_by_addr(P, B_FALSE, addr, buf, size, symp, NULL));
2517 * Search the process symbol tables looking for a symbol whose name matches the
2518 * specified name and whose object and link map optionally match the specified
2519 * parameters. On success, the function returns 0 and fills in the GElf_Sym
2520 * symbol table entry. On failure, -1 is returned.
2523 Pxlookup_by_name(
2524 struct ps_prochandle *P,
2525 Lmid_t lmid, /* link map to match, or -1 for any */
2526 const char *oname, /* load object name */
2527 const char *sname, /* symbol name */
2528 GElf_Sym *symp, /* returned symbol table entry */
2529 prsyminfo_t *sip) /* returned symbol info */
2531 map_info_t *mptr;
2532 file_info_t *fptr;
2533 int cnt;
2535 GElf_Sym sym;
2536 prsyminfo_t si;
2537 int rv = -1;
2538 uint_t id;
2540 if (oname == PR_OBJ_EVERY) {
2541 /* create all the file_info_t's for all the mappings */
2542 (void) Prd_agent(P);
2543 cnt = P->num_files;
2544 fptr = list_next(&P->file_head);
2545 } else {
2546 cnt = 1;
2547 if ((mptr = object_name_to_map(P, lmid, oname)) == NULL ||
2548 (fptr = build_map_symtab(P, mptr)) == NULL)
2549 return (-1);
2553 * Iterate through the loaded object files and look for the symbol
2554 * name in the .symtab and .dynsym of each. If we encounter a match
2555 * with SHN_UNDEF, keep looking in hopes of finding a better match.
2556 * This means that a name such as "puts" will match the puts function
2557 * in libc instead of matching the puts PLT entry in the a.out file.
2559 for (; cnt > 0; cnt--, fptr = list_next(fptr)) {
2560 Pbuild_file_symtab(P, fptr);
2562 if (fptr->file_elf == NULL)
2563 continue;
2565 if (lmid != PR_LMID_EVERY && fptr->file_lo != NULL &&
2566 lmid != fptr->file_lo->rl_lmident)
2567 continue;
2569 if (fptr->file_symtab.sym_data_pri != NULL &&
2570 sym_by_name(&fptr->file_symtab, sname, symp, &id)) {
2571 if (sip != NULL) {
2572 sip->prs_id = id;
2573 sip->prs_table = PR_SYMTAB;
2574 sip->prs_object = oname;
2575 sip->prs_name = sname;
2576 sip->prs_lmid = fptr->file_lo == NULL ?
2577 LM_ID_BASE : fptr->file_lo->rl_lmident;
2579 } else if (fptr->file_dynsym.sym_data_pri != NULL &&
2580 sym_by_name(&fptr->file_dynsym, sname, symp, &id)) {
2581 if (sip != NULL) {
2582 sip->prs_id = id;
2583 sip->prs_table = PR_DYNSYM;
2584 sip->prs_object = oname;
2585 sip->prs_name = sname;
2586 sip->prs_lmid = fptr->file_lo == NULL ?
2587 LM_ID_BASE : fptr->file_lo->rl_lmident;
2589 } else {
2590 continue;
2593 if (GELF_ST_TYPE(symp->st_info) != STT_TLS)
2594 symp->st_value += fptr->file_dyn_base;
2596 if (symp->st_shndx != SHN_UNDEF)
2597 return (0);
2599 if (rv != 0) {
2600 if (sip != NULL)
2601 si = *sip;
2602 sym = *symp;
2603 rv = 0;
2607 if (rv == 0) {
2608 if (sip != NULL)
2609 *sip = si;
2610 *symp = sym;
2613 return (rv);
2617 * Search the process symbol tables looking for a symbol whose name matches the
2618 * specified name, but without any restriction on the link map id.
2621 Plookup_by_name(struct ps_prochandle *P, const char *object,
2622 const char *symbol, GElf_Sym *symp)
2624 return (Pxlookup_by_name(P, PR_LMID_EVERY, object, symbol, symp, NULL));
2628 * Iterate over the process's address space mappings.
2630 static int
2631 i_Pmapping_iter(struct ps_prochandle *P, boolean_t lmresolve,
2632 proc_map_f *func, void *cd)
2634 map_info_t *mptr;
2635 file_info_t *fptr;
2636 char *object_name;
2637 int rc = 0;
2638 int i;
2640 /* create all the file_info_t's for all the mappings */
2641 (void) Prd_agent(P);
2643 for (i = 0, mptr = P->mappings; i < P->map_count; i++, mptr++) {
2644 if ((fptr = mptr->map_file) == NULL)
2645 object_name = NULL;
2646 else if (lmresolve && (fptr->file_rname != NULL))
2647 object_name = fptr->file_rname;
2648 else
2649 object_name = fptr->file_lname;
2650 if ((rc = func(cd, &mptr->map_pmap, object_name)) != 0)
2651 return (rc);
2653 return (0);
2657 Pmapping_iter(struct ps_prochandle *P, proc_map_f *func, void *cd)
2659 return (i_Pmapping_iter(P, B_FALSE, func, cd));
2663 Pmapping_iter_resolved(struct ps_prochandle *P, proc_map_f *func, void *cd)
2665 return (i_Pmapping_iter(P, B_TRUE, func, cd));
2669 * Iterate over the process's mapped objects.
2671 static int
2672 i_Pobject_iter(struct ps_prochandle *P, boolean_t lmresolve,
2673 proc_map_f *func, void *cd)
2675 map_info_t *mptr;
2676 file_info_t *fptr;
2677 uint_t cnt;
2678 int rc = 0;
2680 (void) Prd_agent(P); /* create file_info_t's for all the mappings */
2681 Pupdate_maps(P);
2683 for (cnt = P->num_files, fptr = list_next(&P->file_head);
2684 cnt; cnt--, fptr = list_next(fptr)) {
2685 const char *lname;
2687 if (lmresolve && (fptr->file_rname != NULL))
2688 lname = fptr->file_rname;
2689 else if (fptr->file_lname != NULL)
2690 lname = fptr->file_lname;
2691 else
2692 lname = "";
2694 if ((mptr = fptr->file_map) == NULL)
2695 continue;
2697 if ((rc = func(cd, &mptr->map_pmap, lname)) != 0)
2698 return (rc);
2700 if (!P->info_valid)
2701 Pupdate_maps(P);
2703 return (0);
2707 Pobject_iter(struct ps_prochandle *P, proc_map_f *func, void *cd)
2709 return (i_Pobject_iter(P, B_FALSE, func, cd));
2713 Pobject_iter_resolved(struct ps_prochandle *P, proc_map_f *func, void *cd)
2715 return (i_Pobject_iter(P, B_TRUE, func, cd));
2718 static char *
2719 i_Pobjname(struct ps_prochandle *P, boolean_t lmresolve, uintptr_t addr,
2720 char *buffer, size_t bufsize)
2722 map_info_t *mptr;
2723 file_info_t *fptr;
2725 /* create all the file_info_t's for all the mappings */
2726 (void) Prd_agent(P);
2728 if ((mptr = Paddr2mptr(P, addr)) == NULL)
2729 return (NULL);
2731 if (!lmresolve) {
2732 if (((fptr = mptr->map_file) == NULL) ||
2733 (fptr->file_lname == NULL))
2734 return (NULL);
2735 (void) strlcpy(buffer, fptr->file_lname, bufsize);
2736 return (buffer);
2739 /* Check for a cached copy of the resolved path */
2740 if (Pfindmap(P, mptr, buffer, bufsize) != NULL)
2741 return (buffer);
2743 return (NULL);
2747 * Given a virtual address, return the name of the underlying
2748 * mapped object (file) as provided by the dynamic linker.
2749 * Return NULL if we can't find any name information for the object.
2751 char *
2752 Pobjname(struct ps_prochandle *P, uintptr_t addr,
2753 char *buffer, size_t bufsize)
2755 return (i_Pobjname(P, B_FALSE, addr, buffer, bufsize));
2759 * Given a virtual address, try to return a filesystem path to the
2760 * underlying mapped object (file). If we're in the global zone,
2761 * this path could resolve to an object in another zone. If we're
2762 * unable return a valid filesystem path, we'll fall back to providing
2763 * the mapped object (file) name provided by the dynamic linker in
2764 * the target process (ie, the object reported by Pobjname()).
2766 char *
2767 Pobjname_resolved(struct ps_prochandle *P, uintptr_t addr,
2768 char *buffer, size_t bufsize)
2770 return (i_Pobjname(P, B_TRUE, addr, buffer, bufsize));
2774 * Given a virtual address, return the link map id of the underlying mapped
2775 * object (file), as provided by the dynamic linker. Return -1 on failure.
2778 Plmid(struct ps_prochandle *P, uintptr_t addr, Lmid_t *lmidp)
2780 map_info_t *mptr;
2781 file_info_t *fptr;
2783 /* create all the file_info_t's for all the mappings */
2784 (void) Prd_agent(P);
2786 if ((mptr = Paddr2mptr(P, addr)) != NULL &&
2787 (fptr = mptr->map_file) != NULL && fptr->file_lo != NULL) {
2788 *lmidp = fptr->file_lo->rl_lmident;
2789 return (0);
2792 return (-1);
2796 * Given an object name and optional lmid, iterate over the object's symbols.
2797 * If which == PR_SYMTAB, search the normal symbol table.
2798 * If which == PR_DYNSYM, search the dynamic symbol table.
2800 static int
2801 Psymbol_iter_com(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
2802 int which, int mask, pr_order_t order, proc_xsym_f *func, void *cd)
2804 #if STT_NUM != (STT_TLS + 1)
2805 #error "STT_NUM has grown. update Psymbol_iter_com()"
2806 #endif
2808 GElf_Sym sym;
2809 GElf_Shdr shdr;
2810 map_info_t *mptr;
2811 file_info_t *fptr;
2812 sym_tbl_t *symtab;
2813 size_t symn;
2814 const char *strs;
2815 size_t strsz;
2816 prsyminfo_t si;
2817 int rv;
2818 uint_t *map, i, count, ndx;
2820 if ((mptr = object_name_to_map(P, lmid, object_name)) == NULL)
2821 return (-1);
2823 if ((fptr = build_map_symtab(P, mptr)) == NULL || /* no mapped file */
2824 fptr->file_elf == NULL) /* not an ELF file */
2825 return (-1);
2828 * Search the specified symbol table.
2830 switch (which) {
2831 case PR_SYMTAB:
2832 symtab = &fptr->file_symtab;
2833 si.prs_table = PR_SYMTAB;
2834 break;
2835 case PR_DYNSYM:
2836 symtab = &fptr->file_dynsym;
2837 si.prs_table = PR_DYNSYM;
2838 break;
2839 default:
2840 return (-1);
2843 si.prs_object = object_name;
2844 si.prs_lmid = fptr->file_lo == NULL ?
2845 LM_ID_BASE : fptr->file_lo->rl_lmident;
2847 symn = symtab->sym_symn;
2848 strs = symtab->sym_strs;
2849 strsz = symtab->sym_strsz;
2851 switch (order) {
2852 case PRO_NATURAL:
2853 map = NULL;
2854 count = symn;
2855 break;
2856 case PRO_BYNAME:
2857 map = symtab->sym_byname;
2858 count = symtab->sym_count;
2859 break;
2860 case PRO_BYADDR:
2861 map = symtab->sym_byaddr;
2862 count = symtab->sym_count;
2863 break;
2864 default:
2865 return (-1);
2868 if (symtab->sym_data_pri == NULL || strs == NULL || count == 0)
2869 return (-1);
2871 rv = 0;
2873 for (i = 0; i < count; i++) {
2874 ndx = map == NULL ? i : map[i];
2875 if (symtab_getsym(symtab, ndx, &sym) != NULL) {
2876 uint_t s_bind, s_type, type;
2878 if (sym.st_name >= strsz) /* invalid st_name */
2879 continue;
2881 s_bind = GELF_ST_BIND(sym.st_info);
2882 s_type = GELF_ST_TYPE(sym.st_info);
2885 * In case you haven't already guessed, this relies on
2886 * the bitmask used in <libproc.h> for encoding symbol
2887 * type and binding matching the order of STB and STT
2888 * constants in <sys/elf.h>. Changes to ELF must
2889 * maintain binary compatibility, so I think this is
2890 * reasonably fair game.
2892 if (s_bind < STB_NUM && s_type < STT_NUM) {
2893 type = (1 << (s_type + 8)) | (1 << s_bind);
2894 if ((type & ~mask) != 0)
2895 continue;
2896 } else
2897 continue; /* Invalid type or binding */
2899 if (GELF_ST_TYPE(sym.st_info) != STT_TLS)
2900 sym.st_value += fptr->file_dyn_base;
2902 si.prs_name = strs + sym.st_name;
2905 * If symbol's type is STT_SECTION, then try to lookup
2906 * the name of the corresponding section.
2908 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
2909 fptr->file_shstrs != NULL &&
2910 gelf_getshdr(elf_getscn(fptr->file_elf,
2911 sym.st_shndx), &shdr) != NULL &&
2912 shdr.sh_name != 0 &&
2913 shdr.sh_name < fptr->file_shstrsz)
2914 si.prs_name = fptr->file_shstrs + shdr.sh_name;
2916 si.prs_id = ndx;
2917 if ((rv = func(cd, &sym, si.prs_name, &si)) != 0)
2918 break;
2922 return (rv);
2926 Pxsymbol_iter(struct ps_prochandle *P, Lmid_t lmid, const char *object_name,
2927 int which, int mask, proc_xsym_f *func, void *cd)
2929 return (Psymbol_iter_com(P, lmid, object_name, which, mask,
2930 PRO_NATURAL, func, cd));
2934 Psymbol_iter_by_lmid(struct ps_prochandle *P, Lmid_t lmid,
2935 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2937 return (Psymbol_iter_com(P, lmid, object_name, which, mask,
2938 PRO_NATURAL, (proc_xsym_f *)func, cd));
2942 Psymbol_iter(struct ps_prochandle *P,
2943 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2945 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2946 PRO_NATURAL, (proc_xsym_f *)func, cd));
2950 Psymbol_iter_by_addr(struct ps_prochandle *P,
2951 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2953 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2954 PRO_BYADDR, (proc_xsym_f *)func, cd));
2958 Psymbol_iter_by_name(struct ps_prochandle *P,
2959 const char *object_name, int which, int mask, proc_sym_f *func, void *cd)
2961 return (Psymbol_iter_com(P, PR_LMID_EVERY, object_name, which, mask,
2962 PRO_BYNAME, (proc_xsym_f *)func, cd));
2966 * Get the platform string.
2968 char *
2969 Pplatform(struct ps_prochandle *P, char *s, size_t n)
2971 return (P->ops.pop_platform(P, s, n, P->data));
2975 * Get the uname(2) information.
2978 Puname(struct ps_prochandle *P, struct utsname *u)
2980 return (P->ops.pop_uname(P, u, P->data));
2984 * Called from Pcreate(), Pgrab(), and Pfgrab_core() to initialize
2985 * the symbol table heads in the new ps_prochandle.
2987 void
2988 Pinitsym(struct ps_prochandle *P)
2990 P->num_files = 0;
2991 list_link(&P->file_head, NULL);
2995 * Called from Prelease() to destroy the symbol tables.
2996 * Must be called by the client after an exec() in the victim process.
2998 void
2999 Preset_maps(struct ps_prochandle *P)
3001 int i;
3003 if (P->rap != NULL) {
3004 rd_delete(P->rap);
3005 P->rap = NULL;
3008 if (P->execname != NULL) {
3009 free(P->execname);
3010 P->execname = NULL;
3013 if (P->auxv != NULL) {
3014 free(P->auxv);
3015 P->auxv = NULL;
3016 P->nauxv = 0;
3019 for (i = 0; i < P->map_count; i++)
3020 map_info_free(P, &P->mappings[i]);
3022 if (P->mappings != NULL) {
3023 free(P->mappings);
3024 P->mappings = NULL;
3026 P->map_count = P->map_alloc = 0;
3028 P->info_valid = 0;
3031 typedef struct getenv_data {
3032 char *buf;
3033 size_t bufsize;
3034 const char *search;
3035 size_t searchlen;
3036 } getenv_data_t;
3038 /*ARGSUSED*/
3039 static int
3040 getenv_func(void *data, struct ps_prochandle *P, uintptr_t addr,
3041 const char *nameval)
3043 getenv_data_t *d = data;
3044 size_t len;
3046 if (nameval == NULL)
3047 return (0);
3049 if (d->searchlen < strlen(nameval) &&
3050 strncmp(nameval, d->search, d->searchlen) == 0 &&
3051 nameval[d->searchlen] == '=') {
3052 len = MIN(strlen(nameval), d->bufsize - 1);
3053 (void) strncpy(d->buf, nameval, len);
3054 d->buf[len] = '\0';
3055 return (1);
3058 return (0);
3061 char *
3062 Pgetenv(struct ps_prochandle *P, const char *name, char *buf, size_t buflen)
3064 getenv_data_t d;
3066 d.buf = buf;
3067 d.bufsize = buflen;
3068 d.search = name;
3069 d.searchlen = strlen(name);
3071 if (Penv_iter(P, getenv_func, &d) == 1) {
3072 char *equals = strchr(d.buf, '=');
3074 if (equals != NULL) {
3075 (void) memmove(d.buf, equals + 1,
3076 d.buf + buflen - equals - 1);
3077 d.buf[d.buf + buflen - equals] = '\0';
3079 return (buf);
3083 return (NULL);
3086 /* number of argument or environment pointers to read all at once */
3087 #define NARG 100
3090 Penv_iter(struct ps_prochandle *P, proc_env_f *func, void *data)
3092 const psinfo_t *psp;
3093 uintptr_t envpoff;
3094 GElf_Sym sym;
3095 int ret;
3096 char *buf, *nameval;
3097 size_t buflen;
3099 int nenv = NARG;
3100 long envp[NARG];
3103 * Attempt to find the "_environ" variable in the process.
3104 * Failing that, use the original value provided by Ppsinfo().
3106 if ((psp = Ppsinfo(P)) == NULL)
3107 return (-1);
3109 envpoff = psp->pr_envp; /* Default if no _environ found */
3111 if (Plookup_by_name(P, PR_OBJ_EXEC, "_environ", &sym) == 0) {
3112 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
3113 if (Pread(P, &envpoff, sizeof (envpoff),
3114 sym.st_value) != sizeof (envpoff))
3115 envpoff = psp->pr_envp;
3116 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) {
3117 uint32_t envpoff32;
3119 if (Pread(P, &envpoff32, sizeof (envpoff32),
3120 sym.st_value) != sizeof (envpoff32))
3121 envpoff = psp->pr_envp;
3122 else
3123 envpoff = envpoff32;
3127 buflen = 128;
3128 buf = malloc(buflen);
3130 ret = 0;
3131 for (;;) {
3132 uintptr_t envoff;
3134 if (nenv == NARG) {
3135 (void) memset(envp, 0, sizeof (envp));
3136 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
3137 if (Pread(P, envp,
3138 sizeof (envp), envpoff) <= 0) {
3139 ret = -1;
3140 break;
3142 } else if (P->status.pr_dmodel == PR_MODEL_ILP32) {
3143 uint32_t e32[NARG];
3144 int i;
3146 (void) memset(e32, 0, sizeof (e32));
3147 if (Pread(P, e32, sizeof (e32), envpoff) <= 0) {
3148 ret = -1;
3149 break;
3151 for (i = 0; i < NARG; i++)
3152 envp[i] = e32[i];
3154 nenv = 0;
3157 if ((envoff = envp[nenv++]) == (uintptr_t)NULL)
3158 break;
3161 * Attempt to read the string from the process.
3163 again:
3164 ret = Pread_string(P, buf, buflen, envoff);
3166 if (ret <= 0) {
3167 nameval = NULL;
3168 } else if (ret == buflen - 1) {
3169 free(buf);
3171 * Bail if we have a corrupted environment
3173 if (buflen >= ARG_MAX)
3174 return (-1);
3175 buflen *= 2;
3176 buf = malloc(buflen);
3177 goto again;
3178 } else {
3179 nameval = buf;
3182 if ((ret = func(data, P, envoff, nameval)) != 0)
3183 break;
3185 envpoff += (P->status.pr_dmodel == PR_MODEL_LP64)? 8 : 4;
3188 free(buf);
3190 return (ret);