Browse Source

Prepare to compute CFA rules

master
A.Olokhtonov 3 years ago
parent
commit
24c0681298
  1. 94
      eh_frame.c
  2. 242
      elf_dwarf.h
  3. 10
      util.c

94
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 static u64
iterate_call_frame_instructions(u8 *data, u64 to_read) 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 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; u64 offset = 0;
s64 final_value; s64 final_value;
@ -466,14 +384,14 @@ read_encoded_pointer(struct mi_process proc, struct dwarf_cie_header *cie, u8 *d
} }
static u64 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 }; struct dwarf_fde_header header = { 0 };
header.length = length; header.length = length;
header.cie = (struct dwarf_cie_header *) (data - 4 - cie_offset); 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; data += pointer_size;
u64 fde_length = 0; 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 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; u8 *original_data = data;
u64 length; u64 length;
@ -532,7 +450,7 @@ read_one_call_frame_record(struct mi_process proc, struct dwarf_cie_header *last
if (cie_id == 0) { if (cie_id == 0) {
result = read_one_cie(last_cie, length, data, original_data); result = read_one_cie(last_cie, length, data, original_data);
} else { } 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); return(result);
@ -547,7 +465,7 @@ parse_eh_frame(struct mi_process proc)
u64 read = 0; u64 read = 0;
for (;;) { 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; read += size;
if (read >= eh_frame.size) { if (read >= eh_frame.size) {
break; break;

242
elf_dwarf.h

@ -478,6 +478,62 @@ enum dwarf_expression_op {
DW_OP_hi_user = 0xff 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) #pragma pack(1)
struct elf_header_x64 { struct elf_header_x64 {
char magic[4]; char magic[4];
@ -585,166 +641,28 @@ struct dwarf_line_number_state {
u32 discriminator; u32 discriminator;
}; };
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;
};
static char * struct dwarf_fde_header {
attribute_to_str(enum dwarf_die_tag attr) u32 length;
{ u64 optional_length;
switch (attr) { struct dwarf_cie_header *cie;
case DW_AT_sibling: { return "DW_AT_sibling"; } u64 low_pc;
case DW_AT_location: { return "DW_AT_location"; } u64 high_pc;
case DW_AT_name: { return "DW_AT_name"; } u32 augmentation_data_length;
case DW_AT_ordering: { return "DW_AT_ordering"; } u8 *augmentation_data;
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"; }
}
assert(0);
return(NULL);
}

10
util.c

@ -297,3 +297,13 @@ get_function_around_pc(struct mi_process proc, u64 pc)
return(0); 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
Loading…
Cancel
Save