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} |
|