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