diff --git a/eh_frame.c b/eh_frame.c index 4532f64..dcb02aa 100644 --- a/eh_frame.c +++ b/eh_frame.c @@ -1,85 +1,3 @@ -enum dwarf_cfa_op_base { - DW_CFA_advance_loc = 0x1, - DW_CFA_offset = 0x2, - DW_CFA_restore = 0x3 -}; - -enum dwarf_cfa_op { - DW_CFA_nop = 0x00, - DW_CFA_set_loc = 0x01, - DW_CFA_advance_loc1 = 0x02, - DW_CFA_advance_loc2 = 0x03, - DW_CFA_advance_loc4 = 0x04, - DW_CFA_offset_extended = 0x05, - DW_CFA_restore_extended = 0x06, - DW_CFA_undefined = 0x07, - DW_CFA_same_value = 0x08, - DW_CFA_register = 0x09, - DW_CFA_remember_state = 0x0a, - DW_CFA_restore_state = 0x0b, - DW_CFA_def_cfa = 0x0c, - DW_CFA_def_cfa_register = 0x0d, - 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_offset_sf = 0x15, - DW_CFA_val_expression = 0x16, - DW_CFA_lo_user = 0x1c, - DW_CFA_hi_user = 0x3f, -}; - -enum dwarf_cie_pointer_format { - DW_EH_PE_absptr = 0x00, - DW_EH_PE_uleb128 = 0x01, - DW_EH_PE_udata2 = 0x02, - DW_EH_PE_udata4 = 0x03, - DW_EH_PE_udata8 = 0x04, - DW_EH_PE_sleb128 = 0x09, - DW_EH_PE_sdata2 = 0x0A, - DW_EH_PE_sdata4 = 0x0B, - DW_EH_PE_sdata8 = 0x0C, -}; - -enum dwarf_cie_pointer_application { - DW_EH_PE_pcrel = 0x10, - DW_EH_PE_textrel = 0x20, - DW_EH_PE_datarel = 0x30, - DW_EH_PE_funcrel = 0x40, - DW_EH_PE_aligned = 0x50, - DW_EH_PE_indirect = 0x80, - DW_EH_PE_omit = 0xFF, -}; - -struct dwarf_cie_header { - u32 length; - u8 version; - u32 code_alignment; - s32 data_alignment; - u32 return_address_register; - u32 augmentation_data_length; - u8 *augmentation_data; - - int has_z; - - enum dwarf_cie_pointer_format pointer_format; - enum dwarf_cie_pointer_application pointer_application; - u8 pointer_indirect; -}; - -struct dwarf_fde_header { - u32 length; - u64 optional_length; - struct dwarf_cie_header *cie; - u64 low_pc; - u64 high_pc; - u32 augmentation_data_length; - u8 *augmentation_data; -}; - static u64 iterate_call_frame_instructions(u8 *data, u64 to_read) { @@ -343,7 +261,7 @@ read_one_cie(struct dwarf_cie_header *header, u64 length, u8 *data, u8 *original } static u64 -read_encoded_pointer(struct mi_process proc, struct dwarf_cie_header *cie, u8 *data, u64 *dest, u8 *section_base) +read_encoded_pointer(struct mi_process proc, struct dwarf_cie_header *cie, u8 *data, u64 *dest) { u64 offset = 0; s64 final_value; @@ -466,14 +384,14 @@ read_encoded_pointer(struct mi_process proc, struct dwarf_cie_header *cie, u8 *d } static u64 -read_one_fde(struct mi_process proc, struct dwarf_cie_header *cie, u64 length, u32 cie_offset, u8 *data, u8 *original_data, u8 *section_base) +read_one_fde(struct mi_process proc, struct dwarf_cie_header *cie, u64 length, u32 cie_offset, u8 *data, u8 *original_data) { struct dwarf_fde_header header = { 0 }; header.length = length; header.cie = (struct dwarf_cie_header *) (data - 4 - cie_offset); - u32 pointer_size = read_encoded_pointer(proc, cie, data, &header.low_pc, section_base); + u32 pointer_size = read_encoded_pointer(proc, cie, data, &header.low_pc); data += pointer_size; u64 fde_length = 0; @@ -503,7 +421,7 @@ read_one_fde(struct mi_process proc, struct dwarf_cie_header *cie, u64 length, u } static u64 -read_one_call_frame_record(struct mi_process proc, struct dwarf_cie_header *last_cie, u8 *section_base, u8 *data) +read_one_call_frame_record(struct mi_process proc, struct dwarf_cie_header *last_cie, u8 *data) { u8 *original_data = data; u64 length; @@ -532,7 +450,7 @@ read_one_call_frame_record(struct mi_process proc, struct dwarf_cie_header *last if (cie_id == 0) { result = read_one_cie(last_cie, length, data, original_data); } else { - result = read_one_fde(proc, last_cie, length, cie_id, data, original_data, section_base); + result = read_one_fde(proc, last_cie, length, cie_id, data, original_data); } return(result); @@ -547,7 +465,7 @@ parse_eh_frame(struct mi_process proc) u64 read = 0; for (;;) { - u64 size = read_one_call_frame_record(proc, &last_cie, proc.elf + eh_frame.offset_in_file, proc.elf + eh_frame.offset_in_file + read); + u64 size = read_one_call_frame_record(proc, &last_cie, proc.elf + eh_frame.offset_in_file + read); read += size; if (read >= eh_frame.size) { break; diff --git a/elf_dwarf.h b/elf_dwarf.h index 76eae8e..a9a411e 100644 --- a/elf_dwarf.h +++ b/elf_dwarf.h @@ -478,6 +478,62 @@ enum dwarf_expression_op { DW_OP_hi_user = 0xff }; +enum dwarf_cfa_op_base { + DW_CFA_advance_loc = 0x1, + DW_CFA_offset = 0x2, + DW_CFA_restore = 0x3 +}; + +enum dwarf_cfa_op { + DW_CFA_nop = 0x00, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + 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_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_lo_user = 0x1c, + DW_CFA_hi_user = 0x3f, +}; + +enum dwarf_cie_pointer_format { + DW_EH_PE_absptr = 0x00, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, +}; + +enum dwarf_cie_pointer_application { + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80, + DW_EH_PE_omit = 0xFF, +}; + #pragma pack(1) struct elf_header_x64 { char magic[4]; @@ -585,166 +641,28 @@ struct dwarf_line_number_state { u32 discriminator; }; - -static char * -attribute_to_str(enum dwarf_die_tag attr) -{ - switch (attr) { - case DW_AT_sibling: { return "DW_AT_sibling"; } - case DW_AT_location: { return "DW_AT_location"; } - case DW_AT_name: { return "DW_AT_name"; } - case DW_AT_ordering: { return "DW_AT_ordering"; } - case DW_AT_subscr_data: { return "DW_AT_subscr_data"; } - case DW_AT_byte_size: { return "DW_AT_byte_size"; } - case DW_AT_bit_offset: { return "DW_AT_bit_offset"; } - case DW_AT_bit_size: { return "DW_AT_bit_size"; } - case DW_AT_element_list: { return "DW_AT_element_list"; } - case DW_AT_stmt_list: { return "DW_AT_stmt_list"; } - case DW_AT_low_pc: { return "DW_AT_low_pc"; } - case DW_AT_high_pc: { return "DW_AT_high_pc"; } - case DW_AT_language: { return "DW_AT_language"; } - case DW_AT_member: { return "DW_AT_member"; } - case DW_AT_discr: { return "DW_AT_discr"; } - case DW_AT_discr_value: { return "DW_AT_discr_value"; } - case DW_AT_visibility: { return "DW_AT_visibility"; } - case DW_AT_import: { return "DW_AT_import"; } - case DW_AT_string_length: { return "DW_AT_string_length"; } - case DW_AT_common_reference: { return "DW_AT_common_reference"; } - case DW_AT_comp_dir: { return "DW_AT_comp_dir"; } - case DW_AT_const_value: { return "DW_AT_const_value"; } - case DW_AT_containing_type: { return "DW_AT_containing_type"; } - case DW_AT_default_value: { return "DW_AT_default_value"; } - case DW_AT_inline: { return "DW_AT_inline"; } - case DW_AT_is_optional: { return "DW_AT_is_optional"; } - case DW_AT_lower_bound: { return "DW_AT_lower_bound"; } - case DW_AT_producer: { return "DW_AT_producer"; } - case DW_AT_prototyped: { return "DW_AT_prototyped"; } - case DW_AT_return_addr: { return "DW_AT_return_addr"; } - case DW_AT_start_scope: { return "DW_AT_start_scope"; } - case DW_AT_upper_bound: { return "DW_AT_upper_bound"; } - case DW_AT_abstract_origin: { return "DW_AT_abstract_origin"; } - case DW_AT_accessibility: { return "DW_AT_accessibility"; } - case DW_AT_address_class: { return "DW_AT_address_class"; } - case DW_AT_artificial: { return "DW_AT_artificial"; } - case DW_AT_base_types: { return "DW_AT_base_types"; } - case DW_AT_calling_convention: { return "DW_AT_calling_convention"; } - case DW_AT_count: { return "DW_AT_count"; } - case DW_AT_data_member_location: { return "DW_AT_data_member_location"; } - case DW_AT_decl_column: { return "DW_AT_decl_column"; } - case DW_AT_decl_file: { return "DW_AT_decl_file"; } - case DW_AT_decl_line: { return "DW_AT_decl_line"; } - case DW_AT_declaration: { return "DW_AT_declaration"; } - case DW_AT_encoding: { return "DW_AT_encoding"; } - case DW_AT_external: { return "DW_AT_external"; } - case DW_AT_frame_base: { return "DW_AT_frame_base"; } - case DW_AT_friend: { return "DW_AT_friend"; } - case DW_AT_identifier_case: { return "DW_AT_identifier_case"; } - case DW_AT_macro_info: { return "DW_AT_macro_info"; } - case DW_AT_namelist_item: { return "DW_AT_namelist_item"; } - case DW_AT_priority: { return "DW_AT_priority"; } - case DW_AT_segment: { return "DW_AT_segment"; } - case DW_AT_specification: { return "DW_AT_specification"; } - case DW_AT_static_link: { return "DW_AT_static_link"; } - case DW_AT_type: { return "DW_AT_type"; } - case DW_AT_use_location: { return "DW_AT_use_location"; } - case DW_AT_variable_parameter: { return "DW_AT_variable_parameter"; } - case DW_AT_virtuality: { return "DW_AT_virtuality"; } - case DW_AT_vtable_elem_location: { return "DW_AT_vtable_elem_location"; } - case DW_AT_signature: { return "DW_AT_signature"; } - case DW_AT_main_subprogram: { return "DW_AT_main_subprogram"; } - case DW_AT_data_bit_offset: { return "DW_AT_data_bit_offset"; } - case DW_AT_const_expr: { return "DW_AT_const_expr"; } - case DW_AT_enum_class: { return "DW_AT_enum_class"; } - case DW_AT_linkage_name: { return "DW_AT_linkage_name"; } - case DW_AT_string_length_bit_size: { return "DW_AT_string_length_bit_size"; } - case DW_AT_string_length_byte_size: { return "DW_AT_string_length_byte_size"; } - case DW_AT_rank: { return "DW_AT_rank"; } - case DW_AT_str_offsets_base: { return "DW_AT_str_offsets_base"; } - case DW_AT_addr_base: { return "DW_AT_addr_base"; } - case DW_AT_rnglists_base: { return "DW_AT_rnglists_base"; } - case DW_AT_dwo_id: { return "DW_AT_dwo_id"; } - case DW_AT_dwo_name: { return "DW_AT_dwo_name"; } - case DW_AT_reference: { return "DW_AT_reference"; } - case DW_AT_rvalue_reference: { return "DW_AT_rvalue_reference"; } - case DW_AT_macros: { return "DW_AT_macros"; } - case DW_AT_call_all_calls: { return "DW_AT_call_all_calls"; } - case DW_AT_call_all_source_calls: { return "DW_AT_call_all_source_calls"; } - case DW_AT_call_all_tail_calls: { return "DW_AT_call_all_tail_calls"; } - case DW_AT_call_return_pc: { return "DW_AT_call_return_pc"; } - case DW_AT_call_value: { return "DW_AT_call_value"; } - case DW_AT_call_origin: { return "DW_AT_call_origin"; } - case DW_AT_call_parameter: { return "DW_AT_call_parameter"; } - case DW_AT_call_pc: { return "DW_AT_call_pc"; } - case DW_AT_call_tail_call: { return "DW_AT_call_tail_call"; } - case DW_AT_call_target: { return "DW_AT_call_target"; } - case DW_AT_call_target_clobbered: { return "DW_AT_call_target_clobbered"; } - case DW_AT_call_data_location: { return "DW_AT_call_data_location"; } - case DW_AT_call_data_value: { return "DW_AT_call_data_value"; } - case DW_AT_noreturn: { return "DW_AT_noreturn"; } - case DW_AT_alignment: { return "DW_AT_alignment"; } - case DW_AT_export_symbols: { return "DW_AT_export_symbols"; } - case DW_AT_deleted: { return "DW_AT_deleted"; } - case DW_AT_defaulted: { return "DW_AT_defaulted"; } - case DW_AT_loclists_base: { return "DW_AT_loclists_base"; } - } - - return(NULL); -} - -static char * -tag_to_str(enum dwarf_die_tag tag) { - switch (tag) { - case DW_TAG_array_type: { return "DW_TAG_array_type"; } - case DW_TAG_class_type: { return "DW_TAG_class_type"; } - case DW_TAG_entry_point: { return "DW_TAG_entry_point"; } - case DW_TAG_enumeration_type: { return "DW_TAG_enumeration_type"; } - case DW_TAG_formal_parameter: { return "DW_TAG_formal_parameter"; } - case DW_TAG_imported_declaration: { return "DW_TAG_imported_declaration"; } - case DW_TAG_label: { return "DW_TAG_label"; } - case DW_TAG_lexical_block: { return "DW_TAG_lexical_block"; } - case DW_TAG_member: { return "DW_TAG_member"; } - case DW_TAG_pointer_type: { return "DW_TAG_pointer_type"; } - case DW_TAG_reference_type: { return "DW_TAG_reference_type"; } - case DW_TAG_compile_unit: { return "DW_TAG_compile_unit"; } - case DW_TAG_string_type: { return "DW_TAG_string_type"; } - case DW_TAG_structure_type: { return "DW_TAG_structure_type"; } - case DW_TAG_subroutine_type: { return "DW_TAG_subroutine_type"; } - case DW_TAG_typedef: { return "DW_TAG_typedef"; } - case DW_TAG_union_type: { return "DW_TAG_union_type"; } - case DW_TAG_unspecified_parameters: { return "DW_TAG_unspecified_parameters"; } - case DW_TAG_variant: { return "DW_TAG_variant"; } - case DW_TAG_common_block: { return "DW_TAG_common_block"; } - case DW_TAG_common_inclusion: { return "DW_TAG_common_inclusion"; } - case DW_TAG_inheritance: { return "DW_TAG_inheritance"; } - case DW_TAG_inlined_subroutine: { return "DW_TAG_inlined_subroutine"; } - case DW_TAG_module: { return "DW_TAG_module"; } - case DW_TAG_ptr_to_member_type: { return "DW_TAG_ptr_to_member_type"; } - case DW_TAG_set_type: { return "DW_TAG_set_type"; } - case DW_TAG_subrange_type: { return "DW_TAG_subrange_type"; } - case DW_TAG_with_stmt: { return "DW_TAG_with_stmt"; } - case DW_TAG_access_declaration: { return "DW_TAG_access_declaration"; } - case DW_TAG_base_type: { return "DW_TAG_base_type"; } - case DW_TAG_catch_block: { return "DW_TAG_catch_block"; } - case DW_TAG_const_type: { return "DW_TAG_const_type"; } - case DW_TAG_constant: { return "DW_TAG_constant"; } - case DW_TAG_enumerator: { return "DW_TAG_enumerator"; } - case DW_TAG_file_type: { return "DW_TAG_file_type"; } - case DW_TAG_friend: { return "DW_TAG_friend"; } - case DW_TAG_namelist: { return "DW_TAG_namelist"; } - case DW_TAG_namelist_item: { return "DW_TAG_namelist_item"; } - case DW_TAG_packed_type: { return "DW_TAG_packed_type"; } - case DW_TAG_subprogram: { return "DW_TAG_subprogram"; } - case DW_TAG_thrown_type: { return "DW_TAG_thrown_type"; } - case DW_TAG_try_block: { return "DW_TAG_try_block"; } - case DW_TAG_variant_part: { return "DW_TAG_variant_part"; } - case DW_TAG_variable: { return "DW_TAG_variable"; } - case DW_TAG_volatile_type: { return "DW_TAG_volatile_type"; } - case DW_TAG_lo_user: { return "DW_TAG_lo_user"; } - case DW_TAG_MIPS_loop: { return "DW_TAG_MIPS_loop"; } - default: { return "unknown tag"; } - } +struct dwarf_cie_header { + u32 length; + u8 version; + u32 code_alignment; + s32 data_alignment; + u32 return_address_register; + u32 augmentation_data_length; + u8 *augmentation_data; - assert(0); + int has_z; - return(NULL); -} + enum dwarf_cie_pointer_format pointer_format; + enum dwarf_cie_pointer_application pointer_application; + u8 pointer_indirect; +}; + +struct dwarf_fde_header { + u32 length; + u64 optional_length; + struct dwarf_cie_header *cie; + u64 low_pc; + u64 high_pc; + u32 augmentation_data_length; + u8 *augmentation_data; +}; \ No newline at end of file diff --git a/util.c b/util.c index 528b8b2..e3c0a92 100644 --- a/util.c +++ b/util.c @@ -297,3 +297,13 @@ get_function_around_pc(struct mi_process proc, u64 pc) return(0); } + +#if 0 +static u64 +get_cfa_at_pc(struct mi_process proc, u64 pc) +{ + u64 *at = eh_frame_find_fde(proc, pc); + struct dwarf_regset regs = eh_frame_init(at); + u64 result = eh_frame_find_pc(at, regs, pc); +} +#endif \ No newline at end of file