17e16fca0SAli Bahrami /*
27e16fca0SAli Bahrami * CDDL HEADER START
37e16fca0SAli Bahrami *
47e16fca0SAli Bahrami * The contents of this file are subject to the terms of the
57e16fca0SAli Bahrami * Common Development and Distribution License (the "License").
67e16fca0SAli Bahrami * You may not use this file except in compliance with the License.
77e16fca0SAli Bahrami *
87e16fca0SAli Bahrami * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97e16fca0SAli Bahrami * or http://www.opensolaris.org/os/licensing.
107e16fca0SAli Bahrami * See the License for the specific language governing permissions
117e16fca0SAli Bahrami * and limitations under the License.
127e16fca0SAli Bahrami *
137e16fca0SAli Bahrami * When distributing Covered Code, include this CDDL HEADER in each
147e16fca0SAli Bahrami * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157e16fca0SAli Bahrami * If applicable, add the following below this CDDL HEADER, with the
167e16fca0SAli Bahrami * fields enclosed by brackets "[]" replaced with your own identifying
177e16fca0SAli Bahrami * information: Portions Copyright [yyyy] [name of copyright owner]
187e16fca0SAli Bahrami *
197e16fca0SAli Bahrami * CDDL HEADER END
207e16fca0SAli Bahrami */
217e16fca0SAli Bahrami
227e16fca0SAli Bahrami /*
237e16fca0SAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247e16fca0SAli Bahrami * Use is subject to license terms.
257e16fca0SAli Bahrami */
267e16fca0SAli Bahrami
277e16fca0SAli Bahrami #include <strings.h>
287e16fca0SAli Bahrami #include <dwarf.h>
297e16fca0SAli Bahrami #include "_conv.h"
307e16fca0SAli Bahrami #include <dwarf_msg.h>
317e16fca0SAli Bahrami
327e16fca0SAli Bahrami /*
337e16fca0SAli Bahrami * This code is primarily of interest to elfdump. Separating it from dwarf_ehe
347e16fca0SAli Bahrami * allows other tools to use dwarf_ehe without also pulling this in.
357e16fca0SAli Bahrami */
367e16fca0SAli Bahrami
377e16fca0SAli Bahrami /*
387e16fca0SAli Bahrami * Translate DW_CFA_ codes, used to identify Call Frame Instructions.
397e16fca0SAli Bahrami */
407e16fca0SAli Bahrami const char *
conv_dwarf_cfa(uchar_t op,Conv_fmt_flags_t fmt_flags,Conv_inv_buf_t * inv_buf)417e16fca0SAli Bahrami conv_dwarf_cfa(uchar_t op, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf)
427e16fca0SAli Bahrami {
437e16fca0SAli Bahrami static const Msg cfa[] = {
447e16fca0SAli Bahrami MSG_DW_CFA_NOP, MSG_DW_CFA_SET_LOC,
457e16fca0SAli Bahrami MSG_DW_CFA_ADVANCE_LOC_1, MSG_DW_CFA_ADVANCE_LOC_2,
467e16fca0SAli Bahrami MSG_DW_CFA_ADVANCE_LOC_4, MSG_DW_CFA_OFFSET_EXTENDED,
477e16fca0SAli Bahrami MSG_DW_CFA_RESTORE_EXTENDED, MSG_DW_CFA_UNDEFINED,
487e16fca0SAli Bahrami MSG_DW_CFA_SAME_VALUE, MSG_DW_CFA_REGISTER,
497e16fca0SAli Bahrami MSG_DW_CFA_REMEMBER_STATE, MSG_DW_CFA_RESTORE_STATE,
507e16fca0SAli Bahrami MSG_DW_CFA_DEF_CFA, MSG_DW_CFA_DEF_CFA_REGISTER,
517e16fca0SAli Bahrami MSG_DW_CFA_DEF_CFA_OFFSET, MSG_DW_CFA_DEF_CFA_EXPRESSION,
527e16fca0SAli Bahrami MSG_DW_CFA_EXPRESSION, MSG_DW_CFA_OFFSET_EXTENDED_SF,
537e16fca0SAli Bahrami MSG_DW_CFA_DEF_CFA_SF, MSG_DW_CFA_DEF_CFA_OFFSET_SF,
547e16fca0SAli Bahrami MSG_DW_CFA_VAL_OFFSET, MSG_DW_CFA_VAL_OFFSET_SF,
557e16fca0SAli Bahrami MSG_DW_CFA_VAL_EXPRESSION
567e16fca0SAli Bahrami };
57*4f680cc6SAli Bahrami static const Msg cfa_mips[] = { MSG_DW_CFA_MIPS_ADV_LOC8 };
58*4f680cc6SAli Bahrami static const Msg cfa_gnu[] = {
597e16fca0SAli Bahrami MSG_DW_CFA_GNU_WINDOW_SAVE, MSG_DW_CFA_GNU_ARGS_SIZE,
607e16fca0SAli Bahrami MSG_DW_CFA_GNU_NEGATIVE_OFF_X
617e16fca0SAli Bahrami };
62*4f680cc6SAli Bahrami static const conv_ds_msg_t ds_msg_cfa = {
63*4f680cc6SAli Bahrami CONV_DS_MSG_INIT(0, cfa) };
64*4f680cc6SAli Bahrami static const conv_ds_msg_t ds_msg_cfa_mips = {
65*4f680cc6SAli Bahrami CONV_DS_MSG_INIT(0x1d, cfa_mips) };
66*4f680cc6SAli Bahrami static const conv_ds_msg_t ds_msg_cfa_gnu = {
67*4f680cc6SAli Bahrami CONV_DS_MSG_INIT(0x2d, cfa_gnu) };
68*4f680cc6SAli Bahrami static const conv_ds_t *ds_cfa[] = { CONV_DS_ADDR(ds_msg_cfa),
69*4f680cc6SAli Bahrami CONV_DS_ADDR(ds_msg_cfa_mips), CONV_DS_ADDR(ds_msg_cfa_gnu), NULL };
70*4f680cc6SAli Bahrami
717e16fca0SAli Bahrami
727e16fca0SAli Bahrami /*
737e16fca0SAli Bahrami * DWARF CFA opcodes are bytes. The top 2 bits are a primary
747e16fca0SAli Bahrami * opcode, and if zero, the lower 6 bits specify a sub-opcode
757e16fca0SAli Bahrami */
767e16fca0SAli Bahrami switch (op >> 6) {
777e16fca0SAli Bahrami case 0x1:
787e16fca0SAli Bahrami return (MSG_ORIG(MSG_DW_CFA_ADVANCE_LOC));
797e16fca0SAli Bahrami case 0x2:
807e16fca0SAli Bahrami return (MSG_ORIG(MSG_DW_CFA_OFFSET));
817e16fca0SAli Bahrami case 0x3:
827e16fca0SAli Bahrami return (MSG_ORIG(MSG_DW_CFA_RESTORE));
837e16fca0SAli Bahrami }
847e16fca0SAli Bahrami
85*4f680cc6SAli Bahrami return (conv_map_ds(ELFOSABI_NONE, EM_NONE, op, ds_cfa,
86*4f680cc6SAli Bahrami fmt_flags, inv_buf));
877e16fca0SAli Bahrami }
887e16fca0SAli Bahrami
897e16fca0SAli Bahrami /*
907e16fca0SAli Bahrami * Translate DWARF register numbers to hardware specific names
917e16fca0SAli Bahrami *
927e16fca0SAli Bahrami * If good_name is non-NULL, conv_dwarf_regname() will set the variable to
937e16fca0SAli Bahrami * True(1) if the returned string is considered to be a good name to
947e16fca0SAli Bahrami * display, and False(0) otherwise. To be considered "good":
957e16fca0SAli Bahrami *
967e16fca0SAli Bahrami * - The name must be a well known mnemonic for a register
977e16fca0SAli Bahrami * from the machine type in question.
987e16fca0SAli Bahrami *
997e16fca0SAli Bahrami * - The name must be different than the DWARF name for
1007e16fca0SAli Bahrami * the same register.
1017e16fca0SAli Bahrami *
1027e16fca0SAli Bahrami * The returned string is usable, regardless of the value returned in
1037e16fca0SAli Bahrami * *good_name.
1047e16fca0SAli Bahrami */
1057e16fca0SAli Bahrami const char *
conv_dwarf_regname(Half mach,Word regno,Conv_fmt_flags_t fmt_flags,int * good_name,Conv_inv_buf_t * inv_buf)1067e16fca0SAli Bahrami conv_dwarf_regname(Half mach, Word regno, Conv_fmt_flags_t fmt_flags,
1077e16fca0SAli Bahrami int *good_name, Conv_inv_buf_t *inv_buf)
1087e16fca0SAli Bahrami {
1097e16fca0SAli Bahrami static const Msg reg_amd64[67] = {
1107e16fca0SAli Bahrami MSG_REG_RAX, MSG_REG_RDX,
1117e16fca0SAli Bahrami MSG_REG_RCX, MSG_REG_RBX,
1127e16fca0SAli Bahrami MSG_REG_RSI, MSG_REG_RDI,
1137e16fca0SAli Bahrami MSG_REG_RBP, MSG_REG_RSP,
1147e16fca0SAli Bahrami MSG_REG_R8, MSG_REG_R9,
1157e16fca0SAli Bahrami MSG_REG_R10, MSG_REG_R11,
1167e16fca0SAli Bahrami MSG_REG_R12, MSG_REG_R13,
1177e16fca0SAli Bahrami MSG_REG_R14, MSG_REG_R15,
1187e16fca0SAli Bahrami MSG_REG_RA, MSG_REG_PERXMM0,
1197e16fca0SAli Bahrami MSG_REG_PERXMM1, MSG_REG_PERXMM2,
1207e16fca0SAli Bahrami MSG_REG_PERXMM3, MSG_REG_PERXMM4,
1217e16fca0SAli Bahrami MSG_REG_PERXMM5, MSG_REG_PERXMM6,
1227e16fca0SAli Bahrami MSG_REG_PERXMM7, MSG_REG_PERXMM8,
1237e16fca0SAli Bahrami MSG_REG_PERXMM9, MSG_REG_PERXMM10,
1247e16fca0SAli Bahrami MSG_REG_PERXMM11, MSG_REG_PERXMM12,
1257e16fca0SAli Bahrami MSG_REG_PERXMM13, MSG_REG_PERXMM14,
1267e16fca0SAli Bahrami MSG_REG_PERXMM15, MSG_REG_PERST0,
1277e16fca0SAli Bahrami MSG_REG_PERST1, MSG_REG_PERST2,
1287e16fca0SAli Bahrami MSG_REG_PERST3, MSG_REG_PERST4,
1297e16fca0SAli Bahrami MSG_REG_PERST5, MSG_REG_PERST6,
1307e16fca0SAli Bahrami MSG_REG_PERST7, MSG_REG_PERMM0,
1317e16fca0SAli Bahrami MSG_REG_PERMM1, MSG_REG_PERMM2,
1327e16fca0SAli Bahrami MSG_REG_PERMM3, MSG_REG_PERMM4,
1337e16fca0SAli Bahrami MSG_REG_PERMM5, MSG_REG_PERMM6,
1347e16fca0SAli Bahrami MSG_REG_PERMM7, MSG_REG_PERRFLAGS,
1357e16fca0SAli Bahrami MSG_REG_PERES, MSG_REG_PERCS,
1367e16fca0SAli Bahrami MSG_REG_PERSS, MSG_REG_PERDS,
1377e16fca0SAli Bahrami MSG_REG_PERFS, MSG_REG_PERGS,
1387e16fca0SAli Bahrami MSG_REG_RESERVED, MSG_REG_RESERVED,
1397e16fca0SAli Bahrami MSG_REG_PERFSDOTBASE, MSG_REG_PERGSDOTBASE,
1407e16fca0SAli Bahrami MSG_REG_RESERVED, MSG_REG_RESERVED,
1417e16fca0SAli Bahrami MSG_REG_PERTR, MSG_REG_PERLDTR,
1427e16fca0SAli Bahrami MSG_REG_PERMXCSR, MSG_REG_PERFCW,
1437e16fca0SAli Bahrami MSG_REG_PERFSW
1447e16fca0SAli Bahrami };
145*4f680cc6SAli Bahrami static const conv_ds_msg_t ds_msg_reg_amd64 = {
146*4f680cc6SAli Bahrami CONV_DS_MSG_INIT(0, reg_amd64) };
147*4f680cc6SAli Bahrami static const conv_ds_t *ds_reg_amd64[] = {
148*4f680cc6SAli Bahrami CONV_DS_ADDR(ds_msg_reg_amd64), NULL };
1497e16fca0SAli Bahrami
1507e16fca0SAli Bahrami static const Msg reg_i386[8] = {
1517e16fca0SAli Bahrami MSG_REG_EAX, MSG_REG_ECX,
1527e16fca0SAli Bahrami MSG_REG_EDX, MSG_REG_EBX,
1537e16fca0SAli Bahrami MSG_REG_UESP, MSG_REG_EBP,
1547e16fca0SAli Bahrami MSG_REG_ESI, MSG_REG_EDI
1557e16fca0SAli Bahrami };
156*4f680cc6SAli Bahrami static const conv_ds_msg_t ds_msg_reg_i386 = {
157*4f680cc6SAli Bahrami CONV_DS_MSG_INIT(0, reg_i386) };
158*4f680cc6SAli Bahrami static const conv_ds_t *ds_reg_i386[] = {
159*4f680cc6SAli Bahrami CONV_DS_ADDR(ds_msg_reg_i386), NULL };
1607e16fca0SAli Bahrami
1617e16fca0SAli Bahrami static const Msg reg_sparc[64] = {
1627e16fca0SAli Bahrami MSG_REG_G0, MSG_REG_G1,
1637e16fca0SAli Bahrami MSG_REG_G2, MSG_REG_G3,
1647e16fca0SAli Bahrami MSG_REG_G4, MSG_REG_G5,
1657e16fca0SAli Bahrami MSG_REG_G6, MSG_REG_G7,
1667e16fca0SAli Bahrami MSG_REG_O0, MSG_REG_O1,
1677e16fca0SAli Bahrami MSG_REG_O2, MSG_REG_O3,
1687e16fca0SAli Bahrami MSG_REG_O4, MSG_REG_O5,
1697e16fca0SAli Bahrami MSG_REG_O6, MSG_REG_O7,
1707e16fca0SAli Bahrami MSG_REG_L0, MSG_REG_L1,
1717e16fca0SAli Bahrami MSG_REG_L2, MSG_REG_L3,
1727e16fca0SAli Bahrami MSG_REG_L4, MSG_REG_L5,
1737e16fca0SAli Bahrami MSG_REG_L6, MSG_REG_L7,
1747e16fca0SAli Bahrami MSG_REG_I0, MSG_REG_I1,
1757e16fca0SAli Bahrami MSG_REG_I2, MSG_REG_I3,
1767e16fca0SAli Bahrami MSG_REG_I4, MSG_REG_I5,
1777e16fca0SAli Bahrami MSG_REG_I6, MSG_REG_I7,
1787e16fca0SAli Bahrami MSG_REG_F0, MSG_REG_F1,
1797e16fca0SAli Bahrami MSG_REG_F2, MSG_REG_F3,
1807e16fca0SAli Bahrami MSG_REG_F4, MSG_REG_F5,
1817e16fca0SAli Bahrami MSG_REG_F6, MSG_REG_F7,
1827e16fca0SAli Bahrami MSG_REG_F8, MSG_REG_F9,
1837e16fca0SAli Bahrami MSG_REG_F10, MSG_REG_F11,
1847e16fca0SAli Bahrami MSG_REG_F12, MSG_REG_F13,
1857e16fca0SAli Bahrami MSG_REG_F14, MSG_REG_F15,
1867e16fca0SAli Bahrami MSG_REG_F16, MSG_REG_F17,
1877e16fca0SAli Bahrami MSG_REG_F18, MSG_REG_F19,
1887e16fca0SAli Bahrami MSG_REG_F20, MSG_REG_F21,
1897e16fca0SAli Bahrami MSG_REG_F22, MSG_REG_F23,
1907e16fca0SAli Bahrami MSG_REG_F24, MSG_REG_F25,
1917e16fca0SAli Bahrami MSG_REG_F26, MSG_REG_F27,
1927e16fca0SAli Bahrami MSG_REG_F28, MSG_REG_F29,
1937e16fca0SAli Bahrami MSG_REG_F30, MSG_REG_F31
1947e16fca0SAli Bahrami };
195*4f680cc6SAli Bahrami static const conv_ds_msg_t ds_msg_reg_sparc = {
196*4f680cc6SAli Bahrami CONV_DS_MSG_INIT(0, reg_sparc) };
197*4f680cc6SAli Bahrami static const conv_ds_t *ds_reg_sparc[] = {
198*4f680cc6SAli Bahrami CONV_DS_ADDR(ds_msg_reg_sparc), NULL };
1997e16fca0SAli Bahrami
2007e16fca0SAli Bahrami switch (mach) {
2017e16fca0SAli Bahrami case EM_AMD64:
2027e16fca0SAli Bahrami /*
2037e16fca0SAli Bahrami * amd64 has several in-bounds names we'd rather not
2047e16fca0SAli Bahrami * use. R8-R15 have the same name as their DWARF counterparts.
2057e16fca0SAli Bahrami * 56-57, and 60-61 are reserved, and don't have a good name.
2067e16fca0SAli Bahrami */
2077e16fca0SAli Bahrami if (good_name)
2087e16fca0SAli Bahrami *good_name = ((regno < 8) || (regno > 15)) &&
2097e16fca0SAli Bahrami (regno != 56) && (regno != 57) &&
2107e16fca0SAli Bahrami (regno != 60) && (regno != 61) &&
2117e16fca0SAli Bahrami (regno < ARRAY_NELTS(reg_amd64));
212*4f680cc6SAli Bahrami return (conv_map_ds(ELFOSABI_NONE, EM_NONE, regno,
213*4f680cc6SAli Bahrami ds_reg_amd64, fmt_flags, inv_buf));
2147e16fca0SAli Bahrami
2157e16fca0SAli Bahrami case EM_386:
2167e16fca0SAli Bahrami case EM_486:
2177e16fca0SAli Bahrami if (good_name)
2187e16fca0SAli Bahrami *good_name = (regno < ARRAY_NELTS(reg_i386));
219*4f680cc6SAli Bahrami return (conv_map_ds(ELFOSABI_NONE, EM_NONE, regno,
220*4f680cc6SAli Bahrami ds_reg_i386, fmt_flags, inv_buf));
2217e16fca0SAli Bahrami
2227e16fca0SAli Bahrami case EM_SPARC:
2237e16fca0SAli Bahrami case EM_SPARC32PLUS:
2247e16fca0SAli Bahrami case EM_SPARCV9:
2257e16fca0SAli Bahrami if (good_name)
2267e16fca0SAli Bahrami *good_name = (regno < ARRAY_NELTS(reg_sparc));
227*4f680cc6SAli Bahrami return (conv_map_ds(ELFOSABI_NONE, EM_NONE, regno,
228*4f680cc6SAli Bahrami ds_reg_sparc, fmt_flags, inv_buf));
2297e16fca0SAli Bahrami }
2307e16fca0SAli Bahrami
2317e16fca0SAli Bahrami if (good_name)
2327e16fca0SAli Bahrami *good_name = 0;
2337e16fca0SAli Bahrami return (conv_invalid_val(inv_buf, regno, 0));
2347e16fca0SAli Bahrami }
235