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