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