-- | Constants describing the DWARF format. Most of this simply -- mirrors /usr/include/dwarf.h. module Dwarf.Constants where import FastString import Platform import Outputable import Reg import X86.Regs import Data.Word -- | Language ID used for Haskell. dW_LANG_Haskell :: Word dW_LANG_Haskell = 0x18 -- Thanks to Nathan Howell for getting us our very own language ID! -- | Dwarf tags dW_TAG_compile_unit, dW_TAG_subroutine_type, dW_TAG_file_type, dW_TAG_subprogram, dW_TAG_lexical_block, dW_TAG_base_type, dW_TAG_structure_type, dW_TAG_pointer_type, dW_TAG_array_type, dW_TAG_subrange_type, dW_TAG_typedef, dW_TAG_variable, dW_TAG_arg_variable, dW_TAG_auto_variable :: Word dW_TAG_array_type = 1 dW_TAG_lexical_block = 11 dW_TAG_pointer_type = 15 dW_TAG_compile_unit = 17 dW_TAG_structure_type = 19 dW_TAG_typedef = 22 dW_TAG_subroutine_type = 32 dW_TAG_subrange_type = 33 dW_TAG_base_type = 36 dW_TAG_file_type = 41 dW_TAG_subprogram = 46 dW_TAG_variable = 52 dW_TAG_auto_variable = 256 dW_TAG_arg_variable = 257 -- | Dwarf attributes dW_AT_name, dW_AT_stmt_list, dW_AT_low_pc, dW_AT_high_pc, dW_AT_language, dW_AT_comp_dir, dW_AT_producer, dW_AT_external, dW_AT_frame_base, dW_AT_use_UTF8, dW_AT_MIPS_linkage_name :: Word dW_AT_name = 0x03 dW_AT_stmt_list = 0x10 dW_AT_low_pc = 0x11 dW_AT_high_pc = 0x12 dW_AT_language = 0x13 dW_AT_comp_dir = 0x1b dW_AT_producer = 0x25 dW_AT_external = 0x3f dW_AT_frame_base = 0x40 dW_AT_use_UTF8 = 0x53 dW_AT_MIPS_linkage_name = 0x2007 -- | Abbrev declaration dW_CHILDREN_no, dW_CHILDREN_yes :: Word8 dW_CHILDREN_no = 0 dW_CHILDREN_yes = 1 dW_FORM_addr, dW_FORM_data4, dW_FORM_string, dW_FORM_flag, dW_FORM_block1, dW_FORM_ref4 :: Word dW_FORM_addr = 0x01 dW_FORM_data4 = 0x06 dW_FORM_string = 0x08 dW_FORM_flag = 0x0c dW_FORM_block1 = 0x0a dW_FORM_ref4 = 0x13 -- | Dwarf native types dW_ATE_address, dW_ATE_boolean, dW_ATE_float, dW_ATE_signed, dW_ATE_signed_char, dW_ATE_unsigned, dW_ATE_unsigned_char :: Word dW_ATE_address = 1 dW_ATE_boolean = 2 dW_ATE_float = 4 dW_ATE_signed = 5 dW_ATE_signed_char = 6 dW_ATE_unsigned = 7 dW_ATE_unsigned_char = 8 -- | Call frame information dW_CFA_set_loc, dW_CFA_undefined, dW_CFA_same_value, dW_CFA_def_cfa, dW_CFA_def_cfa_offset, dW_CFA_def_cfa_expression, dW_CFA_expression, dW_CFA_offset_extended_sf, dW_CFA_def_cfa_offset_sf, dW_CFA_def_cfa_sf, dW_CFA_val_offset, dW_CFA_val_expression, dW_CFA_offset :: Word8 dW_CFA_set_loc = 0x01 dW_CFA_undefined = 0x07 dW_CFA_same_value = 0x08 dW_CFA_def_cfa = 0x0c dW_CFA_def_cfa_offset = 0x0e dW_CFA_def_cfa_expression = 0x0f dW_CFA_expression = 0x10 dW_CFA_offset_extended_sf = 0x11 dW_CFA_def_cfa_sf = 0x12 dW_CFA_def_cfa_offset_sf = 0x13 dW_CFA_val_offset = 0x14 dW_CFA_val_expression = 0x16 dW_CFA_offset = 0x80 -- | Operations dW_OP_deref, dW_OP_consts, dW_OP_minus, dW_OP_mul, dW_OP_plus, dW_OP_lit0, dW_OP_breg0, dW_OP_call_frame_cfa :: Word8 dW_OP_deref = 0x06 dW_OP_consts = 0x11 dW_OP_minus = 0x1c dW_OP_mul = 0x1e dW_OP_plus = 0x22 dW_OP_lit0 = 0x30 dW_OP_breg0 = 0x70 dW_OP_call_frame_cfa = 0x9c -- | Dwarf section declarations dwarfInfoSection, dwarfAbbrevSection, dwarfLineSection, dwarfFrameSection, dwarfGhcSection :: SDoc dwarfInfoSection = dwarfSection "info" dwarfAbbrevSection = dwarfSection "abbrev" dwarfLineSection = dwarfSection "line" dwarfFrameSection = dwarfSection "frame" dwarfGhcSection = dwarfSection "ghc" dwarfSection :: String -> SDoc dwarfSection name = sdocWithPlatform $ \plat -> case platformOS plat of OSDarwin -> ftext $ mkFastString $ ".section __DWARF,__debug_" ++ name ++ ",regular,debug" _other -> ftext $ mkFastString $ ".section .debug_" ++ name ++ ",\"\",@progbits" -- | Dwarf section labels dwarfInfoLabel, dwarfAbbrevLabel, dwarfLineLabel, dwarfFrameLabel :: LitString dwarfInfoLabel = sLit ".Lsection_info" dwarfAbbrevLabel = sLit ".Lsection_abbrev" dwarfLineLabel = sLit ".Lsection_line" dwarfFrameLabel = sLit ".Lsection_frame" -- | Mapping of registers to DWARF register numbers dwarfRegNo :: Platform -> Reg -> Word8 dwarfRegNo p r = case platformArch p of ArchX86 | r == eax -> 0 | r == ecx -> 1 -- yes, no typo | r == edx -> 2 | r == ebx -> 3 | r == esp -> 4 | r == ebp -> 5 | r == esi -> 6 | r == edi -> 7 ArchX86_64 | r == rax -> 0 | r == rdx -> 1 -- this neither. The order GCC allocates registers in? | r == rcx -> 2 | r == rbx -> 3 | r == rsi -> 4 | r == rdi -> 5 | r == rbp -> 6 | r == rsp -> 7 | r == r8 -> 8 | r == r9 -> 9 | r == r10 -> 10 | r == r11 -> 11 | r == r12 -> 12 | r == r13 -> 13 | r == r14 -> 14 | r == r15 -> 15 | r == xmm0 -> 17 | r == xmm1 -> 18 | r == xmm2 -> 19 | r == xmm3 -> 20 | r == xmm4 -> 21 | r == xmm5 -> 22 | r == xmm6 -> 23 | r == xmm7 -> 24 | r == xmm8 -> 25 | r == xmm9 -> 26 | r == xmm10 -> 27 | r == xmm11 -> 28 | r == xmm12 -> 29 | r == xmm13 -> 30 | r == xmm14 -> 31 | r == xmm15 -> 32 _other -> error "dwarfRegNo: Unsupported platform or unknown register!" -- | Virtual register number to use for return address. dwarfReturnRegNo :: Platform -> Word8 dwarfReturnRegNo p -- We "overwrite" IP with our pseudo register - that makes sense, as -- when using this mechanism gdb already knows the IP anyway. Clang -- does this too, so it must be safe. = case platformArch p of ArchX86 -> 8 -- eip ArchX86_64 -> 16 -- rip _other -> error "dwarfReturnRegNo: Unsupported platform!"