1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
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 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright (c) 2014 Joyent, Inc. All rights reserved.
28 */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <proc_service.h>
33 #include <link.h>
34 #include <rtld_db.h>
35 #include <rtld.h>
36 #include <alist.h>
37 #include <list.h>
38 #include <_rtld_db.h>
39 #include <msg.h>
40 #include <limits.h>
41 #include <string.h>
42 #include <sys/param.h>
43
44 /*
45 * We want to include zone.h to pull in the prototype for zone_get_nroot(),
46 * but we need to avoid pulling in <sys/stream.h>, which has a definition
47 * of M_DATA that conflicts with the ELF-related definition in machdep_*.h.
48 */
49 #define _SYS_STREAM_H
50 #include <zone.h>
51
52 /*
53 * 64-bit builds are going to compile this module twice, the
54 * second time with _ELF64 defined. These defines should make
55 * all the necessary adjustments to the code.
56 */
57 #ifdef _LP64
58 #ifdef _ELF64
59 #define _rd_event_enable32 _rd_event_enable64
60 #define _rd_event_getmsg32 _rd_event_getmsg64
61 #define _rd_get_dyns32 _rd_get_dyns64
62 #define _rd_get_ehdr32 _rd_get_ehdr64
63 #define _rd_objpad_enable32 _rd_objpad_enable64
64 #define _rd_loadobj_iter32 _rd_loadobj_iter64
65 #define _rd_reset32 _rd_reset64
66 #define find_dynamic_ent32 find_dynamic_ent64
67 #define validate_rdebug32 validate_rdebug64
68 #define TAPlist APlist
69 #define TLm_list Lm_list
70 #define TList List
71 #define TListnode Listnode
72 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_64
73 #else /* ELF32 */
74 #define Rt_map Rt_map32
75 #define Rtld_db_priv Rtld_db_priv32
76 #define TAPlist APlist32
77 #define TLm_list Lm_list32
78 #define TList List32
79 #define TListnode Listnode32
80 #define Lm_list Lm_list32
81 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32
82 #endif /* _ELF64 */
83 #else /* _LP64 */
84 #define TAPlist APlist
85 #define TLm_list Lm_list
86 #define TList List
87 #define TListnode Listnode
88 #define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32
89 #endif /* _LP64 */
90
91 /*
92 * BrandZ added ps_pbrandname(). Many debuggers that link directly
93 * against librtld_db.so may not implement this interface. Hence
94 * we won't call the function directly, instead we'll try to look it
95 * up using the linker first and only invoke it if we find it.
96 */
97 typedef ps_err_e (*ps_pbrandname_fp_t)(struct ps_prochandle *,
98 char *, size_t);
99
100 rd_err_e
101 validate_rdebug32(struct rd_agent *rap)
102 {
103 struct ps_prochandle *php = rap->rd_psp;
104 psaddr_t db_privp;
105 Rtld_db_priv db_priv;
106
107 if (rap->rd_rdebug == 0)
108 return (RD_ERR);
109
110 /*
111 * The rtld_db_priv structure contains both the traditional (exposed)
112 * r_debug structure as well as private data only available to
113 * this library.
114 */
115 db_privp = rap->rd_rdebug;
116
117 /*
118 * Verify that librtld_db & rtld are at the proper revision
119 * levels.
120 */
121 if (ps_pread(php, db_privp, (char *)&db_priv,
122 sizeof (Rtld_db_priv)) != PS_OK) {
123 LOG(ps_plog(MSG_ORIG(MSG_DB_READPRIVFAIL_1),
124 EC_ADDR(db_privp)));
125 return (RD_DBERR);
126 }
127
128 if ((db_priv.rtd_version < R_RTLDDB_VERSION1) ||
129 (db_priv.rtd_version > R_RTLDDB_VERSION)) {
130 LOG(ps_plog(MSG_ORIG(MSG_DB_BADPVERS),
131 db_priv.rtd_version, R_RTLDDB_VERSION));
132 return (RD_NOCAPAB);
133 }
134
135 /*
136 * Is the image being examined from a core file or not.
137 * If it is a core file then the following write will fail.
138 */
139 if (ps_pwrite(php, db_privp, (char *)&db_priv,
140 sizeof (Rtld_db_priv)) != PS_OK)
141 rap->rd_flags |= RDF_FL_COREFILE;
142
143 rap->rd_rdebugvers = db_priv.rtd_version;
144 rap->rd_rtlddbpriv = db_privp;
145
146 LOG(ps_plog(MSG_ORIG(MSG_DB_VALIDRDEBUG), EC_ADDR(rap->rd_rdebug),
147 R_RTLDDB_VERSION, rap->rd_rdebugvers,
148 rap->rd_flags & RDF_FL_COREFILE));
149 return (RD_OK);
150 }
151
152
153 rd_err_e
154 find_dynamic_ent32(struct rd_agent *rap, psaddr_t dynaddr,
155 Xword dyntag, Dyn *dyn)
156 {
157 struct ps_prochandle *php = rap->rd_psp;
158 Dyn d;
159
160 d.d_tag = DT_NULL;
161 do {
162 if (ps_pread(php, dynaddr, (void *)(&d), sizeof (d)) !=
163 PS_OK) {
164 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_4),
165 EC_ADDR(dynaddr)));
166 return (RD_DBERR);
167 }
168 dynaddr += sizeof (d);
169 if (d.d_tag == dyntag)
170 break;
171 } while (d.d_tag != DT_NULL);
172 if (d.d_tag == dyntag) {
173 *dyn = d;
174 LOG(ps_plog(MSG_ORIG(MSG_DB_FINDDYNAMIC), EC_ADDR(dyntag),
175 EC_ADDR(d.d_un.d_val)));
176 return (RD_OK);
177 }
178 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNDEBUG), EC_ADDR(dyntag)));
179 return (RD_DBERR);
180 }
181
182 extern char rtld_db_helper_path[MAXPATHLEN];
183
184 rd_err_e
185 _rd_reset32(struct rd_agent *rap)
186 {
187 psaddr_t symaddr;
188 struct ps_prochandle *php = rap->rd_psp;
189 const auxv_t *auxvp = NULL;
190 rd_err_e rc = RD_OK;
191 char brandname[MAXPATHLEN];
192 char brandlib[MAXPATHLEN];
193 ps_pbrandname_fp_t ps_pbrandname;
194
195 /*
196 * librtld_db attempts three different methods to find
197 * the r_debug structure which is required to
198 * initialize itself. The methods are:
199 * method1:
200 * entirely independent of any text segment
201 * and relies on the AT_SUN_LDDATA auxvector
202 * to find the ld.so.1::rdebug structure.
203 * method2:
204 * lookup symbols in ld.so.1's symbol table
205 * to find the r_debug symbol.
206 * method3:
207 * (old dbx method) dependent upon the
208 * text segment/symbol table of the
209 * executable and not ld.so.1. We lookup the
210 * _DYNAMIC symbol in the executable and look for
211 * the DT_DEBUG entry in the .dynamic table. This
212 * points to rdebug.
213 *
214 * If none of that works - we fail.
215 */
216 LOG(ps_plog(MSG_ORIG(MSG_DB_RDRESET), rap->rd_dmodel));
217 /*
218 * Method1
219 *
220 * Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA
221 */
222
223 if (ps_pauxv(php, &auxvp) != PS_OK) {
224 LOG(ps_plog(MSG_ORIG(MSG_DB_NOAUXV)));
225 rc = RD_ERR;
226 }
227
228 rap->rd_rdebug = 0;
229
230 if (auxvp != NULL) {
231 rc = RD_ERR;
232 while (auxvp->a_type != AT_NULL) {
233 if (auxvp->a_type == AT_SUN_LDDATA) {
234 /* LINTED */
235 rap->rd_rdebug = (uintptr_t)auxvp->a_un.a_ptr;
236 LOG(ps_plog(MSG_ORIG(MSG_DB_FLDDATA),
237 rap->rd_rdebug));
238 rc = validate_rdebug32(rap);
239 break;
240 }
241 auxvp++;
242 }
243 }
244
245 /*
246 * method2 - look for r_rdebug symbol in ld.so.1
247 */
248 if (rc != RD_OK) {
249 /*
250 * If the AT_SUN_LDDATA auxv vector is not present
251 * fall back on doing a symlookup of
252 * the r_debug symbol. This is for backward
253 * compatiblity with older OS's
254 */
255 LOG(ps_plog(MSG_ORIG(MSG_DB_NOLDDATA)));
256 if (ps_pglobal_lookup(php, PS_OBJ_LDSO, MSG_ORIG(MSG_SYM_DEBUG),
257 &symaddr) != PS_OK) {
258 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
259 MSG_ORIG(MSG_SYM_DEBUG)));
260 rc = RD_DBERR;
261 } else {
262 rap->rd_rdebug = symaddr;
263 LOG(ps_plog(MSG_ORIG(MSG_DB_SYMRDEBUG),
264 EC_ADDR(symaddr)));
265 rc = validate_rdebug32(rap);
266 }
267 }
268
269
270 /*
271 * method3 - find DT_DEBUG in the executables .dynamic section.
272 */
273 if (rc != RD_OK) {
274 Dyn dyn;
275 if (ps_pglobal_lookup(php, PS_OBJ_EXEC,
276 MSG_ORIG(MSG_SYM_DYNAMIC), &symaddr) != PS_OK) {
277 LOG(ps_plog(MSG_ORIG(MSG_DB_NODYNAMIC)));
278 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
279 return (rc);
280 }
281 rc = find_dynamic_ent32(rap, symaddr, DT_DEBUG, &dyn);
282 if (rc != RD_OK) {
283 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
284 return (rc);
285 }
286 rap->rd_rdebug = dyn.d_un.d_ptr;
287 rc = validate_rdebug32(rap);
288 if (rc != RD_OK) {
289 LOG(ps_plog(MSG_ORIG(MSG_DB_INITFAILED)));
290 return (rc);
291 }
292 }
293
294 /*
295 * If we are debugging a branded executable, load the appropriate
296 * helper library, and call its initialization routine. Being unable
297 * to load the helper library is not a critical error. (Hopefully
298 * we'll still be able to access some objects in the target.) Note
299 * that we pull in the native root here to allow for helper libraries
300 * to be properly found from within the branded zone.
301 */
302 ps_pbrandname = (ps_pbrandname_fp_t)dlsym(RTLD_PROBE, "ps_pbrandname");
303 while ((ps_pbrandname != NULL) &&
304 (ps_pbrandname(php, brandname, MAXPATHLEN) == PS_OK)) {
305 const char *isa = "";
306
307 #ifdef _LP64
308 isa = MSG_ORIG(MSG_DB_64BIT_PREFIX);
309 #endif /* _LP64 */
310
311 if (rtld_db_helper_path[0] != '\0') {
312 (void) snprintf(brandlib, MAXPATHLEN,
313 MSG_ORIG(MSG_DB_BRAND_HELPERPATH_PREFIX),
314 rtld_db_helper_path,
315 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
316 brandname);
317 } else {
318 const char *nroot = zone_get_nroot();
319
320 if (nroot == NULL)
321 nroot = "";
322
323 (void) snprintf(brandlib, MAXPATHLEN,
324 MSG_ORIG(MSG_DB_BRAND_HELPERPATH), nroot,
325 MSG_ORIG(MSG_DB_HELPER_PREFIX), brandname, isa,
326 brandname);
327 }
328
329 rap->rd_helper.rh_dlhandle = dlopen(brandlib,
330 RTLD_LAZY | RTLD_LOCAL);
331 if (rap->rd_helper.rh_dlhandle == NULL) {
332 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADFAILED),
333 brandlib));
334 break;
335 }
336
337 rap->rd_helper.rh_ops = dlsym(rap->rd_helper.rh_dlhandle,
338 MSG_ORIG(MSG_SYM_BRANDOPS));
339 if (rap->rd_helper.rh_ops == NULL) {
340 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERNOOPS),
341 brandlib));
342 (void) dlclose(rap->rd_helper.rh_dlhandle);
343 rap->rd_helper.rh_dlhandle = NULL;
344 break;
345 }
346
347 rap->rd_helper.rh_data = rap->rd_helper.rh_ops->rho_init(rap,
348 php);
349 if (rap->rd_helper.rh_data == NULL) {
350 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERINITFAILED)));
351 (void) dlclose(rap->rd_helper.rh_dlhandle);
352 rap->rd_helper.rh_dlhandle = NULL;
353 rap->rd_helper.rh_ops = NULL;
354 break;
355 }
356
357 LOG(ps_plog(MSG_ORIG(MSG_DB_HELPERLOADED), brandname));
358 break;
359
360 /* NOTREACHED */
361 }
362
363 if ((rap->rd_flags & RDF_FL_COREFILE) == 0) {
364 if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
365 MSG_ORIG(MSG_SYM_PREINIT), &symaddr) != PS_OK) {
366 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
367 MSG_ORIG(MSG_SYM_PREINIT)));
368 return (RD_DBERR);
369 }
370 rap->rd_preinit = symaddr;
371
372 if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
373 MSG_ORIG(MSG_SYM_POSTINIT), &symaddr) != PS_OK) {
374 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
375 MSG_ORIG(MSG_SYM_POSTINIT)));
376 return (RD_DBERR);
377 }
378 rap->rd_postinit = symaddr;
379
380 if (ps_pglobal_lookup(php, PS_OBJ_LDSO,
381 MSG_ORIG(MSG_SYM_DLACT), &symaddr) != PS_OK) {
382 LOG(ps_plog(MSG_ORIG(MSG_DB_LOOKFAIL),
383 MSG_ORIG(MSG_SYM_DLACT)));
384 return (RD_DBERR);
385 }
386 rap->rd_dlact = symaddr;
387 rap->rd_tbinder = 0;
388 }
389
390 return (RD_OK);
391 }
392
393 rd_err_e
394 _rd_get_ehdr32(struct rd_agent *rap,
395 psaddr_t addr, Ehdr *ehdr, uint_t *phnum)
396 {
397 struct ps_prochandle *php = rap->rd_psp;
398 Shdr shdr;
399
400 if (ps_pread(php, addr, ehdr, sizeof (*ehdr)) != PS_OK) {
401 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
402 return (RD_ERR);
403 }
404 if (phnum == NULL)
405 return (RD_OK);
406
407 if (ehdr->e_phnum != PN_XNUM) {
408 *phnum = ehdr->e_phnum;
409 return (RD_OK);
410 }
411
412 /* deal with elf extended program headers */
413 if ((ehdr->e_shoff == 0) || (ehdr->e_shentsize < sizeof (shdr)))
414 return (RD_ERR);
415
416 addr += ehdr->e_shoff;
417 if (ps_pread(php, addr, &shdr, sizeof (shdr)) != PS_OK) {
418 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_5), EC_ADDR(addr)));
419 return (RD_ERR);
420 }
421
422 if (shdr.sh_info == 0)
423 return (RD_ERR);
424
425 *phnum = shdr.sh_info;
426 return (RD_OK);
427 }
428
429 rd_err_e
430 _rd_get_dyns32(rd_agent_t *rap, psaddr_t addr, Dyn **dynpp, size_t *dynpp_sz)
431 {
432 struct ps_prochandle *php = rap->rd_psp;
433 rd_err_e err;
434 uint_t phnum;
435 Ehdr ehdr;
436 Phdr phdr;
437 Dyn *dynp;
438 int i;
439
440 /* We only need to muck with dyn elements for ET_DYN objects */
441 if ((err = _rd_get_ehdr32(rap, addr, &ehdr, &phnum)) != RD_OK)
442 return (err);
443
444 for (i = 0; i < phnum; i++) {
445 psaddr_t a = addr + ehdr.e_phoff + (i * ehdr.e_phentsize);
446 if (ps_pread(php, a, &phdr, sizeof (phdr)) != PS_OK) {
447 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6), EC_ADDR(a)));
448 return (RD_ERR);
449 }
450 if (phdr.p_type == PT_DYNAMIC)
451 break;
452 }
453 if (i == phnum)
454 return (RD_ERR);
455
456 if ((dynp = malloc(phdr.p_filesz)) == NULL)
457 return (RD_ERR);
458 if (ehdr.e_type == ET_DYN)
459 phdr.p_vaddr += addr;
460 if (ps_pread(php, phdr.p_vaddr, dynp, phdr.p_filesz) != PS_OK) {
461 free(dynp);
462 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_6),
463 EC_ADDR(phdr.p_vaddr)));
464 return (RD_ERR);
465 }
466
467 *dynpp = dynp;
468 if (dynpp_sz != NULL)
469 *dynpp_sz = phdr.p_filesz;
470 return (RD_OK);
471 }
472
473 rd_err_e
474 _rd_event_enable32(rd_agent_t *rap, int onoff)
475 {
476 struct ps_prochandle *php = rap->rd_psp;
477 Rtld_db_priv rdb;
478
479 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTENABLE), rap->rd_dmodel, onoff));
480 /*
481 * Tell the debugged process that debugging is occuring
482 * This will enable the storing of event messages so that
483 * the can be gathered by the debugger.
484 */
485 if (ps_pread(php, rap->rd_rdebug, (char *)&rdb,
486 sizeof (Rtld_db_priv)) != PS_OK) {
487 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_1),
488 EC_ADDR((uintptr_t)&rdb)));
489 return (RD_DBERR);
490 }
491
492 if (onoff)
493 rdb.rtd_rdebug.r_flags |= RD_FL_DBG;
494 else
495 rdb.rtd_rdebug.r_flags &= ~RD_FL_DBG;
496
497 if (ps_pwrite(php, rap->rd_rdebug, (char *)&rdb,
498 sizeof (Rtld_db_priv)) != PS_OK) {
499 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_1),
500 EC_ADDR((uintptr_t)&rdb)));
501 return (RD_DBERR);
502 }
503
504 return (RD_OK);
505 }
506
507
508 rd_err_e
509 _rd_event_getmsg32(rd_agent_t *rap, rd_event_msg_t *emsg)
510 {
511 Rtld_db_priv rdb;
512
513 if (ps_pread(rap->rd_psp, rap->rd_rdebug, (char *)&rdb,
514 sizeof (Rtld_db_priv)) != PS_OK) {
515 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_2),
516 EC_ADDR(rap->rd_rdebug)));
517 return (RD_DBERR);
518 }
519 emsg->type = rdb.rtd_rdebug.r_rdevent;
520 if (emsg->type == RD_DLACTIVITY) {
521 switch (rdb.rtd_rdebug.r_state) {
522 case RT_CONSISTENT:
523 emsg->u.state = RD_CONSISTENT;
524 break;
525 case RT_ADD:
526 emsg->u.state = RD_ADD;
527 break;
528 case RT_DELETE:
529 emsg->u.state = RD_DELETE;
530 break;
531 }
532 } else
533 emsg->u.state = RD_NOSTATE;
534
535 LOG(ps_plog(MSG_ORIG(MSG_DB_RDEVENTGETMSG), rap->rd_dmodel,
536 emsg->type, emsg->u.state));
537
538 return (RD_OK);
539 }
540
541
542 rd_err_e
543 _rd_objpad_enable32(struct rd_agent *rap, size_t padsize)
544 {
545 Rtld_db_priv db_priv;
546 struct ps_prochandle *php = rap->rd_psp;
547
548 LOG(ps_plog(MSG_ORIG(MSG_DB_RDOBJPADE), EC_ADDR(padsize)));
549
550 if (ps_pread(php, rap->rd_rtlddbpriv, (char *)&db_priv,
551 sizeof (Rtld_db_priv)) != PS_OK) {
552 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_3),
553 EC_ADDR(rap->rd_rtlddbpriv)));
554 return (RD_DBERR);
555 }
556 #if defined(_LP64) && !defined(_ELF64)
557 /*LINTED*/
558 db_priv.rtd_objpad = (uint32_t)padsize;
559 #else
560 db_priv.rtd_objpad = padsize;
561 #endif
562 if (ps_pwrite(php, rap->rd_rtlddbpriv, (char *)&db_priv,
563 sizeof (Rtld_db_priv)) != PS_OK) {
564 LOG(ps_plog(MSG_ORIG(MSG_DB_WRITEFAIL_2),
565 EC_ADDR(rap->rd_rtlddbpriv)));
566 return (RD_DBERR);
567 }
568 return (RD_OK);
569 }
570
571 static rd_err_e
572 iter_map(rd_agent_t *rap, unsigned long ident, psaddr_t lmaddr,
573 rl_iter_f *cb, void *client_data, uint_t *abort_iterp)
574 {
575 while (lmaddr) {
576 Rt_map rmap;
577 rd_loadobj_t lobj;
578 int i;
579 ulong_t off;
580 Ehdr ehdr;
581 Phdr phdr;
582
583 if (ps_pread(rap->rd_psp, lmaddr, (char *)&rmap,
584 sizeof (Rt_map)) != PS_OK) {
585 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
586 return (RD_DBERR);
587 }
588
589 /*
590 * As of 'VERSION5' we only report objects
591 * which have been fully relocated. While the maps
592 * might be in a consistent state - if a object hasn't
593 * been relocated - it's not really ready for the debuggers
594 * to examine. This is mostly due to the fact that we
595 * might still be mucking with the text-segment, if
596 * we are - we could conflict with any break-points
597 * the debuggers might have set.
598 */
599 if (rap->rd_rdebugvers >= R_RTLDDB_VERSION5) {
600 if ((FLAGS(&rmap) & FLG_RT_RELOCED) == 0) {
601 lmaddr = (psaddr_t)NEXT(&rmap);
602 continue;
603 }
604 }
605
606 lobj.rl_base = (psaddr_t)ADDR(&rmap);
607 lobj.rl_flags = 0;
608 lobj.rl_refnameaddr = (psaddr_t)REFNAME(&rmap);
609 if ((rap->rd_helper.rh_ops != NULL) &&
610 (rap->rd_helper.rh_ops->rho_lmid != LM_ID_NONE))
611 lobj.rl_lmident =
612 rap->rd_helper.rh_ops->rho_lmid;
613 else
614 lobj.rl_lmident = ident;
615
616 /*
617 * refnameaddr is only valid from a core file
618 * which is VERSION3 or greater.
619 */
620 if (rap->rd_rdebugvers < R_RTLDDB_VERSION3) {
621 lobj.rl_nameaddr = (psaddr_t)NAME(&rmap);
622 lobj.rl_bend = 0;
623 lobj.rl_padstart = 0;
624 lobj.rl_padend = 0;
625 } else {
626 lobj.rl_nameaddr = (psaddr_t)PATHNAME(&rmap);
627 lobj.rl_bend = ADDR(&rmap) + MSIZE(&rmap);
628 lobj.rl_padstart = PADSTART(&rmap);
629 lobj.rl_padend = PADSTART(&rmap) + PADIMLEN(&rmap);
630
631 }
632
633 if (rtld_db_version >= RD_VERSION2)
634 if (FLAGS(&rmap) & FLG_RT_IMGALLOC)
635 lobj.rl_flags |= RD_FLG_MEM_OBJECT;
636 if (rtld_db_version >= RD_VERSION2) {
637 lobj.rl_dynamic = (psaddr_t)DYN(&rmap);
638 }
639
640 if (rtld_db_version >= RD_VERSION4)
641 lobj.rl_tlsmodid = TLSMODID(&rmap);
642
643 /*
644 * Look for beginning of data segment.
645 *
646 * NOTE: the data segment can only be found for full
647 * processes and not from core images.
648 */
649 lobj.rl_data_base = 0;
650 if (rap->rd_flags & RDF_FL_COREFILE)
651 lobj.rl_data_base = 0;
652 else {
653 off = ADDR(&rmap);
654 if (ps_pread(rap->rd_psp, off, (char *)&ehdr,
655 sizeof (Ehdr)) != PS_OK) {
656 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPFAIL)));
657 return (RD_DBERR);
658 }
659 off += sizeof (Ehdr);
660 for (i = 0; i < ehdr.e_phnum; i++) {
661 if (ps_pread(rap->rd_psp, off, (char *)&phdr,
662 sizeof (Phdr)) != PS_OK) {
663 LOG(ps_plog(MSG_ORIG(
664 MSG_DB_LKMAPFAIL)));
665 return (RD_DBERR);
666 }
667 if ((phdr.p_type == PT_LOAD) &&
668 (phdr.p_flags & PF_W)) {
669 lobj.rl_data_base = phdr.p_vaddr;
670 if (ehdr.e_type == ET_DYN)
671 lobj.rl_data_base +=
672 ADDR(&rmap);
673 break;
674 }
675 off += ehdr.e_phentsize;
676 }
677 }
678
679 /*
680 * When we transfer control to the client we free the
681 * lock and re-atain it after we've returned from the
682 * client. This is to avoid any deadlock situations.
683 */
684 LOG(ps_plog(MSG_ORIG(MSG_DB_ITERMAP), cb, client_data,
685 EC_ADDR(lobj.rl_base), EC_ADDR(lobj.rl_lmident)));
686 RDAGUNLOCK(rap);
687 if ((*cb)(&lobj, client_data) == 0) {
688 LOG(ps_plog(MSG_ORIG(MSG_DB_CALLBACKR0)));
689 RDAGLOCK(rap);
690 *abort_iterp = 1;
691 break;
692 }
693 RDAGLOCK(rap);
694 lmaddr = (psaddr_t)NEXT(&rmap);
695 }
696 return (RD_OK);
697 }
698
699
700 static rd_err_e
701 _rd_loadobj_iter32_native(rd_agent_t *rap, rl_iter_f *cb, void *client_data,
702 uint_t *abort_iterp)
703 {
704 Rtld_db_priv db_priv;
705 TAPlist apl;
706 uintptr_t datap, nitems;
707 Addr addr;
708 rd_err_e rc;
709
710 LOG(ps_plog(MSG_ORIG(MSG_DB_LOADOBJITER), rap->rd_dmodel, cb,
711 client_data));
712
713 /*
714 * First, determine whether the link-map information has been
715 * established. Some debuggers have made an initial call to this
716 * function with a null call back function (cb), but expect a
717 * RD_NOMAPS error return rather than a RD_ERR return when the
718 * link-maps aren't available.
719 */
720 if (ps_pread(rap->rd_psp, rap->rd_rtlddbpriv, (char *)&db_priv,
721 sizeof (Rtld_db_priv)) != PS_OK) {
722 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_1),
723 EC_ADDR(rap->rd_rtlddbpriv)));
724 return (RD_DBERR);
725 }
726
727 if (db_priv.rtd_dynlmlst == NULL) {
728 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT),
729 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
730 return (RD_NOMAPS);
731 }
732
733 if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst, (char *)&addr,
734 sizeof (Addr)) != PS_OK) {
735 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
736 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
737 return (RD_DBERR);
738 }
739
740 if (addr == NULL) {
741 LOG(ps_plog(MSG_ORIG(MSG_DB_LKMAPNOINIT_1),
742 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
743 return (RD_NOMAPS);
744 }
745
746 /*
747 * Having determined we have link-maps, ensure we have an iterator
748 * call back function.
749 */
750 if (cb == NULL) {
751 LOG(ps_plog(MSG_ORIG(MSG_DB_NULLITER)));
752 return (RD_ERR);
753 }
754
755 /*
756 * As of VERSION6, rtd_dynlmlst points to an APlist. Prior to VERSION6
757 * rtd_dynlmlst pointed to a List. But, there was a window where the
758 * version was not incremented, and this must be worked around by
759 * interpreting the APlist data. Read the initial APlist information.
760 */
761 if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&apl,
762 sizeof (TAPlist)) != PS_OK) {
763 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
764 EC_ADDR((uintptr_t)addr)));
765 return (RD_DBERR);
766 }
767
768 /*
769 * The rtd_dynlmlst change from a List to an APlist occurred under
770 * 6801536 in snv_112. However, this change neglected to preserve
771 * backward compatibility by maintaining List processing and using a
772 * version increment to detect the change. 6862967, intergrated in
773 * snv_121 corrects the version detection. However, to catch objects
774 * built between these releases, we look at the first element of the
775 * APlist. apl_arritems indicates the number of APlist items that are
776 * available. This was originally initialized with a AL_CNT_DYNLIST
777 * value of 2 (one entry for LM_ID_BASE and one entry for LM_ID_LDSO).
778 * It is possible that the use of an auditor results in an additional
779 * link-map list, in which case the original apl_arritems would have
780 * been doubled.
781 *
782 * Therefore, if the debugging verion is VERSION6, or the apl_arritems
783 * entry has a value less than or equal to 4 and the debugging version
784 * is VERSION5, then we process APlists. Otherwise, fall back to List
785 * processing.
786 */
787 if ((rap->rd_rdebugvers >= R_RTLDDB_VERSION6) ||
788 ((rap->rd_rdebugvers == R_RTLDDB_VERSION5) &&
789 (apl.apl_arritems <= 4))) {
790 /*
791 * Iterate through each apl.ap_data[] entry.
792 */
793 for (datap = (uintptr_t)((char *)(uintptr_t)addr +
794 ((size_t)(((TAPlist *)0)->apl_data))), nitems = 0;
795 nitems < apl.apl_nitems; nitems++, datap += sizeof (Addr)) {
796 TLm_list lm;
797 ulong_t ident;
798
799 /*
800 * Obtain the Lm_list address for this apl.ap_data[]
801 * entry.
802 */
803 if (ps_pread(rap->rd_psp, (psaddr_t)datap,
804 (char *)&addr, sizeof (Addr)) != PS_OK) {
805 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
806 EC_ADDR(datap)));
807 return (RD_DBERR);
808 }
809
810 /*
811 * Obtain the Lm_list data for this Lm_list address.
812 */
813 if (ps_pread(rap->rd_psp, (psaddr_t)addr, (char *)&lm,
814 sizeof (TLm_list)) != PS_OK) {
815 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_6),
816 EC_ADDR((uintptr_t)addr)));
817 return (RD_DBERR);
818 }
819
820 /*
821 * Determine IDENT of current LM_LIST
822 */
823 if (lm.lm_flags & LML_FLG_BASELM)
824 ident = LM_ID_BASE;
825 else if (lm.lm_flags & LML_FLG_RTLDLM)
826 ident = LM_ID_LDSO;
827 else
828 ident = (ulong_t)addr;
829
830 if ((rc = iter_map(rap, ident, (psaddr_t)lm.lm_head,
831 cb, client_data, abort_iterp)) != RD_OK)
832 return (rc);
833
834 if (*abort_iterp != 0)
835 break;
836 }
837 } else {
838 TList list;
839 TListnode lnode;
840 Addr lnp;
841
842 /*
843 * Re-read the dynlmlst address to obtain a List structure.
844 */
845 if (ps_pread(rap->rd_psp, (psaddr_t)db_priv.rtd_dynlmlst,
846 (char *)&list, sizeof (TList)) != PS_OK) {
847 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_3),
848 EC_ADDR((uintptr_t)db_priv.rtd_dynlmlst)));
849 return (RD_DBERR);
850 }
851
852 /*
853 * Iterate through the link-map list.
854 */
855 for (lnp = (Addr)list.head; lnp; lnp = (Addr)lnode.next) {
856 Lm_list lml;
857 ulong_t ident;
858
859 /*
860 * Iterate through the List of Lm_list's.
861 */
862 if (ps_pread(rap->rd_psp, (psaddr_t)lnp, (char *)&lnode,
863 sizeof (TListnode)) != PS_OK) {
864 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_4),
865 EC_ADDR(lnp)));
866 return (RD_DBERR);
867 }
868
869 if (ps_pread(rap->rd_psp, (psaddr_t)lnode.data,
870 (char *)&lml, sizeof (Lm_list)) != PS_OK) {
871 LOG(ps_plog(MSG_ORIG(MSG_DB_READDBGFAIL_5),
872 EC_ADDR((uintptr_t)lnode.data)));
873 return (RD_DBERR);
874 }
875
876 /*
877 * Determine IDENT of current LM_LIST
878 */
879 if (lml.lm_flags & LML_FLG_BASELM)
880 ident = LM_ID_BASE;
881 else if (lml.lm_flags & LML_FLG_RTLDLM)
882 ident = LM_ID_LDSO;
883 else
884 ident = (unsigned long)lnode.data;
885
886 if ((rc = iter_map(rap, ident, (psaddr_t)lml.lm_head,
887 cb, client_data, abort_iterp)) != RD_OK)
888 return (rc);
889
890 if (*abort_iterp != 0)
891 break;
892 }
893 }
894
895 return (rc);
896 }
897
898 rd_err_e
899 _rd_loadobj_iter32(rd_agent_t *rap, rl_iter_f *cb, void *client_data)
900 {
901 rd_err_e rc, rc_brand = RD_OK;
902 uint_t abort_iter = 0;
903
904 /* First iterate over the native target objects */
905 rc = _rd_loadobj_iter32_native(rap, cb, client_data, &abort_iter);
906 if (abort_iter != 0)
907 return (rc);
908
909 /* Then iterate over any branded objects. */
910 if ((rap->rd_helper.rh_ops != NULL) &&
911 (rap->rd_helper.rh_ops->rho_loadobj_iter != NULL))
912 rc_brand = rap->rd_helper.rh_ops->rho_loadobj_iter(
913 rap->rd_helper.rh_data, cb, client_data);
914
915 rc = (rc != RD_OK) ? rc : rc_brand;
916 return (rc);
917 }