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