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 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <strings.h> 28 #include <dwarf.h> 29 #include "_conv.h" 30 #include <dwarf_msg.h> 31 32 /* 33 * This code is primarily of interest to elfdump. Separating it from dwarf_ehe 34 * allows other tools to use dwarf_ehe without also pulling this in. 35 */ 36 37 /* 38 * Translate DW_CFA_ codes, used to identify Call Frame Instructions. 39 */ 40 const char * 41 conv_dwarf_cfa(uchar_t op, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf) 42 { 43 static const Msg cfa[] = { 44 MSG_DW_CFA_NOP, MSG_DW_CFA_SET_LOC, 45 MSG_DW_CFA_ADVANCE_LOC_1, MSG_DW_CFA_ADVANCE_LOC_2, 46 MSG_DW_CFA_ADVANCE_LOC_4, MSG_DW_CFA_OFFSET_EXTENDED, 47 MSG_DW_CFA_RESTORE_EXTENDED, MSG_DW_CFA_UNDEFINED, 48 MSG_DW_CFA_SAME_VALUE, MSG_DW_CFA_REGISTER, 49 MSG_DW_CFA_REMEMBER_STATE, MSG_DW_CFA_RESTORE_STATE, 50 MSG_DW_CFA_DEF_CFA, MSG_DW_CFA_DEF_CFA_REGISTER, 51 MSG_DW_CFA_DEF_CFA_OFFSET, MSG_DW_CFA_DEF_CFA_EXPRESSION, 52 MSG_DW_CFA_EXPRESSION, MSG_DW_CFA_OFFSET_EXTENDED_SF, 53 MSG_DW_CFA_DEF_CFA_SF, MSG_DW_CFA_DEF_CFA_OFFSET_SF, 54 MSG_DW_CFA_VAL_OFFSET, MSG_DW_CFA_VAL_OFFSET_SF, 55 MSG_DW_CFA_VAL_EXPRESSION 56 }; 57 static const Msg cfa_mips[] = { MSG_DW_CFA_MIPS_ADV_LOC8 }; 58 static const Msg cfa_gnu[] = { 59 MSG_DW_CFA_GNU_WINDOW_SAVE, MSG_DW_CFA_GNU_ARGS_SIZE, 60 MSG_DW_CFA_GNU_NEGATIVE_OFF_X 61 }; 62 static const conv_ds_msg_t ds_msg_cfa = { 63 CONV_DS_MSG_INIT(0, cfa) }; 64 static const conv_ds_msg_t ds_msg_cfa_mips = { 65 CONV_DS_MSG_INIT(0x1d, cfa_mips) }; 66 static const conv_ds_msg_t ds_msg_cfa_gnu = { 67 CONV_DS_MSG_INIT(0x2d, cfa_gnu) }; 68 static const conv_ds_t *ds_cfa[] = { CONV_DS_ADDR(ds_msg_cfa), 69 CONV_DS_ADDR(ds_msg_cfa_mips), CONV_DS_ADDR(ds_msg_cfa_gnu), NULL }; 70 71 72 /* 73 * DWARF CFA opcodes are bytes. The top 2 bits are a primary 74 * opcode, and if zero, the lower 6 bits specify a sub-opcode 75 */ 76 switch (op >> 6) { 77 case 0x1: 78 return (MSG_ORIG(MSG_DW_CFA_ADVANCE_LOC)); 79 case 0x2: 80 return (MSG_ORIG(MSG_DW_CFA_OFFSET)); 81 case 0x3: 82 return (MSG_ORIG(MSG_DW_CFA_RESTORE)); 83 } 84 85 return (conv_map_ds(ELFOSABI_NONE, EM_NONE, op, ds_cfa, 86 fmt_flags, inv_buf)); 87 } 88 89 /* 90 * Translate DWARF register numbers to hardware specific names 91 * 92 * If good_name is non-NULL, conv_dwarf_regname() will set the variable to 93 * True(1) if the returned string is considered to be a good name to 94 * display, and False(0) otherwise. To be considered "good": 95 * 96 * - The name must be a well known mnemonic for a register 97 * from the machine type in question. 98 * 99 * - The name must be different than the DWARF name for 100 * the same register. 101 * 102 * The returned string is usable, regardless of the value returned in 103 * *good_name. 104 */ 105 const char * 106 conv_dwarf_regname(Half mach, Word regno, Conv_fmt_flags_t fmt_flags, 107 int *good_name, Conv_inv_buf_t *inv_buf) 108 { 109 static const Msg reg_amd64[67] = { 110 MSG_REG_RAX, MSG_REG_RDX, 111 MSG_REG_RCX, MSG_REG_RBX, 112 MSG_REG_RSI, MSG_REG_RDI, 113 MSG_REG_RBP, MSG_REG_RSP, 114 MSG_REG_R8, MSG_REG_R9, 115 MSG_REG_R10, MSG_REG_R11, 116 MSG_REG_R12, MSG_REG_R13, 117 MSG_REG_R14, MSG_REG_R15, 118 MSG_REG_RA, MSG_REG_PERXMM0, 119 MSG_REG_PERXMM1, MSG_REG_PERXMM2, 120 MSG_REG_PERXMM3, MSG_REG_PERXMM4, 121 MSG_REG_PERXMM5, MSG_REG_PERXMM6, 122 MSG_REG_PERXMM7, MSG_REG_PERXMM8, 123 MSG_REG_PERXMM9, MSG_REG_PERXMM10, 124 MSG_REG_PERXMM11, MSG_REG_PERXMM12, 125 MSG_REG_PERXMM13, MSG_REG_PERXMM14, 126 MSG_REG_PERXMM15, MSG_REG_PERST0, 127 MSG_REG_PERST1, MSG_REG_PERST2, 128 MSG_REG_PERST3, MSG_REG_PERST4, 129 MSG_REG_PERST5, MSG_REG_PERST6, 130 MSG_REG_PERST7, MSG_REG_PERMM0, 131 MSG_REG_PERMM1, MSG_REG_PERMM2, 132 MSG_REG_PERMM3, MSG_REG_PERMM4, 133 MSG_REG_PERMM5, MSG_REG_PERMM6, 134 MSG_REG_PERMM7, MSG_REG_PERRFLAGS, 135 MSG_REG_PERES, MSG_REG_PERCS, 136 MSG_REG_PERSS, MSG_REG_PERDS, 137 MSG_REG_PERFS, MSG_REG_PERGS, 138 MSG_REG_RESERVED, MSG_REG_RESERVED, 139 MSG_REG_PERFSDOTBASE, MSG_REG_PERGSDOTBASE, 140 MSG_REG_RESERVED, MSG_REG_RESERVED, 141 MSG_REG_PERTR, MSG_REG_PERLDTR, 142 MSG_REG_PERMXCSR, MSG_REG_PERFCW, 143 MSG_REG_PERFSW 144 }; 145 static const conv_ds_msg_t ds_msg_reg_amd64 = { 146 CONV_DS_MSG_INIT(0, reg_amd64) }; 147 static const conv_ds_t *ds_reg_amd64[] = { 148 CONV_DS_ADDR(ds_msg_reg_amd64), NULL }; 149 150 static const Msg reg_i386[8] = { 151 MSG_REG_EAX, MSG_REG_ECX, 152 MSG_REG_EDX, MSG_REG_EBX, 153 MSG_REG_UESP, MSG_REG_EBP, 154 MSG_REG_ESI, MSG_REG_EDI 155 }; 156 static const conv_ds_msg_t ds_msg_reg_i386 = { 157 CONV_DS_MSG_INIT(0, reg_i386) }; 158 static const conv_ds_t *ds_reg_i386[] = { 159 CONV_DS_ADDR(ds_msg_reg_i386), NULL }; 160 161 static const Msg reg_sparc[64] = { 162 MSG_REG_G0, MSG_REG_G1, 163 MSG_REG_G2, MSG_REG_G3, 164 MSG_REG_G4, MSG_REG_G5, 165 MSG_REG_G6, MSG_REG_G7, 166 MSG_REG_O0, MSG_REG_O1, 167 MSG_REG_O2, MSG_REG_O3, 168 MSG_REG_O4, MSG_REG_O5, 169 MSG_REG_O6, MSG_REG_O7, 170 MSG_REG_L0, MSG_REG_L1, 171 MSG_REG_L2, MSG_REG_L3, 172 MSG_REG_L4, MSG_REG_L5, 173 MSG_REG_L6, MSG_REG_L7, 174 MSG_REG_I0, MSG_REG_I1, 175 MSG_REG_I2, MSG_REG_I3, 176 MSG_REG_I4, MSG_REG_I5, 177 MSG_REG_I6, MSG_REG_I7, 178 MSG_REG_F0, MSG_REG_F1, 179 MSG_REG_F2, MSG_REG_F3, 180 MSG_REG_F4, MSG_REG_F5, 181 MSG_REG_F6, MSG_REG_F7, 182 MSG_REG_F8, MSG_REG_F9, 183 MSG_REG_F10, MSG_REG_F11, 184 MSG_REG_F12, MSG_REG_F13, 185 MSG_REG_F14, MSG_REG_F15, 186 MSG_REG_F16, MSG_REG_F17, 187 MSG_REG_F18, MSG_REG_F19, 188 MSG_REG_F20, MSG_REG_F21, 189 MSG_REG_F22, MSG_REG_F23, 190 MSG_REG_F24, MSG_REG_F25, 191 MSG_REG_F26, MSG_REG_F27, 192 MSG_REG_F28, MSG_REG_F29, 193 MSG_REG_F30, MSG_REG_F31 194 }; 195 static const conv_ds_msg_t ds_msg_reg_sparc = { 196 CONV_DS_MSG_INIT(0, reg_sparc) }; 197 static const conv_ds_t *ds_reg_sparc[] = { 198 CONV_DS_ADDR(ds_msg_reg_sparc), NULL }; 199 200 switch (mach) { 201 case EM_AMD64: 202 /* 203 * amd64 has several in-bounds names we'd rather not 204 * use. R8-R15 have the same name as their DWARF counterparts. 205 * 56-57, and 60-61 are reserved, and don't have a good name. 206 */ 207 if (good_name) 208 *good_name = ((regno < 8) || (regno > 15)) && 209 (regno != 56) && (regno != 57) && 210 (regno != 60) && (regno != 61) && 211 (regno < ARRAY_NELTS(reg_amd64)); 212 return (conv_map_ds(ELFOSABI_NONE, EM_NONE, regno, 213 ds_reg_amd64, fmt_flags, inv_buf)); 214 215 case EM_386: 216 case EM_486: 217 if (good_name) 218 *good_name = (regno < ARRAY_NELTS(reg_i386)); 219 return (conv_map_ds(ELFOSABI_NONE, EM_NONE, regno, 220 ds_reg_i386, fmt_flags, inv_buf)); 221 222 case EM_SPARC: 223 case EM_SPARC32PLUS: 224 case EM_SPARCV9: 225 if (good_name) 226 *good_name = (regno < ARRAY_NELTS(reg_sparc)); 227 return (conv_map_ds(ELFOSABI_NONE, EM_NONE, regno, 228 ds_reg_sparc, fmt_flags, inv_buf)); 229 } 230 231 if (good_name) 232 *good_name = 0; 233 return (conv_invalid_val(inv_buf, regno, 0)); 234 } 235