X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Funwind.c;h=6d60f79e7701cc5b697f276356f68f68c0fde65c;hb=b472a0391ca66b87e86e8406e0702dc2b1e66deb;hp=ef3c65a7f225790813dfa5ab71f9a5e11b8c8ed4;hpb=f41e857d3fef58b944e1523f0ee9a97b4f142468;p=mono.git diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c index ef3c65a7f22..6d60f79e770 100644 --- a/mono/mini/unwind.c +++ b/mono/mini/unwind.c @@ -46,19 +46,19 @@ static int unwind_info_size; #ifdef TARGET_AMD64 static int map_hw_reg_to_dwarf_reg [] = { 0, 2, 1, 3, 7, 6, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; -#define NUM_REGS AMD64_NREG +#define NUM_DWARF_REGS AMD64_NREG #define DWARF_DATA_ALIGN (-8) #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (AMD64_RIP)) #elif defined(TARGET_ARM) // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf /* Assign d8..d15 to hregs 16..24 (dwarf regs 264..271) */ static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 264, 265, 266, 267, 268, 269, 270, 271 }; -#define NUM_REGS 272 +#define NUM_DWARF_REGS 272 #define DWARF_DATA_ALIGN (-4) #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR)) #define IS_DOUBLE_REG(dwarf_reg) (((dwarf_reg) >= 264) && ((dwarf_reg) <= 271)) #elif defined(TARGET_ARM64) -#define NUM_REGS 96 +#define NUM_DWARF_REGS 96 #define DWARF_DATA_ALIGN (-8) /* LR */ #define DWARF_PC_REG 30 @@ -75,21 +75,25 @@ static int map_hw_reg_to_dwarf_reg [] = { */ static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 5, 4, 6, 7, 8 }; /* + 1 is for IP */ -#define NUM_REGS X86_NREG + 1 +#define NUM_DWARF_REGS (X86_NREG + 1) #define DWARF_DATA_ALIGN (-4) #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (X86_NREG)) #elif defined (TARGET_POWERPC) // http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html -static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, +static int map_hw_reg_to_dwarf_reg [ppc_lr + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; -#define NUM_REGS 110 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t)) +#if _CALL_ELF == 2 +#define DWARF_PC_REG 65 +#else #define DWARF_PC_REG 108 +#endif +#define NUM_DWARF_REGS (DWARF_PC_REG + 1) #elif defined (TARGET_S390X) static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; -#define NUM_REGS 16 +#define NUM_DWARF_REGS 16 #define DWARF_DATA_ALIGN (-8) #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (14)) #elif defined (TARGET_MIPS) @@ -100,23 +104,36 @@ static int map_hw_reg_to_dwarf_reg [32] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; -#define NUM_REGS 32 +#define NUM_DWARF_REGS 32 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t)) #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (mips_ra)) #else static int map_hw_reg_to_dwarf_reg [16]; -#define NUM_REGS 16 +#define NUM_DWARF_REGS 16 #define DWARF_DATA_ALIGN 0 #define DWARF_PC_REG -1 #endif +#define NUM_HW_REGS (sizeof (map_hw_reg_to_dwarf_reg) / sizeof (int)) + #ifndef IS_DOUBLE_REG -#define IS_DOUBLE_REG(dwarf_reg) 0 +#define IS_DOUBLE_REG(dwarf_reg) (dwarf_reg ? 0 : 0) #endif static gboolean dwarf_reg_to_hw_reg_inited; +static gboolean hw_reg_to_dwarf_reg_inited; -static int map_dwarf_reg_to_hw_reg [NUM_REGS]; +static int map_dwarf_reg_to_hw_reg [NUM_DWARF_REGS]; + +static void +init_hw_reg_map (void) +{ +#ifdef TARGET_POWERPC + map_hw_reg_to_dwarf_reg [ppc_lr] = DWARF_PC_REG; +#endif + mono_memory_barrier (); + hw_reg_to_dwarf_reg_inited = TRUE; +} /* * mono_hw_reg_to_dwarf_reg: @@ -126,14 +143,10 @@ static int map_dwarf_reg_to_hw_reg [NUM_REGS]; int mono_hw_reg_to_dwarf_reg (int reg) { -#ifdef TARGET_POWERPC - if (reg == ppc_lr) - return 108; - else - g_assert (reg < NUM_REGS); -#endif + if (!hw_reg_to_dwarf_reg_inited) + init_hw_reg_map (); - if (NUM_REGS == 0) { + if (NUM_HW_REGS == 0) { g_assert_not_reached (); return -1; } else { @@ -142,19 +155,15 @@ mono_hw_reg_to_dwarf_reg (int reg) } static void -init_reg_map (void) +init_dwarf_reg_map (void) { int i; - g_assert (NUM_REGS > 0); - for (i = 0; i < sizeof (map_hw_reg_to_dwarf_reg) / sizeof (int); ++i) { + g_assert (NUM_HW_REGS > 0); + for (i = 0; i < NUM_HW_REGS; ++i) { map_dwarf_reg_to_hw_reg [mono_hw_reg_to_dwarf_reg (i)] = i; } -#ifdef TARGET_POWERPC - map_dwarf_reg_to_hw_reg [DWARF_PC_REG] = ppc_lr; -#endif - mono_memory_barrier (); dwarf_reg_to_hw_reg_inited = TRUE; } @@ -163,7 +172,7 @@ int mono_dwarf_reg_to_hw_reg (int reg) { if (!dwarf_reg_to_hw_reg_inited) - init_reg_map (); + init_dwarf_reg_map (); return map_dwarf_reg_to_hw_reg [reg]; } @@ -375,13 +384,15 @@ mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enab while (op->when > loc) { if (op->when - loc > 65536) { *p ++ = DW_CFA_advance_loc4; - *(guint32*)p = (guint32)(op->when - loc); + guint32 v = (guint32)(op->when - loc); + memcpy (p, &v, 4); g_assert (read32 (p) == (guint32)(op->when - loc)); p += 4; loc = op->when; } else if (op->when - loc > 256) { *p ++ = DW_CFA_advance_loc2; - *(guint16*)p = (guint16)(op->when - loc); + guint16 v = (guint16)(op->when - loc); + memcpy (p, &v, 2); g_assert (read16 (p) == (guint32)(op->when - loc)); p += 2; loc = op->when; @@ -477,8 +488,8 @@ print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *location } typedef struct { - Loc locations [NUM_REGS]; - guint8 reg_saved [NUM_REGS]; + Loc locations [NUM_HW_REGS]; + guint8 reg_saved [NUM_HW_REGS]; int cfa_reg, cfa_offset; } UnwindState; @@ -499,9 +510,9 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, mgreg_t **save_locations, int save_locations_len, guint8 **out_cfa) { - Loc locations [NUM_REGS]; - guint8 reg_saved [NUM_REGS]; - int i, pos, reg, cfa_reg = -1, cfa_offset = 0, offset; + Loc locations [NUM_HW_REGS]; + guint8 reg_saved [NUM_HW_REGS]; + int pos, reg, hwreg, cfa_reg = -1, cfa_offset = 0, offset; guint8 *p; guint8 *cfa_val; UnwindState state_stack [1]; @@ -526,11 +537,11 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, p ++; break; case DW_CFA_offset: - reg = *p & 0x3f; + hwreg = mono_dwarf_reg_to_hw_reg (*p & 0x3f); p ++; - reg_saved [reg] = TRUE; - locations [reg].loc_type = LOC_OFFSET; - locations [reg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN; + reg_saved [hwreg] = TRUE; + locations [hwreg].loc_type = LOC_OFFSET; + locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN; break; case 0: { int ext_op = *p; @@ -548,23 +559,25 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, break; case DW_CFA_offset_extended_sf: reg = decode_uleb128 (p, &p); + hwreg = mono_dwarf_reg_to_hw_reg (reg); offset = decode_sleb128 (p, &p); - g_assert (reg < NUM_REGS); - reg_saved [reg] = TRUE; - locations [reg].loc_type = LOC_OFFSET; - locations [reg].offset = offset * DWARF_DATA_ALIGN; + g_assert (reg < NUM_DWARF_REGS); + reg_saved [hwreg] = TRUE; + locations [hwreg].loc_type = LOC_OFFSET; + locations [hwreg].offset = offset * DWARF_DATA_ALIGN; break; case DW_CFA_offset_extended: reg = decode_uleb128 (p, &p); + hwreg = mono_dwarf_reg_to_hw_reg (reg); offset = decode_uleb128 (p, &p); - g_assert (reg < NUM_REGS); - reg_saved [reg] = TRUE; - locations [reg].loc_type = LOC_OFFSET; - locations [reg].offset = offset * DWARF_DATA_ALIGN; + g_assert (reg < NUM_DWARF_REGS); + reg_saved [hwreg] = TRUE; + locations [hwreg].loc_type = LOC_OFFSET; + locations [hwreg].offset = offset * DWARF_DATA_ALIGN; break; case DW_CFA_same_value: - reg = decode_uleb128 (p, &p); - locations [reg].loc_type = LOC_SAME; + hwreg = mono_dwarf_reg_to_hw_reg (decode_uleb128 (p, &p)); + locations [hwreg].loc_type = LOC_SAME; break; case DW_CFA_advance_loc1: pos += *p; @@ -613,16 +626,16 @@ mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, g_assert (cfa_reg != -1); cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset; - for (i = 0; i < NUM_REGS; ++i) { - if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET) { - int hreg = mono_dwarf_reg_to_hw_reg (i); - g_assert (hreg < nregs); - if (IS_DOUBLE_REG (i)) - regs [hreg] = *(guint64*)(cfa_val + locations [i].offset); + for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) { + if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) { + int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg); + g_assert (hwreg < nregs); + if (IS_DOUBLE_REG (dwarfreg)) + regs [hwreg] = *(guint64*)(cfa_val + locations [hwreg].offset); else - regs [hreg] = *(mgreg_t*)(cfa_val + locations [i].offset); - if (save_locations && hreg < save_locations_len) - save_locations [hreg] = (mgreg_t*)(cfa_val + locations [i].offset); + regs [hwreg] = *(mgreg_t*)(cfa_val + locations [hwreg].offset); + if (save_locations && hwreg < save_locations_len) + save_locations [hwreg] = (mgreg_t*)(cfa_val + locations [hwreg].offset); } }