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 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <msg.h>
32 #include <_elfdump.h>
33 #include <struct_layout.h>
34 #include <conv.h>
35
36
37 /*
38 * Functions for extracting and formatting numeric values from
39 * structure data.
40 */
41
42
43
44
45 /*
46 * Extract the integral field into the value union given and
47 * perform any necessary byte swapping to make the result readable
48 * on the elfdump host.
49 */
50 void
sl_extract_num_field(const char * data,int do_swap,const sl_field_t * fdesc,sl_data_t * field_data)51 sl_extract_num_field(const char *data, int do_swap, const sl_field_t *fdesc,
52 sl_data_t *field_data)
53 {
54 /* Copy the value bytes into our union */
55 (void) memcpy(field_data, data + fdesc->slf_offset,
56 fdesc->slf_eltlen);
57
58 /* Do byte swapping as necessary */
59 if (do_swap) {
60 switch (fdesc->slf_eltlen) {
61 case 2:
62 field_data->sld_ui16 = BSWAP_HALF(field_data->sld_ui16);
63 break;
64
65 case 4:
66 field_data->sld_ui32 = BSWAP_WORD(field_data->sld_ui32);
67 break;
68
69 case 8:
70 field_data->sld_ui64 =
71 BSWAP_LWORD(field_data->sld_ui64);
72 break;
73 }
74 }
75 }
76
77 /*
78 * Extract the given integer field, and return its value, cast
79 * to Word. Note that this operation must not be used on values
80 * that can be negative, or larger than 32-bits, as information
81 * can be lost.
82 */
83 Word
sl_extract_as_word(const char * data,int do_swap,const sl_field_t * fdesc)84 sl_extract_as_word(const char *data, int do_swap, const sl_field_t *fdesc)
85 {
86 sl_data_t v;
87
88 /* Extract the value from the raw data */
89 sl_extract_num_field(data, do_swap, fdesc, &v);
90
91 if (fdesc->slf_sign) {
92 switch (fdesc->slf_eltlen) {
93 case 1:
94 return ((Word) v.sld_i8);
95 case 2:
96 return ((Word) v.sld_i16);
97 case 4:
98 return ((Word) v.sld_i32);
99 case 8:
100 return ((Word) v.sld_i64);
101 }
102 } else {
103 switch (fdesc->slf_eltlen) {
104 case 1:
105 return ((Word) v.sld_ui8);
106 case 2:
107 return ((Word) v.sld_ui16);
108 case 4:
109 return ((Word) v.sld_ui32);
110 case 8:
111 return ((Word) v.sld_ui64);
112 }
113 }
114
115 /* This should not be reached */
116 assert(0);
117 return (0);
118 }
119
120
121 /*
122 * Extract the given integer field, and return its value, cast
123 * to Word. Note that this operation must not be used on values
124 * that can be negative, as information can be lost.
125 */
126 Lword
sl_extract_as_lword(const char * data,int do_swap,const sl_field_t * fdesc)127 sl_extract_as_lword(const char *data, int do_swap, const sl_field_t *fdesc)
128 {
129 sl_data_t v;
130
131 /* Extract the value from the raw data */
132 sl_extract_num_field(data, do_swap, fdesc, &v);
133
134 if (fdesc->slf_sign) {
135 switch (fdesc->slf_eltlen) {
136 case 1:
137 return ((Lword) v.sld_i8);
138 case 2:
139 return ((Lword) v.sld_i16);
140 case 4:
141 return ((Lword) v.sld_i32);
142 case 8:
143 return ((Lword) v.sld_i64);
144 }
145 } else {
146 switch (fdesc->slf_eltlen) {
147 case 1:
148 return ((Lword) v.sld_ui8);
149 case 2:
150 return ((Lword) v.sld_ui16);
151 case 4:
152 return ((Lword) v.sld_ui32);
153 case 8:
154 return ((Lword) v.sld_ui64);
155 }
156 }
157
158 /* This should not be reached */
159 assert(0);
160 return (0);
161 }
162
163
164 /*
165 * Extract the given integer field, and return its value, cast
166 * to int32_t. Note that this operation must not be used on unsigned
167 * values larger than 31-bits, or on signed values larger than 32-bits,
168 * as information can be lost.
169 */
170 Sword
sl_extract_as_sword(const char * data,int do_swap,const sl_field_t * fdesc)171 sl_extract_as_sword(const char *data, int do_swap, const sl_field_t *fdesc)
172 {
173 sl_data_t v;
174
175 /* Extract the value from the raw data */
176 sl_extract_num_field(data, do_swap, fdesc, &v);
177
178 if (fdesc->slf_sign) {
179 switch (fdesc->slf_eltlen) {
180 case 1:
181 return ((Sword)v.sld_i8);
182 case 2:
183 return ((Sword)v.sld_i16);
184 case 4:
185 return ((Sword)v.sld_i32);
186 case 8:
187 return ((Sword)v.sld_i64);
188 }
189 } else {
190 switch (fdesc->slf_eltlen) {
191 case 1:
192 return ((Sword)v.sld_ui8);
193 case 2:
194 return ((Sword)v.sld_ui16);
195 case 4:
196 return ((Sword)v.sld_ui32);
197 case 8:
198 return ((Sword)v.sld_ui64);
199 }
200 }
201
202 /* This should not be reached */
203 assert(0);
204 return (0);
205 }
206
207
208 /*
209 * Extract the integral field and format it into the supplied buffer.
210 */
211 const char *
sl_fmt_num(const char * data,int do_swap,const sl_field_t * fdesc,sl_fmt_num_t fmt_type,sl_fmtbuf_t buf)212 sl_fmt_num(const char *data, int do_swap, const sl_field_t *fdesc,
213 sl_fmt_num_t fmt_type, sl_fmtbuf_t buf)
214 {
215 /*
216 * These static arrays are indexed by [fdesc->slf_sign][fmt_type]
217 * to get a format string to use for the specified combination.
218 */
219 static const char *fmt_i8[2][3] = {
220 {
221 MSG_ORIG(MSG_CNOTE_FMT_U),
222 MSG_ORIG(MSG_CNOTE_FMT_X),
223 MSG_ORIG(MSG_CNOTE_FMT_Z2X)
224 },
225 {
226 MSG_ORIG(MSG_CNOTE_FMT_D),
227 MSG_ORIG(MSG_CNOTE_FMT_X),
228 MSG_ORIG(MSG_CNOTE_FMT_Z2X)
229 }
230 };
231 static const char *fmt_i16[2][3] = {
232 {
233 MSG_ORIG(MSG_CNOTE_FMT_U),
234 MSG_ORIG(MSG_CNOTE_FMT_X),
235 MSG_ORIG(MSG_CNOTE_FMT_Z4X)
236 },
237 {
238 MSG_ORIG(MSG_CNOTE_FMT_D),
239 MSG_ORIG(MSG_CNOTE_FMT_X),
240 MSG_ORIG(MSG_CNOTE_FMT_Z4X)
241 }
242 };
243 static const char *fmt_i32[2][3] = {
244 {
245 MSG_ORIG(MSG_CNOTE_FMT_U),
246 MSG_ORIG(MSG_CNOTE_FMT_X),
247 MSG_ORIG(MSG_CNOTE_FMT_Z8X)
248 },
249 {
250 MSG_ORIG(MSG_CNOTE_FMT_D),
251 MSG_ORIG(MSG_CNOTE_FMT_X),
252 MSG_ORIG(MSG_CNOTE_FMT_Z8X)
253 }
254 };
255 static const char *fmt_i64[2][3] = {
256 {
257 MSG_ORIG(MSG_CNOTE_FMT_LLU),
258 MSG_ORIG(MSG_CNOTE_FMT_LLX),
259 MSG_ORIG(MSG_CNOTE_FMT_Z16LLX)
260 },
261 {
262 MSG_ORIG(MSG_CNOTE_FMT_LLD),
263 MSG_ORIG(MSG_CNOTE_FMT_LLX),
264 MSG_ORIG(MSG_CNOTE_FMT_Z16LLX)
265 }
266 };
267
268 sl_data_t v;
269
270 /* Extract the value from the raw data */
271 sl_extract_num_field(data, do_swap, fdesc, &v);
272
273 /*
274 * Format into the buffer. Note that we depend on the signed
275 * and unsigned versions of each width being equivalent as long
276 * as the format specifies the proper formatting.
277 */
278 switch (fdesc->slf_eltlen) {
279 case 1:
280 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
281 fmt_i8[fdesc->slf_sign][fmt_type], (uint32_t)v.sld_ui8);
282 break;
283
284 case 2:
285 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
286 fmt_i16[fdesc->slf_sign][fmt_type], (uint32_t)v.sld_ui16);
287 break;
288
289 case 4:
290 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
291 fmt_i32[fdesc->slf_sign][fmt_type], v.sld_ui32);
292 break;
293
294 case 8:
295 (void) snprintf(buf, sizeof (sl_fmtbuf_t),
296 fmt_i64[fdesc->slf_sign][fmt_type], v.sld_ui64);
297 break;
298 }
299
300 return (buf);
301 }
302
303 /*
304 * Return structure layout definition for the given machine type,
305 * or NULL if the specified machine is not supported.
306 */
307 const sl_arch_layout_t *
sl_mach(Half mach)308 sl_mach(Half mach)
309 {
310 switch (mach) {
311 case EM_386:
312 return (struct_layout_i386());
313
314 case EM_AMD64:
315 return (struct_layout_amd64());
316
317 case EM_SPARC:
318 case EM_SPARC32PLUS:
319 return (struct_layout_sparc());
320
321 case EM_SPARCV9:
322 return (struct_layout_sparcv9());
323 }
324
325 /* Unsupported architecture */
326 return (NULL);
327 }
328