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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdio.h>
28 #include <proc_service.h>
29 #include <link.h>
30 #include <rtld_db.h>
31 #include <_rtld_db.h>
32 #include <msg.h>
33
34
35 /*
36 * A un-initialized PLT look like so:
37 *
38 * .PLT
39 * sethi (.-.PLT0), %g1
40 * ba,a .PLT0
41 * nop
42 *
43 * To test to see if this is an uninitialized PLT we check
44 * the second instruction and confirm that it's a branch.
45 */
46 /* ARGSUSED 2 */
47 rd_err_e
plt32_resolution(rd_agent_t * rap,psaddr_t pc,lwpid_t lwpid,psaddr_t pltbase,rd_plt_info_t * rpi)48 plt32_resolution(rd_agent_t *rap, psaddr_t pc, lwpid_t lwpid,
49 psaddr_t pltbase, rd_plt_info_t *rpi)
50 {
51 unsigned int instr[4];
52 rd_err_e rerr;
53 psaddr_t destaddr = 0;
54 psaddr_t pltoff, pltaddr;
55 int pltbound = 0;
56
57 pltoff = pc - pltbase;
58 pltaddr = pltbase +
59 ((pltoff / M32_PLT_ENTSIZE) * M32_PLT_ENTSIZE);
60
61 if (ps_pread(rap->rd_psp, pltaddr, (char *)instr,
62 M32_PLT_ENTSIZE) != PS_OK) {
63 LOG(ps_plog(MSG_ORIG(MSG_DB_READFAIL_2), EC_ADDR(pltaddr)));
64 return (RD_ERR);
65 }
66
67 if (rtld_db_version >= RD_VERSION3) {
68 rpi->pi_flags = 0;
69 rpi->pi_baddr = 0;
70 }
71
72 if ((instr[0] != M_NOP) &&
73 ((instr[1] & (~(S_MASK(22)))) == M_BA_A)) {
74 /*
75 * Unbound PLT
76 */
77 if ((rerr = rd_binder_exit_addr(rap, MSG_ORIG(MSG_SYM_RTBIND),
78 &(rpi->pi_target))) != RD_OK) {
79 return (rerr);
80 }
81 rpi->pi_skip_method = RD_RESOLVE_TARGET_STEP;
82 rpi->pi_nstep = 1;
83 } else if ((instr[2] & (~(S_MASK(13)))) == M_JMPL) {
84 /*
85 * Resolved 32-bit PLT entry format (full-32):
86 *
87 * .PLT:
88 * 0 sethi (.-PLT0), %g1
89 * 1 sethi %hi(dest), %g1
90 * 2 jmpl %g1 + lo(dest), %g0
91 * 3 nop
92 */
93 rpi->pi_skip_method = RD_RESOLVE_STEP;
94 rpi->pi_nstep = 4;
95 rpi->pi_target = 0;
96 if (rtld_db_version >= RD_VERSION3) {
97 uint_t hi_bits;
98 uint_t lo_bits;
99 hi_bits = instr[1] & S_MASK(22); /* 31..10 */
100 lo_bits = instr[2] & S_MASK(10); /* 09..00 */
101 destaddr = (hi_bits << 10) | lo_bits;
102 pltbound++;
103 }
104 } else if ((instr[0] == M_NOP) &&
105 ((instr[1] & (~(S_MASK(22)))) == M_BA_A)) {
106 /*
107 * Resolved 32-bit PLT entry format (b+-8mb):
108 * .PLT
109 * 0 nop
110 * 1 ba,a <dest>
111 * 2 nop
112 * 3 nop
113 */
114 rpi->pi_skip_method = RD_RESOLVE_STEP;
115 rpi->pi_nstep = 2;
116 rpi->pi_target = 0;
117 if (rtld_db_version >= RD_VERSION3) {
118 uint_t d22;
119 d22 = instr[1] & S_MASK(22);
120 destaddr = ((int)pltaddr + 4) +
121 (((int)d22 << 10) >> 8);
122 pltbound++;
123 }
124 } else if ((instr[0] == M_NOP) &&
125 ((instr[1] & (~(S_MASK(19)))) == M_BA_A_PT)) {
126 /*
127 * Resolved 32-bit PLT entry format (b+-2mb):
128 * .PLT
129 * 0 nop
130 * 1 ba,a,pt %icc, <dest>
131 * 2 nop
132 * 3 nop
133 */
134 rpi->pi_skip_method = RD_RESOLVE_STEP;
135 rpi->pi_nstep = 2;
136 rpi->pi_target = 0;
137 if (rtld_db_version >= RD_VERSION3) {
138 uint_t d19;
139 d19 = instr[1] & S_MASK(22);
140 destaddr = ((int)pltaddr + 4) +
141 (((int)d19 << 13) >> 11);
142 pltbound++;
143 }
144 } else
145 rpi->pi_skip_method = RD_RESOLVE_NONE;
146
147 if ((rtld_db_version >= RD_VERSION3) && pltbound) {
148 rpi->pi_flags |= RD_FLG_PI_PLTBOUND;
149 rpi->pi_baddr = destaddr;
150 }
151 return (RD_OK);
152 }
153