diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.c | 64 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.h | 1 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcore.c | 102 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Psymtab.c | 215 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/libproc.h | 2 |
5 files changed, 271 insertions, 113 deletions
diff --git a/usr/src/lib/libproc/common/Pcontrol.c b/usr/src/lib/libproc/common/Pcontrol.c index 6cf0c45891..9e3c26fc04 100644 --- a/usr/src/lib/libproc/common/Pcontrol.c +++ b/usr/src/lib/libproc/common/Pcontrol.c @@ -55,6 +55,9 @@ #include "P32ton.h" int _libproc_debug; /* set non-zero to enable debugging printfs */ +int _libproc_no_qsort; /* set non-zero to inhibit sorting */ + /* of symbol tables */ + sigset_t blockable_sigs; /* signals to block when we need to be safe */ static int minfd; /* minimum file descriptor returned by dupfd(fd, 0) */ char procfs_path[PATH_MAX] = "/proc"; @@ -93,6 +96,7 @@ void _libproc_init(void) { _libproc_debug = getenv("LIBPROC_DEBUG") != NULL; + _libproc_no_qsort = getenv("LIBPROC_NO_QSORT") != NULL; (void) sigfillset(&blockable_sigs); (void) sigdelset(&blockable_sigs, SIGKILL); @@ -359,7 +363,7 @@ Pxcreate(const char *file, /* executable file name */ * to get the information later. */ (void) Pread_string(P, execpath, sizeof (execpath), - (off_t)P->status.pr_lwp.pr_sysarg[0]); + (off_t)P->status.pr_lwp.pr_sysarg[0]); if (path != NULL) (void) strncpy(path, execpath, len); /* @@ -1556,23 +1560,23 @@ prldump(const char *caller, lwpstatus_t *lsp) break; case PR_SIGNALLED: dprintf("%s: SIGNALLED %s\n", caller, - proc_signame(lsp->pr_what, name, sizeof (name))); + proc_signame(lsp->pr_what, name, sizeof (name))); break; case PR_FAULTED: dprintf("%s: FAULTED %s\n", caller, - proc_fltname(lsp->pr_what, name, sizeof (name))); + proc_fltname(lsp->pr_what, name, sizeof (name))); break; case PR_SYSENTRY: dprintf("%s: SYSENTRY %s\n", caller, - proc_sysname(lsp->pr_what, name, sizeof (name))); + proc_sysname(lsp->pr_what, name, sizeof (name))); break; case PR_SYSEXIT: dprintf("%s: SYSEXIT %s\n", caller, - proc_sysname(lsp->pr_what, name, sizeof (name))); + proc_sysname(lsp->pr_what, name, sizeof (name))); break; case PR_JOBCONTROL: dprintf("%s: JOBCONTROL %s\n", caller, - proc_signame(lsp->pr_what, name, sizeof (name))); + proc_signame(lsp->pr_what, name, sizeof (name))); break; case PR_SUSPENDED: dprintf("%s: SUSPENDED\n", caller); @@ -1884,8 +1888,8 @@ Psetrun(struct ps_prochandle *P, int sbits = (PR_DSTOP | PR_ISTOP | PR_ASLEEP); long ctl[1 + /* PCCFAULT */ - 1 + sizeof (siginfo_t)/sizeof (long) + /* PCSSIG/PCCSIG */ - 2 ]; /* PCRUN */ + 1 + sizeof (siginfo_t)/sizeof (long) + /* PCSSIG/PCCSIG */ + 2 ]; /* PCRUN */ long *ctlp = ctl; size_t size; @@ -2036,7 +2040,7 @@ int Psetbkpt(struct ps_prochandle *P, uintptr_t address, ulong_t *saved) { long ctl[1 + sizeof (priovec_t) / sizeof (long) + /* PCREAD */ - 1 + sizeof (priovec_t) / sizeof (long)]; /* PCWRITE */ + 1 + sizeof (priovec_t) / sizeof (long)]; /* PCWRITE */ long *ctlp = ctl; size_t size; priovec_t *iovp; @@ -2129,15 +2133,15 @@ execute_bkpt( ulong_t saved) /* the saved instruction */ { long ctl[ - 1 + sizeof (sigset_t) / sizeof (long) + /* PCSHOLD */ - 1 + sizeof (fltset_t) / sizeof (long) + /* PCSFAULT */ - 1 + sizeof (priovec_t) / sizeof (long) + /* PCWRITE */ - 2 + /* PCRUN */ - 1 + /* PCWSTOP */ - 1 + /* PCCFAULT */ - 1 + sizeof (priovec_t) / sizeof (long) + /* PCWRITE */ - 1 + sizeof (fltset_t) / sizeof (long) + /* PCSFAULT */ - 1 + sizeof (sigset_t) / sizeof (long)]; /* PCSHOLD */ + 1 + sizeof (sigset_t) / sizeof (long) + /* PCSHOLD */ + 1 + sizeof (fltset_t) / sizeof (long) + /* PCSFAULT */ + 1 + sizeof (priovec_t) / sizeof (long) + /* PCWRITE */ + 2 + /* PCRUN */ + 1 + /* PCWSTOP */ + 1 + /* PCCFAULT */ + 1 + sizeof (priovec_t) / sizeof (long) + /* PCWRITE */ + 1 + sizeof (fltset_t) / sizeof (long) + /* PCSFAULT */ + 1 + sizeof (sigset_t) / sizeof (long)]; /* PCSHOLD */ long *ctlp = ctl; sigset_t unblock; size_t size; @@ -2231,8 +2235,8 @@ Pxecbkpt(struct ps_prochandle *P, ulong_t saved) Psync(P); error = execute_bkpt(ctlfd, - &P->status.pr_flttrace, &P->status.pr_lwp.pr_lwphold, - P->status.pr_lwp.pr_reg[R_PC], saved); + &P->status.pr_flttrace, &P->status.pr_lwp.pr_lwphold, + P->status.pr_lwp.pr_reg[R_PC], saved); rv = Pstopstatus(P, PCNULL, 0); if (error != 0) { @@ -2425,7 +2429,7 @@ Pxecwapt(struct ps_prochandle *P, const prwatch_t *wp) Psync(P); error = execute_wapt(ctlfd, - &P->status.pr_flttrace, &P->status.pr_lwp.pr_lwphold, wp); + &P->status.pr_flttrace, &P->status.pr_lwp.pr_lwphold, wp); rv = Pstopstatus(P, PCNULL, 0); if (error != 0) { @@ -2820,7 +2824,7 @@ retry: for (i = 0; i < P->core->core_nlwp; i++, lwp = list_prev(lwp)) { sp = (lwp->lwp_psinfo.pr_sname == 'Z')? NULL : - &lwp->lwp_status; + &lwp->lwp_status; if ((rv = func(cd, sp, &lwp->lwp_psinfo)) != 0) break; } @@ -3040,9 +3044,9 @@ Lgrab(struct ps_prochandle *P, lwpid_t lwpid, int *perr) L->lwp_ctlfd = fd; L->lwp_state = - ((L->lwp_status.pr_flags & (PR_STOPPED|PR_ISTOP)) - == (PR_STOPPED|PR_ISTOP))? - PS_STOP : PS_RUN; + ((L->lwp_status.pr_flags & (PR_STOPPED|PR_ISTOP)) + == (PR_STOPPED|PR_ISTOP))? + PS_STOP : PS_RUN; *perr = 0; (void) mutex_unlock(&P->proc_lock); @@ -3412,8 +3416,8 @@ Lsetrun(struct ps_lwphandle *L, int sbits = (PR_DSTOP | PR_ISTOP | PR_ASLEEP); long ctl[1 + /* PCCFAULT */ - 1 + sizeof (siginfo_t)/sizeof (long) + /* PCSSIG/PCCSIG */ - 2 ]; /* PCRUN */ + 1 + sizeof (siginfo_t)/sizeof (long) + /* PCSSIG/PCCSIG */ + 2 ]; /* PCRUN */ long *ctlp = ctl; size_t size; @@ -3503,8 +3507,8 @@ Lxecbkpt(struct ps_lwphandle *L, ulong_t saved) Lsync(L); error = execute_bkpt(L->lwp_ctlfd, - &P->status.pr_flttrace, &L->lwp_status.pr_lwphold, - L->lwp_status.pr_reg[R_PC], saved); + &P->status.pr_flttrace, &L->lwp_status.pr_lwphold, + L->lwp_status.pr_reg[R_PC], saved); rv = Lstopstatus(L, PCNULL, 0); if (error != 0) { @@ -3539,7 +3543,7 @@ Lxecwapt(struct ps_lwphandle *L, const prwatch_t *wp) Lsync(L); error = execute_wapt(L->lwp_ctlfd, - &P->status.pr_flttrace, &L->lwp_status.pr_lwphold, wp); + &P->status.pr_flttrace, &L->lwp_status.pr_lwphold, wp); rv = Lstopstatus(L, PCNULL, 0); if (error != 0) { diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h index 5a4d606c9d..b195db3b63 100644 --- a/usr/src/lib/libproc/common/Pcontrol.h +++ b/usr/src/lib/libproc/common/Pcontrol.h @@ -263,6 +263,7 @@ extern char *Pfindexec(struct ps_prochandle *, const char *, int (*)(const char *, void *), void *); extern int getlwpstatus(struct ps_prochandle *, lwpid_t, lwpstatus_t *); int Pstopstatus(struct ps_prochandle *, long, uint32_t); +extern file_info_t *file_info_new(struct ps_prochandle *, map_info_t *); extern int Padd_mapping(struct ps_prochandle *, off64_t, file_info_t *, prmap_t *); diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c index b4cfea717a..ca109c8158 100644 --- a/usr/src/lib/libproc/common/Pcore.c +++ b/usr/src/lib/libproc/common/Pcore.c @@ -1382,29 +1382,28 @@ core_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P) return (1); /* No mapping; advance to next mapping */ } - if ((fp = mp->map_file) == NULL) { - if ((fp = malloc(sizeof (file_info_t))) == NULL) { - P->core->core_errno = errno; - dprintf("failed to malloc mapping data\n"); - return (0); /* Abort */ - } - - (void) memset(fp, 0, sizeof (file_info_t)); - - list_link(fp, &P->file_head); - mp->map_file = fp; - P->num_files++; - - fp->file_ref = 1; - fp->file_fd = -1; + /* + * Create a new file_info_t for this mapping, and therefore for + * this load object. + * + * If there's an ELF header at the beginning of this mapping, + * file_info_new() will try to use its section headers to + * identify any other mappings that belong to this load object. + */ + if ((fp = mp->map_file) == NULL && + (fp = file_info_new(P, mp)) == NULL) { + P->core->core_errno = errno; + dprintf("failed to malloc mapping data\n"); + return (0); /* Abort */ } + fp->file_map = mp; + /* Create a local copy of the load object representation */ if ((fp->file_lo = malloc(sizeof (rd_loadobj_t))) == NULL) { P->core->core_errno = errno; dprintf("failed to malloc mapping data\n"); return (0); /* Abort */ } - *fp->file_lo = *rlp; if (fp->file_lname == NULL && @@ -1444,51 +1443,60 @@ core_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P) if (fp->file_lname != NULL) fp->file_lbase = basename(fp->file_lname); - /* - * Associate the file and the mapping, and attempt to build - * a symbol table for this file. - */ - (void) strcpy(fp->file_pname, mp->map_pmap.pr_mapname); - fp->file_map = mp; - - Pbuild_file_symtab(P, fp); - - if (fp->file_elf == NULL) { - dprintf("core_iter_mapping: no symtab - going to next\n"); - return (1); /* No symbol table; advance to next mapping */ - } + /* Associate the file and the mapping. */ + (void) strncpy(fp->file_pname, mp->map_pmap.pr_mapname, PRMAPSZ); + fp->file_pname[PRMAPSZ - 1] = '\0'; /* - * Locate the start of a data segment associated with this file. - * Starting with that data segment, name all mappings that - * fall within this file's address range after the file and - * establish their mp->map_file links. + * If no section headers were available then we'll have to + * identify this load object's other mappings with what we've + * got: the start and end of the object's corresponding + * address space. */ - if ((mp = core_find_data(P, fp->file_elf, fp->file_lo)) != NULL) { - dprintf("found data for %s at %p (pr_offset 0x%llx)\n", - fp->file_pname, (void *)fp->file_lo->rl_data_base, - mp->map_pmap.pr_offset); + if (fp->file_saddrs == NULL) { + for (mp = fp->file_map + 1; mp < P->mappings + P->map_count && + mp->map_pmap.pr_vaddr < rlp->rl_bend; mp++) { - for (; mp < P->mappings + P->map_count; mp++) { - if (mp->map_pmap.pr_vaddr > fp->file_lo->rl_bend) - break; if (mp->map_file == NULL) { - dprintf("%s: associating segment at %p\n", + dprintf("core_iter_mapping %s: associating " + "segment at %p\n", fp->file_pname, (void *)mp->map_pmap.pr_vaddr); mp->map_file = fp; fp->file_ref++; } else { - dprintf("%s: segment at %p already associated " - "with %s\n", fp->file_pname, + dprintf("core_iter_mapping %s: segment at " + "%p already associated with %s\n", + fp->file_pname, (void *)mp->map_pmap.pr_vaddr, - mp->map_file->file_pname); + (mp == fp->file_map ? "this file" : + mp->map_file->file_pname)); } + } + } - if (!(mp->map_pmap.pr_mflags & MA_BREAK)) - (void) strcpy(mp->map_pmap.pr_mapname, - fp->file_pname); + /* Ensure that all this file's mappings are named. */ + for (mp = fp->file_map; mp < P->mappings + P->map_count && + mp->map_file == fp; mp++) { + if (mp->map_pmap.pr_mapname[0] == '\0' && + !(mp->map_pmap.pr_mflags & MA_BREAK)) { + (void) strncpy(mp->map_pmap.pr_mapname, fp->file_pname, + PRMAPSZ); + mp->map_pmap.pr_mapname[PRMAPSZ - 1] = '\0'; } + } + + /* Attempt to build a symbol table for this file. */ + Pbuild_file_symtab(P, fp); + if (fp->file_elf == NULL) + dprintf("core_iter_mapping: no symtab for %s\n", + fp->file_pname); + + /* Locate the start of a data segment associated with this file. */ + if ((mp = core_find_data(P, fp->file_elf, fp->file_lo)) != NULL) { + dprintf("found data for %s at %p (pr_offset 0x%llx)\n", + fp->file_pname, (void *)fp->file_lo->rl_data_base, + mp->map_pmap.pr_offset); } else { dprintf("core_iter_mapping: no data found for %s\n", fp->file_pname); diff --git a/usr/src/lib/libproc/common/Psymtab.c b/usr/src/lib/libproc/common/Psymtab.c index 35107c546b..0b98622759 100644 --- a/usr/src/lib/libproc/common/Psymtab.c +++ b/usr/src/lib/libproc/common/Psymtab.c @@ -171,13 +171,13 @@ get_saddrs(struct ps_prochandle *P, uintptr_t ehdr_start, uint_t *n) /* * Allocation function for a new file_info_t */ -static file_info_t * +file_info_t * file_info_new(struct ps_prochandle *P, map_info_t *mptr) { file_info_t *fptr; map_info_t *mp; - uintptr_t addr; - uint_t i, j; + uintptr_t mstart, mend, sstart, send; + uint_t i; if ((fptr = calloc(1, sizeof (file_info_t))) == NULL) return (NULL); @@ -201,22 +201,38 @@ file_info_new(struct ps_prochandle *P, map_info_t *mptr) &fptr->file_nsaddrs)) == NULL) return (fptr); - i = j = 0; mp = P->mappings; - while (j < P->map_count && i < fptr->file_nsaddrs) { - addr = fptr->file_saddrs[i]; - if (addr >= mp->map_pmap.pr_vaddr && - addr < mp->map_pmap.pr_vaddr + mp->map_pmap.pr_size && - mp->map_file == NULL) { - mp->map_file = fptr; - fptr->file_ref++; - } + i = 0; + while (mp < P->mappings + P->map_count && i < fptr->file_nsaddrs) { - if (addr < mp->map_pmap.pr_vaddr + mp->map_pmap.pr_size) { - i++; + /* Calculate the start and end of the mapping and section */ + mstart = mp->map_pmap.pr_vaddr; + mend = mp->map_pmap.pr_vaddr + mp->map_pmap.pr_size; + sstart = fptr->file_saddrs[i]; + send = fptr->file_saddrs[i + 1]; + + if (mend <= sstart) { + /* This mapping is below the current section */ + mp++; + } else if (mstart >= send) { + /* This mapping is above the current section */ + i += 2; } else { + /* This mapping overlaps the current section */ + if (mp->map_file == NULL) { + dprintf("file_info_new: associating " + "segment at %p\n", + (void *)mp->map_pmap.pr_vaddr); + mp->map_file = fptr; + fptr->file_ref++; + } else { + dprintf("file_info_new: segment at %p " + "already associated with %s\n", + (void *)mp->map_pmap.pr_vaddr, + (mp == mptr ? "this file" : + mp->map_file->file_pname)); + } mp++; - j++; } } @@ -596,9 +612,17 @@ Paddr_to_text_map(struct ps_prochandle *P, uintptr_t addr) file_info_t *fptr = build_map_symtab(P, mptr); const prmap_t *pmp = &mptr->map_pmap; + /* + * Assume that if rl_data_base is NULL, it means that no + * data section was found for this load object, and that + * a section must be text. Otherwise, a section will be + * text unless it ends above the start of the data + * section. + */ if (fptr != NULL && fptr->file_lo != NULL && - fptr->file_lo->rl_base >= pmp->pr_vaddr && - fptr->file_lo->rl_base < pmp->pr_vaddr + pmp->pr_size) + (fptr->file_lo->rl_data_base == NULL || + pmp->pr_vaddr + pmp->pr_size < + fptr->file_lo->rl_data_base)) return (pmp); } @@ -906,6 +930,7 @@ is_mapping_in_file(struct ps_prochandle *P, map_info_t *mptr, file_info_t *fptr) prmap_t *pmap = &mptr->map_pmap; rd_loadobj_t *lop = fptr->file_lo; uint_t i; + uintptr_t mstart, mend, sstart, send; /* * We can get for free the start address of the text and data @@ -927,7 +952,7 @@ is_mapping_in_file(struct ps_prochandle *P, map_info_t *mptr, file_info_t *fptr) * only one will be seen to enclose that section's start address. * Thus, to be rigorous, we ask not whether this mapping encloses * the start of a section, but whether there exists a section that - * encloses the start of this mapping. + * overlaps this mapping. * * If we don't already have the section addresses, and we successfully * get them, then we cache them in case we come here again. @@ -936,10 +961,14 @@ is_mapping_in_file(struct ps_prochandle *P, map_info_t *mptr, file_info_t *fptr) (fptr->file_saddrs = get_saddrs(P, fptr->file_map->map_pmap.pr_vaddr, &fptr->file_nsaddrs)) == NULL) return (0); + + mstart = mptr->map_pmap.pr_vaddr; + mend = mptr->map_pmap.pr_vaddr + mptr->map_pmap.pr_size; for (i = 0; i < fptr->file_nsaddrs; i += 2) { - /* Does this section enclose the start of the mapping? */ - if (fptr->file_saddrs[i] <= pmap->pr_vaddr && - fptr->file_saddrs[i + 1] > pmap->pr_vaddr) + /* Does this section overlap the mapping? */ + sstart = fptr->file_saddrs[i]; + send = fptr->file_saddrs[i + 1]; + if (!(mend <= sstart || mstart >= send)) return (1); } @@ -1513,18 +1542,31 @@ optimize_symtab(sym_tbl_t *symtab) } /* - * Sort the two tables according to the appropriate criteria. + * Sort the two tables according to the appropriate criteria, + * unless the user has overridden this behaviour. + * + * An example where we might not sort the tables is the relatively + * unusual case of a process with very large symbol tables in which + * we perform few lookups. In such a case the total time would be + * dominated by the sort. It is difficult to determine a priori + * how many lookups an arbitrary client will perform, and + * hence whether the symbol tables should be sorted. We therefore + * sort the tables by default, but provide the user with a + * "chicken switch" in the form of the LIBPROC_NO_QSORT + * environment variable. */ - (void) mutex_lock(&sort_mtx); - sort_strs = symtab->sym_strs; - sort_syms = syms; + if (!_libproc_no_qsort) { + (void) mutex_lock(&sort_mtx); + sort_strs = symtab->sym_strs; + sort_syms = syms; - qsort(symtab->sym_byaddr, count, sizeof (uint_t), byaddr_cmp); - qsort(symtab->sym_byname, count, sizeof (uint_t), byname_cmp); + qsort(symtab->sym_byaddr, count, sizeof (uint_t), byaddr_cmp); + qsort(symtab->sym_byname, count, sizeof (uint_t), byname_cmp); - sort_strs = NULL; - sort_syms = NULL; - (void) mutex_unlock(&sort_mtx); + sort_strs = NULL; + sort_syms = NULL; + (void) mutex_unlock(&sort_mtx); + } free(syms); } @@ -2084,12 +2126,11 @@ sym_prefer(GElf_Sym *sym1, char *name1, GElf_Sym *sym2, char *name2) } /* - * Look up a symbol by address in the specified symbol table. - * Adjustment to 'addr' must already have been made for the - * offset of the symbol if this is a dynamic library symbol table. + * Use a binary search to do the work of sym_by_addr(). */ static GElf_Sym * -sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp) +sym_by_addr_binary(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, + uint_t *idp) { GElf_Sym sym, osym; uint_t i, oid, *byaddr = symtab->sym_byaddr; @@ -2154,10 +2195,70 @@ sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp) } /* - * Look up a symbol by name in the specified symbol table. + * Use a linear search to do the work of sym_by_addr(). */ static GElf_Sym * -sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp) +sym_by_addr_linear(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symbolp, + uint_t *idp) +{ + size_t symn = symtab->sym_symn; + char *strs = symtab->sym_strs; + GElf_Sym sym, *symp = NULL; + GElf_Sym osym, *osymp = NULL; + int i, id; + + if (symtab->sym_data_pri == NULL || symn == 0 || strs == NULL) + return (NULL); + + for (i = 0; i < symn; i++) { + if ((symp = symtab_getsym(symtab, i, &sym)) != NULL) { + if (addr >= sym.st_value && + addr < sym.st_value + sym.st_size) { + if (osymp) + symp = sym_prefer( + symp, strs + symp->st_name, + osymp, strs + osymp->st_name); + if (symp != osymp) { + osym = sym; + osymp = &osym; + id = i; + } + } + } + } + if (osymp) { + *symbolp = osym; + if (idp) + *idp = id; + return (symbolp); + } + return (NULL); +} + +/* + * Look up a symbol by address in the specified symbol table. + * Adjustment to 'addr' must already have been made for the + * offset of the symbol if this is a dynamic library symbol table. + * + * Use a linear or a binary search depending on whether or not we + * chose to sort the table in optimize_symtab(). + */ +static GElf_Sym * +sym_by_addr(sym_tbl_t *symtab, GElf_Addr addr, GElf_Sym *symp, uint_t *idp) +{ + if (_libproc_no_qsort) { + return (sym_by_addr_linear(symtab, addr, symp, idp)); + } else { + return (sym_by_addr_binary(symtab, addr, symp, idp)); + } +} + +/* + * Use a binary search to do the work of sym_by_name(). + */ +static GElf_Sym * +sym_by_name_binary(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, + uint_t *idp) { char *strs = symtab->sym_strs; uint_t i, *byname = symtab->sym_byname; @@ -2192,6 +2293,48 @@ sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp) } /* + * Use a linear search to do the work of sym_by_name(). + */ +static GElf_Sym * +sym_by_name_linear(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, + uint_t *idp) +{ + size_t symn = symtab->sym_symn; + char *strs = symtab->sym_strs; + int i; + + if (symtab->sym_data_pri == NULL || symn == 0 || strs == NULL) + return (NULL); + + for (i = 0; i < symn; i++) { + if (symtab_getsym(symtab, i, symp) && + strcmp(name, strs + symp->st_name) == 0) { + if (idp) + *idp = i; + return (symp); + } + } + + return (NULL); +} + +/* + * Look up a symbol by name in the specified symbol table. + * + * Use a linear or a binary search depending on whether or not we + * chose to sort the table in optimize_symtab(). + */ +static GElf_Sym * +sym_by_name(sym_tbl_t *symtab, const char *name, GElf_Sym *symp, uint_t *idp) +{ + if (_libproc_no_qsort) { + return (sym_by_name_linear(symtab, name, symp, idp)); + } else { + return (sym_by_name_binary(symtab, name, symp, idp)); + } +} + +/* * Search the process symbol tables looking for a symbol whose * value to value+size contain the address specified by addr. * Return values are: diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h index d12fda05e3..07c6ee1622 100644 --- a/usr/src/lib/libproc/common/libproc.h +++ b/usr/src/lib/libproc/common/libproc.h @@ -82,6 +82,8 @@ struct ps_prochandle; struct ps_lwphandle; extern int _libproc_debug; /* set non-zero to enable debugging fprintfs */ +extern int _libproc_no_qsort; /* set non-zero to inhibit sorting */ + /* of symbol tables */ #if defined(__sparc) #define R_RVAL1 R_O0 /* register holding a function return value */ |