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