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
sl_extract_num_field(const char * data,int do_swap,const sl_field_t * fdesc,sl_data_t * field_data)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
sl_extract_as_word(const char * data,int do_swap,const sl_field_t * fdesc)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
sl_extract_as_lword(const char * data,int do_swap,const sl_field_t * fdesc)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
sl_extract_as_sword(const char * data,int do_swap,const sl_field_t * fdesc)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 *
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*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 *
sl_mach(Half mach)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