elfcap.c (d0f8ff6ee41946134faff06b3a9f643e21aefa78) elfcap.c (99f63845ee65f89a523460ce4b6b0603a06eceb7)
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

--- 20 unchanged lines hidden (view full) ---

29/* LINTLIBRARY */
30
31/*
32 * String conversion routine for hardware capabilities types.
33 */
34#include <strings.h>
35#include <stdio.h>
36#include <ctype.h>
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

--- 20 unchanged lines hidden (view full) ---

29/* LINTLIBRARY */
30
31/*
32 * String conversion routine for hardware capabilities types.
33 */
34#include <strings.h>
35#include <stdio.h>
36#include <ctype.h>
37#include <limits.h>
38#include <sys/machelf.h>
39#include <sys/elf.h>
40#include <sys/auxv_SPARC.h>
41#include <sys/auxv_386.h>
42#include <elfcap.h>
43
44/*
37#include <sys/machelf.h>
38#include <sys/elf.h>
39#include <sys/auxv_SPARC.h>
40#include <sys/auxv_386.h>
41#include <elfcap.h>
42
43/*
45 * Define separators for val2str processing.
44 * Given a literal string, generate an initialization for an
45 * elfcap_str_t value.
46 */
46 */
47static const Fmt_desc format[] = {
48 {" ", 1 },
49 {" ", 2 },
50 {" | ", 3 }
51};
47#define STRDESC(_str) { _str, sizeof (_str) - 1 }
52
53/*
48
49/*
54 * Define all known capabilities as both lower and upper case strings. This
55 * duplication is necessary, rather than have one string and use something
56 * like toupper(), as a client such as ld.so.1 doesn't need the overhead of
57 * dragging in the internationalization support of toupper(). The Intel 3DNow
58 * flags are a slightly odd convention too.
50 * The items in the elfcap_desc_t arrays are required to be
51 * ordered so that the array index is related to the
52 * c_val field as:
59 *
53 *
60 * Define all known software capabilities.
54 * array[ndx].c_val = 2^ndx
55 *
56 * meaning that
57 *
58 * array[0].c_val = 2^0 = 1
59 * array[1].c_val = 2^1 = 2
60 * array[2].c_val = 2^2 = 4
61 * .
62 * .
63 * .
64 *
65 * Since 0 is not a valid value for the c_val field, we use it to
66 * mark an array entry that is a placeholder. This can happen if there
67 * is a hole in the assigned bits.
68 *
69 * The RESERVED_ELFCAP_DESC macro is used to reserve such holes.
61 */
70 */
62#ifdef CAP_UPPERCASE
63static const char Sf1_fpknwn[] = "FPKNWN";
64static const char Sf1_fpused[] = "FPUSED";
65#elif CAP_LOWERCASE
66static const char Sf1_fpknwn[] = "fpknwn";
67static const char Sf1_fpused[] = "fpused";
68#else
69#error "Software Capabilities - what case do you want?"
70#endif
71#define RESERVED_ELFCAP_DESC { 0, { NULL, 0 }, { NULL, 0 }, { NULL, 0 } }
71
72/*
72
73/*
73 * Order the software capabilities to match their numeric value. See SF1_SUNW_
74 * values in sys/elf.h.
74 * Define separators for output string processing. This must be kept in
75 * sync with the elfcap_fmt_t values in elfcap.h.
75 */
76 */
76static const Cap_desc sf1[] = {
77 { SF1_SUNW_FPKNWN, Sf1_fpknwn, (sizeof (Sf1_fpknwn) - 1) },
78 { SF1_SUNW_FPUSED, Sf1_fpused, (sizeof (Sf1_fpused) - 1) }
77static const elfcap_str_t format[] = {
78 STRDESC(" "), /* ELFCAP_FMT_SNGSPACE */
79 STRDESC(" "), /* ELFCAP_FMT_DBLSPACE */
80 STRDESC(" | ") /* ELFCAP_FMT_PIPSPACE */
79};
81};
80static const uint_t sf1_num = sizeof (sf1) / sizeof (Cap_desc);
82#define FORMAT_NELTS (sizeof (format) / sizeof (format[0]))
81
83
84
85
82/*
86/*
83 * Define all known SPARC hardware capabilities.
87 * Define all known software capabilities in all the supported styles.
88 * Order the capabilities by their numeric value. See SF1_SUNW_
89 * values in sys/elf.h.
84 */
90 */
85#ifdef CAP_UPPERCASE
86static const char Hw1_s_mul32[] = "MUL32";
87static const char Hw1_s_div32[] = "DIV32";
88static const char Hw1_s_fsmuld[] = "FSMULD";
89static const char Hw1_s_v8plus[] = "V8PLUS";
90static const char Hw1_s_popc[] = "POPC";
91static const char Hw1_s_vis[] = "VIS";
92static const char Hw1_s_vis2[] = "VIS2";
93static const char Hw1_s_asi_blk_init[] = "ASI_BLK_INIT";
94static const char Hw1_s_fmaf[] = "FMAF";
95static const char Hw1_s_reserved1[] = "RESERVED1";
96static const char Hw1_s_reserved2[] = "RESERVED2";
97static const char Hw1_s_reserved3[] = "RESERVED3";
98static const char Hw1_s_reserved4[] = "RESERVED4";
99static const char Hw1_s_reserved5[] = "RESERVED5";
100static const char Hw1_s_fjfmau[] = "FJFMAU";
101static const char Hw1_s_ima[] = "IMA";
102#elif CAP_LOWERCASE
103static const char Hw1_s_mul32[] = "mul32";
104static const char Hw1_s_div32[] = "div32";
105static const char Hw1_s_fsmuld[] = "fsmuld";
106static const char Hw1_s_v8plus[] = "v8plus";
107static const char Hw1_s_popc[] = "popc";
108static const char Hw1_s_vis[] = "vis";
109static const char Hw1_s_vis2[] = "vis2";
110static const char Hw1_s_asi_blk_init[] = "asi_blk_init";
111static const char Hw1_s_fmaf[] = "fmaf";
112static const char Hw1_s_reserved1[] = "reserved1";
113static const char Hw1_s_reserved2[] = "reserved2";
114static const char Hw1_s_reserved3[] = "reserved3";
115static const char Hw1_s_reserved4[] = "reserved4";
116static const char Hw1_s_reserved5[] = "reserved5";
117static const char Hw1_s_fjfmau[] = "fjfmau";
118static const char Hw1_s_ima[] = "ima";
91static const elfcap_desc_t sf1[ELFCAP_NUM_SF1] = {
92 { /* 0x00000001 */
93 SF1_SUNW_FPKNWN, STRDESC("SF1_SUNW_FPKNWN"),
94 STRDESC("FPKNWN"), STRDESC("fpknwn")
95 },
96 { /* 0x00000002 */
97 SF1_SUNW_FPUSED, STRDESC("SF1_SUNW_FPUSED"),
98 STRDESC("FPUSED"), STRDESC("fpused"),
99 }
100};
119
101
120#else
121#error "Hardware Capabilities (sparc) - what case do you want?"
122#endif
123
102
103
124/*
125 * Order the SPARC hardware capabilities to match their numeric value. See
126 * AV_SPARC_ values in sys/auxv_SPARC.h.
127 */
104/*
105 * Order the SPARC hardware capabilities to match their numeric value. See
106 * AV_SPARC_ values in sys/auxv_SPARC.h.
107 */
128static const Cap_desc hw1_s[] = {
129 { AV_SPARC_MUL32, Hw1_s_mul32, sizeof (Hw1_s_mul32) - 1 },
130 { AV_SPARC_DIV32, Hw1_s_div32, sizeof (Hw1_s_div32) - 1 },
131 { AV_SPARC_FSMULD, Hw1_s_fsmuld, sizeof (Hw1_s_fsmuld) - 1 },
132 { AV_SPARC_V8PLUS, Hw1_s_v8plus, sizeof (Hw1_s_v8plus) - 1 },
133 { AV_SPARC_POPC, Hw1_s_popc, sizeof (Hw1_s_popc) - 1 },
134 { AV_SPARC_VIS, Hw1_s_vis, sizeof (Hw1_s_vis) - 1 },
135 { AV_SPARC_VIS2, Hw1_s_vis2, sizeof (Hw1_s_vis2) - 1 },
136 { AV_SPARC_ASI_BLK_INIT, Hw1_s_asi_blk_init,
137 sizeof (Hw1_s_asi_blk_init) - 1 },
138 { AV_SPARC_FMAF, Hw1_s_fmaf, sizeof (Hw1_s_fmaf) - 1 },
139 { 0, Hw1_s_reserved1, sizeof (Hw1_s_reserved1) - 1 },
140 { 0, Hw1_s_reserved2, sizeof (Hw1_s_reserved2) - 1 },
141 { 0, Hw1_s_reserved3, sizeof (Hw1_s_reserved3) - 1 },
142 { 0, Hw1_s_reserved4, sizeof (Hw1_s_reserved4) - 1 },
143 { 0, Hw1_s_reserved5, sizeof (Hw1_s_reserved5) - 1 },
144 { AV_SPARC_FJFMAU, Hw1_s_fjfmau, sizeof (Hw1_s_fjfmau) - 1 },
145 { AV_SPARC_IMA, Hw1_s_ima, sizeof (Hw1_s_ima) - 1 }
108static const elfcap_desc_t hw1_sparc[ELFCAP_NUM_HW1_SPARC] = {
109 { /* 0x00000001 */
110 AV_SPARC_MUL32, STRDESC("AV_SPARC_MUL32"),
111 STRDESC("MUL32"), STRDESC("mul32"),
112 },
113 { /* 0x00000002 */
114 AV_SPARC_DIV32, STRDESC("AV_SPARC_DIV32"),
115 STRDESC("DIV32"), STRDESC("div32"),
116 },
117 { /* 0x00000004 */
118 AV_SPARC_FSMULD, STRDESC("AV_SPARC_FSMULD"),
119 STRDESC("FSMULD"), STRDESC("fsmuld"),
120 },
121 { /* 0x00000008 */
122 AV_SPARC_V8PLUS, STRDESC("AV_SPARC_V8PLUS"),
123 STRDESC("V8PLUS"), STRDESC("v8plus"),
124 },
125 { /* 0x00000010 */
126 AV_SPARC_POPC, STRDESC("AV_SPARC_POPC"),
127 STRDESC("POPC"), STRDESC("popc"),
128 },
129 { /* 0x00000020 */
130 AV_SPARC_VIS, STRDESC("AV_SPARC_VIS"),
131 STRDESC("VIS"), STRDESC("vis"),
132 },
133 { /* 0x00000040 */
134 AV_SPARC_VIS2, STRDESC("AV_SPARC_VIS2"),
135 STRDESC("VIS2"), STRDESC("vis2"),
136 },
137 { /* 0x00000080 */
138 AV_SPARC_ASI_BLK_INIT, STRDESC("AV_SPARC_ASI_BLK_INIT"),
139 STRDESC("ASI_BLK_INIT"), STRDESC("asi_blk_init"),
140 },
141 { /* 0x00000100 */
142 AV_SPARC_FMAF, STRDESC("AV_SPARC_FMAF"),
143 STRDESC("FMAF"), STRDESC("fmaf"),
144 },
145 RESERVED_ELFCAP_DESC, /* 0x00000200 */
146 RESERVED_ELFCAP_DESC, /* 0x00000400 */
147 RESERVED_ELFCAP_DESC, /* 0x00000800 */
148 RESERVED_ELFCAP_DESC, /* 0x00001000 */
149 RESERVED_ELFCAP_DESC, /* 0x00002000 */
150 { /* 0x00004000 */
151 AV_SPARC_FJFMAU, STRDESC("AV_SPARC_FJFMAU"),
152 STRDESC("FJFMAU"), STRDESC("fjfmau"),
153 },
154 { /* 0x00008000 */
155 AV_SPARC_IMA, STRDESC("AV_SPARC_IMA"),
156 STRDESC("IMA"), STRDESC("ima"),
157 }
146};
158};
147static const uint_t hw1_s_num = sizeof (hw1_s) / sizeof (Cap_desc);
148
159
149/*
150 * Define all known Intel hardware capabilities.
151 */
152#ifdef CAP_UPPERCASE
153static const char Hw1_i_fpu[] = "FPU";
154static const char Hw1_i_tsc[] = "TSC";
155static const char Hw1_i_cx8[] = "CX8";
156static const char Hw1_i_sep[] = "SEP";
157static const char Hw1_i_amd_sysc[] = "AMD_SYSC";
158static const char Hw1_i_cmov[] = "CMOV";
159static const char Hw1_i_mmx[] = "MMX";
160static const char Hw1_i_amd_mmx[] = "AMD_MMX";
161static const char Hw1_i_amd_3dnow[] = "AMD_3DNow";
162static const char Hw1_i_amd_3dnowx[] = "AMD_3DNowx";
163static const char Hw1_i_fxsr[] = "FXSR";
164static const char Hw1_i_sse[] = "SSE";
165static const char Hw1_i_sse2[] = "SSE2";
166static const char Hw1_i_pause[] = "PAUSE";
167static const char Hw1_i_sse3[] = "SSE3";
168static const char Hw1_i_mon[] = "MON";
169static const char Hw1_i_cx16[] = "CX16";
170static const char Hw1_i_ahf[] = "AHF";
171static const char Hw1_i_tscp[] = "TSCP";
172static const char Hw1_i_amd_sse4a[] = "AMD_SSE4A";
173static const char Hw1_i_popcnt[] = "POPCNT";
174static const char Hw1_i_amd_lzcnt[] = "AMD_LZCNT";
175static const char Hw1_i_ssse3[] = "SSSE3";
176static const char Hw1_i_sse4_1[] = "SSE4.1";
177static const char Hw1_i_sse4_2[] = "SSE4.2";
178#elif CAP_LOWERCASE
179static const char Hw1_i_fpu[] = "fpu";
180static const char Hw1_i_tsc[] = "tsc";
181static const char Hw1_i_cx8[] = "cx8";
182static const char Hw1_i_sep[] = "sep";
183static const char Hw1_i_amd_sysc[] = "amd_sysc";
184static const char Hw1_i_cmov[] = "cmov";
185static const char Hw1_i_mmx[] = "mmx";
186static const char Hw1_i_amd_mmx[] = "amd_mmx";
187static const char Hw1_i_amd_3dnow[] = "amd_3dnow";
188static const char Hw1_i_amd_3dnowx[] = "amd_3dnowx";
189static const char Hw1_i_fxsr[] = "fxsr";
190static const char Hw1_i_sse[] = "sse";
191static const char Hw1_i_sse2[] = "sse2";
192static const char Hw1_i_pause[] = "pause";
193static const char Hw1_i_sse3[] = "sse3";
194static const char Hw1_i_mon[] = "mon";
195static const char Hw1_i_cx16[] = "cx16";
196static const char Hw1_i_ahf[] = "ahf";
197static const char Hw1_i_tscp[] = "tscp";
198static const char Hw1_i_amd_sse4a[] = "amd_sse4a";
199static const char Hw1_i_popcnt[] = "popcnt";
200static const char Hw1_i_amd_lzcnt[] = "amd_lzcnt";
201static const char Hw1_i_ssse3[] = "ssse3";
202static const char Hw1_i_sse4_1[] = "sse4.1";
203static const char Hw1_i_sse4_2[] = "sse4.2";
204#else
205#error "Hardware Capabilities (intel) - what case do you want?"
206#endif
207
160
161
208/*
209 * Order the Intel hardware capabilities to match their numeric value. See
210 * AV_386_ values in sys/auxv_386.h.
211 */
162/*
163 * Order the Intel hardware capabilities to match their numeric value. See
164 * AV_386_ values in sys/auxv_386.h.
165 */
212static const Cap_desc hw1_i[] = {
213 { AV_386_FPU, Hw1_i_fpu, sizeof (Hw1_i_fpu) - 1 },
214 { AV_386_TSC, Hw1_i_tsc, sizeof (Hw1_i_tsc) - 1 },
215 { AV_386_CX8, Hw1_i_cx8, sizeof (Hw1_i_cx8) - 1 },
216 { AV_386_SEP, Hw1_i_sep, sizeof (Hw1_i_sep) - 1 },
217 { AV_386_AMD_SYSC, Hw1_i_amd_sysc, sizeof (Hw1_i_amd_sysc) - 1 },
218 { AV_386_CMOV, Hw1_i_cmov, sizeof (Hw1_i_cmov) - 1 },
219 { AV_386_MMX, Hw1_i_mmx, sizeof (Hw1_i_mmx) - 1 },
220 { AV_386_AMD_MMX, Hw1_i_amd_mmx, sizeof (Hw1_i_amd_mmx) - 1 },
221 { AV_386_AMD_3DNow, Hw1_i_amd_3dnow,
222 sizeof (Hw1_i_amd_3dnow) - 1 },
223 { AV_386_AMD_3DNowx, Hw1_i_amd_3dnowx,
224 sizeof (Hw1_i_amd_3dnowx) - 1 },
225 { AV_386_FXSR, Hw1_i_fxsr, sizeof (Hw1_i_fxsr) - 1 },
226 { AV_386_SSE, Hw1_i_sse, sizeof (Hw1_i_sse) - 1 },
227 { AV_386_SSE2, Hw1_i_sse2, sizeof (Hw1_i_sse2) - 1 },
228 { AV_386_PAUSE, Hw1_i_pause, sizeof (Hw1_i_pause) - 1 },
229 { AV_386_SSE3, Hw1_i_sse3, sizeof (Hw1_i_sse3) - 1 },
230 { AV_386_MON, Hw1_i_mon, sizeof (Hw1_i_mon) - 1 },
231 { AV_386_CX16, Hw1_i_cx16, sizeof (Hw1_i_cx16) - 1 },
232 { AV_386_AHF, Hw1_i_ahf, sizeof (Hw1_i_ahf) - 1 },
233 { AV_386_TSCP, Hw1_i_tscp, sizeof (Hw1_i_tscp) - 1 },
234 { AV_386_AMD_SSE4A, Hw1_i_amd_sse4a,
235 sizeof (Hw1_i_amd_sse4a) - 1 },
236 { AV_386_POPCNT, Hw1_i_popcnt, sizeof (Hw1_i_popcnt) - 1 },
237 { AV_386_AMD_LZCNT, Hw1_i_amd_lzcnt,
238 sizeof (Hw1_i_amd_lzcnt) - 1 },
239 { AV_386_SSSE3, Hw1_i_ssse3, sizeof (Hw1_i_ssse3) - 1 },
240 { AV_386_SSE4_1, Hw1_i_sse4_1, sizeof (Hw1_i_sse4_1) - 1 },
241 { AV_386_SSE4_2, Hw1_i_sse4_2, sizeof (Hw1_i_sse4_2) - 1 }
166static const elfcap_desc_t hw1_386[ELFCAP_NUM_HW1_386] = {
167 { /* 0x00000001 */
168 AV_386_FPU, STRDESC("AV_386_FPU"),
169 STRDESC("FPU"), STRDESC("fpu"),
170 },
171 { /* 0x00000002 */
172 AV_386_TSC, STRDESC("AV_386_TSC"),
173 STRDESC("TSC"), STRDESC("tsc"),
174 },
175 { /* 0x00000004 */
176 AV_386_CX8, STRDESC("AV_386_CX8"),
177 STRDESC("CX8"), STRDESC("cx8"),
178 },
179 { /* 0x00000008 */
180 AV_386_SEP, STRDESC("AV_386_SEP"),
181 STRDESC("SEP"), STRDESC("sep"),
182 },
183 { /* 0x00000010 */
184 AV_386_AMD_SYSC, STRDESC("AV_386_AMD_SYSC"),
185 STRDESC("AMD_SYSC"), STRDESC("amd_sysc"),
186 },
187 { /* 0x00000020 */
188 AV_386_CMOV, STRDESC("AV_386_CMOV"),
189 STRDESC("CMOV"), STRDESC("cmov"),
190 },
191 { /* 0x00000040 */
192 AV_386_MMX, STRDESC("AV_386_MMX"),
193 STRDESC("MMX"), STRDESC("mmx"),
194 },
195 { /* 0x00000080 */
196 AV_386_AMD_MMX, STRDESC("AV_386_AMD_MMX"),
197 STRDESC("AMD_MMX"), STRDESC("amd_mmx"),
198 },
199 { /* 0x00000100 */
200 AV_386_AMD_3DNow, STRDESC("AV_386_AMD_3DNow"),
201 STRDESC("AMD_3DNow"), STRDESC("amd_3dnow"),
202 },
203 { /* 0x00000200 */
204 AV_386_AMD_3DNowx, STRDESC("AV_386_AMD_3DNowx"),
205 STRDESC("AMD_3DNowx"), STRDESC("amd_3dnowx"),
206 },
207 { /* 0x00000400 */
208 AV_386_FXSR, STRDESC("AV_386_FXSR"),
209 STRDESC("FXSR"), STRDESC("fxsr"),
210 },
211 { /* 0x00000800 */
212 AV_386_SSE, STRDESC("AV_386_SSE"),
213 STRDESC("SSE"), STRDESC("sse"),
214 },
215 { /* 0x00001000 */
216 AV_386_SSE2, STRDESC("AV_386_SSE2"),
217 STRDESC("SSE2"), STRDESC("sse2"),
218 },
219 { /* 0x00002000 */
220 AV_386_PAUSE, STRDESC("AV_386_PAUSE"),
221 STRDESC("PAUSE"), STRDESC("pause"),
222 },
223 { /* 0x00004000 */
224 AV_386_SSE3, STRDESC("AV_386_SSE3"),
225 STRDESC("SSE3"), STRDESC("sse3"),
226 },
227 { /* 0x00008000 */
228 AV_386_MON, STRDESC("AV_386_MON"),
229 STRDESC("MON"), STRDESC("mon"),
230 },
231 { /* 0x00010000 */
232 AV_386_CX16, STRDESC("AV_386_CX16"),
233 STRDESC("CX16"), STRDESC("cx16"),
234 },
235 { /* 0x00020000 */
236 AV_386_AHF, STRDESC("AV_386_AHF"),
237 STRDESC("AHF"), STRDESC("ahf"),
238 },
239 { /* 0x00040000 */
240 AV_386_TSCP, STRDESC("AV_386_TSCP"),
241 STRDESC("TSCP"), STRDESC("tscp"),
242 },
243 { /* 0x00080000 */
244 AV_386_AMD_SSE4A, STRDESC("AV_386_AMD_SSE4A"),
245 STRDESC("AMD_SSE4A"), STRDESC("amd_sse4a"),
246 },
247 { /* 0x00100000 */
248 AV_386_POPCNT, STRDESC("AV_386_POPCNT"),
249 STRDESC("POPCNT"), STRDESC("popcnt"),
250 },
251 { /* 0x00200000 */
252 AV_386_AMD_LZCNT, STRDESC("AV_386_AMD_LZCNT"),
253 STRDESC("AMD_LZCNT"), STRDESC("amd_lzcnt"),
254 },
255 { /* 0x00400000 */
256 AV_386_SSSE3, STRDESC("AV_386_SSSE3"),
257 STRDESC("SSSE3"), STRDESC("ssse3"),
258 },
259 { /* 0x00800000 */
260 AV_386_SSE4_1, STRDESC("AV_386_SSE4_1"),
261 STRDESC("SSE4.1"), STRDESC("sse4.1"),
262 },
263 { /* 0x01000000 */
264 AV_386_SSE4_2, STRDESC("AV_386_SSE4_2"),
265 STRDESC("SSE4.2"), STRDESC("sse4.2"),
266 }
242};
267};
243static const uint_t hw1_i_num = sizeof (hw1_i) / sizeof (Cap_desc);
244
245/*
246 * Concatenate a token to the string buffer. This can be a capabilities token
247 * or a separator token.
248 */
268
269/*
270 * Concatenate a token to the string buffer. This can be a capabilities token
271 * or a separator token.
272 */
249static int
250token(char **ostr, size_t *olen, const char *nstr, size_t nlen)
273static elfcap_err_t
274token(char **ostr, size_t *olen, const elfcap_str_t *nstr)
251{
275{
252 if (*olen < nlen)
253 return (CAP_ERR_BUFOVFL);
276 if (*olen < nstr->s_len)
277 return (ELFCAP_ERR_BUFOVFL);
254
278
255 (void) strcat(*ostr, nstr);
256 *ostr += nlen;
257 *olen -= nlen;
279 (void) strcat(*ostr, nstr->s_str);
280 *ostr += nstr->s_len;
281 *olen -= nstr->s_len;
258
282
259 return (0);
283 return (ELFCAP_ERR_NONE);
260}
261
284}
285
286static elfcap_err_t
287get_str_desc(elfcap_style_t style, const elfcap_desc_t *cdp,
288 const elfcap_str_t **ret_str)
289{
290 switch (style) {
291 case ELFCAP_STYLE_FULL:
292 *ret_str = &cdp->c_full;
293 break;
294 case ELFCAP_STYLE_UC:
295 *ret_str = &cdp->c_uc;
296 break;
297 case ELFCAP_STYLE_LC:
298 *ret_str = &cdp->c_lc;
299 break;
300 default:
301 return (ELFCAP_ERR_INVSTYLE);
302 }
303
304 return (ELFCAP_ERR_NONE);
305}
306
307
262/*
263 * Expand a capabilities value into the strings defined in the associated
264 * capabilities descriptor.
265 */
308/*
309 * Expand a capabilities value into the strings defined in the associated
310 * capabilities descriptor.
311 */
266static int
267expand(uint64_t val, const Cap_desc *cdp, uint_t cnum, char *str, size_t slen,
268 int fmt)
312static elfcap_err_t
313expand(elfcap_style_t style, uint64_t val, const elfcap_desc_t *cdp,
314 uint_t cnum, char *str, size_t slen, elfcap_fmt_t fmt)
269{
315{
270 uint_t cnt, mask;
271 int follow = 0, err;
316 uint_t cnt;
317 int follow = 0, err;
318 const elfcap_str_t *nstr;
272
273 if (val == 0)
319
320 if (val == 0)
274 return (0);
321 return (ELFCAP_ERR_NONE);
275
322
276 for (cnt = WORD_BIT, mask = 0x80000000; cnt; cnt--,
277 (mask = mask >> 1)) {
278 if ((val & mask) && (cnt <= cnum) && cdp[cnt - 1].c_val) {
323 for (cnt = cnum; cnt > 0; cnt--) {
324 uint_t mask = cdp[cnt - 1].c_val;
325
326 if ((val & mask) != 0) {
279 if (follow++ && ((err = token(&str, &slen,
327 if (follow++ && ((err = token(&str, &slen,
280 format[fmt].f_str, format[fmt].f_len)) != 0))
328 &format[fmt])) != ELFCAP_ERR_NONE))
281 return (err);
282
329 return (err);
330
283 if ((err = token(&str, &slen, cdp[cnt - 1].c_str,
284 cdp[cnt - 1].c_len)) != 0)
331 err = get_str_desc(style, &cdp[cnt - 1], &nstr);
332 if (err != ELFCAP_ERR_NONE)
285 return (err);
333 return (err);
334 if ((err = token(&str, &slen, nstr)) != ELFCAP_ERR_NONE)
335 return (err);
286
287 val = val & ~mask;
288 }
289 }
290
291 /*
292 * If there are any unknown bits remaining display the numeric value.
293 */
294 if (val) {
336
337 val = val & ~mask;
338 }
339 }
340
341 /*
342 * If there are any unknown bits remaining display the numeric value.
343 */
344 if (val) {
295 if (follow && ((err = token(&str, &slen, format[fmt].f_str,
296 format[fmt].f_len)) != 0))
345 if (follow && ((err = token(&str, &slen, &format[fmt])) !=
346 ELFCAP_ERR_NONE))
297 return (err);
298
299 (void) snprintf(str, slen, "0x%llx", val);
300 }
347 return (err);
348
349 (void) snprintf(str, slen, "0x%llx", val);
350 }
301 return (0);
351 return (ELFCAP_ERR_NONE);
302}
303
304/*
305 * Expand a CA_SUNW_HW_1 value.
306 */
352}
353
354/*
355 * Expand a CA_SUNW_HW_1 value.
356 */
307int
308hwcap_1_val2str(uint64_t val, char *str, size_t len, int fmt, ushort_t mach)
357elfcap_err_t
358elfcap_hw1_to_str(elfcap_style_t style, uint64_t val, char *str,
359 size_t len, elfcap_fmt_t fmt, ushort_t mach)
309{
310 /*
311 * Initialize the string buffer, and validate the format request.
312 */
313 *str = '\0';
360{
361 /*
362 * Initialize the string buffer, and validate the format request.
363 */
364 *str = '\0';
314 if (fmt > CAP_MAX_TYPE)
315 return (CAP_ERR_INVFMT);
365 if ((fmt < 0) || (fmt >= FORMAT_NELTS))
366 return (ELFCAP_ERR_INVFMT);
316
317 if ((mach == EM_386) || (mach == EM_IA_64) || (mach == EM_AMD64))
367
368 if ((mach == EM_386) || (mach == EM_IA_64) || (mach == EM_AMD64))
318 return (expand(val, &hw1_i[0], hw1_i_num, str, len, fmt));
369 return (expand(style, val, &hw1_386[0], ELFCAP_NUM_HW1_386,
370 str, len, fmt));
319
320 if ((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
321 (mach == EM_SPARCV9))
371
372 if ((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
373 (mach == EM_SPARCV9))
322 return (expand(val, &hw1_s[0], hw1_s_num, str, len, fmt));
374 return (expand(style, val, hw1_sparc, ELFCAP_NUM_HW1_SPARC,
375 str, len, fmt));
323
376
324 return (CAP_ERR_UNKMACH);
377 return (ELFCAP_ERR_UNKMACH);
325}
326
327/*
328 * Expand a CA_SUNW_SF_1 value. Note, that at present these capabilities are
329 * common across all platforms. The use of "mach" is therefore redundant, but
378}
379
380/*
381 * Expand a CA_SUNW_SF_1 value. Note, that at present these capabilities are
382 * common across all platforms. The use of "mach" is therefore redundant, but
330 * is retained for compatibility with the interface of hwcap_1_val2str(), and
383 * is retained for compatibility with the interface of elfcap_hw1_to_str(), and
331 * possible future expansion.
332 */
384 * possible future expansion.
385 */
333int
386elfcap_err_t
334/* ARGSUSED4 */
387/* ARGSUSED4 */
335sfcap_1_val2str(uint64_t val, char *str, size_t len, int fmt, ushort_t mach)
388elfcap_sf1_to_str(elfcap_style_t style, uint64_t val, char *str,
389 size_t len, elfcap_fmt_t fmt, ushort_t mach)
336{
337 /*
338 * Initialize the string buffer, and validate the format request.
339 */
340 *str = '\0';
390{
391 /*
392 * Initialize the string buffer, and validate the format request.
393 */
394 *str = '\0';
341 if (fmt > CAP_MAX_TYPE)
342 return (CAP_ERR_INVFMT);
395 if ((fmt < 0) || (fmt >= FORMAT_NELTS))
396 return (ELFCAP_ERR_INVFMT);
343
397
344 return (expand(val, &sf1[0], sf1_num, str, len, fmt));
398 return (expand(style, val, &sf1[0], ELFCAP_NUM_SF1, str, len, fmt));
345}
346
347/*
399}
400
401/*
348 * Determine capability type from the capability tag.
402 * Given a capability tag type and value, map it to a string representation.
349 */
403 */
350int
351cap_val2str(uint64_t tag, uint64_t val, char *str, size_t len, int fmt,
352 ushort_t mach)
404elfcap_err_t
405elfcap_tag_to_str(elfcap_style_t style, uint64_t tag, uint64_t val,
406 char *str, size_t len, elfcap_fmt_t fmt, ushort_t mach)
353{
354 if (tag == CA_SUNW_HW_1)
407{
408 if (tag == CA_SUNW_HW_1)
355 return (hwcap_1_val2str(val, str, len, fmt, mach));
409 return (elfcap_hw1_to_str(style, val, str, len, fmt, mach));
356 if (tag == CA_SUNW_SF_1)
410 if (tag == CA_SUNW_SF_1)
357 return (sfcap_1_val2str(val, str, len, fmt, mach));
411 return (elfcap_sf1_to_str(style, val, str, len, fmt, mach));
358
412
359 return (CAP_ERR_UNKTAG);
413 return (ELFCAP_ERR_UNKTAG);
360}
361
362/*
363 * Determine a capabilities value from a capabilities string.
364 */
365static uint64_t
414}
415
416/*
417 * Determine a capabilities value from a capabilities string.
418 */
419static uint64_t
366value(const char *str, const Cap_desc *cdp, uint_t cnum)
420value(elfcap_style_t style, const char *str, const elfcap_desc_t *cdp,
421 uint_t cnum)
367{
422{
423 const elfcap_str_t *nstr;
368 uint_t num;
424 uint_t num;
425 int err;
369
370 for (num = 0; num < cnum; num++) {
426
427 for (num = 0; num < cnum; num++) {
371 if (strcmp(str, cdp[num].c_str) == 0)
428 /*
429 * Skip "reserved" bits. These are unassigned bits in the
430 * middle of the assigned range.
431 */
432 if (cdp[num].c_val == 0)
433 continue;
434
435 if ((err = get_str_desc(style, &cdp[num], &nstr)) != 0)
436 return (err);
437 if (strcmp(str, nstr->s_str) == 0)
372 return (cdp[num].c_val);
373 }
374 return (0);
375}
376
377uint64_t
438 return (cdp[num].c_val);
439 }
440 return (0);
441}
442
443uint64_t
378sfcap_1_str2val(const char *str, ushort_t mach)
444elfcap_sf1_from_str(elfcap_style_t style, const char *str, ushort_t mach)
379{
445{
380 return (value(str, &sf1[0], sf1_num));
446 return (value(style, str, &sf1[0], ELFCAP_NUM_SF1));
381}
382
383uint64_t
447}
448
449uint64_t
384hwcap_1_str2val(const char *str, ushort_t mach)
450elfcap_hw1_from_str(elfcap_style_t style, const char *str, ushort_t mach)
385{
386 if ((mach == EM_386) || (mach == EM_IA_64) || (mach == EM_AMD64))
451{
452 if ((mach == EM_386) || (mach == EM_IA_64) || (mach == EM_AMD64))
387 return (value(str, &hw1_i[0], hw1_i_num));
453 return (value(style, str, &hw1_386[0], ELFCAP_NUM_HW1_386));
388
389 if ((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
390 (mach == EM_SPARCV9))
454
455 if ((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
456 (mach == EM_SPARCV9))
391 return (value(str, &hw1_s[0], hw1_s_num));
457 return (value(style, str, hw1_sparc, ELFCAP_NUM_HW1_SPARC));
392
393 return (0);
394}
458
459 return (0);
460}
461
462/*
463 * These functions allow the caller to get direct access to the
464 * cap descriptors.
465 */
466const elfcap_desc_t *
467elfcap_getdesc_hw1_sparc(void)
468{
469 return (hw1_sparc);
470}
471
472const elfcap_desc_t *
473elfcap_getdesc_hw1_386(void)
474{
475 return (hw1_386);
476}
477
478const elfcap_desc_t *
479elfcap_getdesc_sf1(void)
480{
481 return (sf1);
482}