diff --git a/libIRDB/test/dwarf2.h b/libIRDB/test/dwarf2.h index 57c2d4e7440a71e4eff487e2fcafa9af18c6e844..6917b1457496310a34a8d33508e9ff89f062e56c 100644 --- a/libIRDB/test/dwarf2.h +++ b/libIRDB/test/dwarf2.h @@ -507,6 +507,11 @@ enum dwarf_call_frame_info DW_CFA_offset_extended_sf = 0x11, DW_CFA_def_cfa_sf = 0x12, DW_CFA_def_cfa_offset_sf = 0x13, + /* added by jdh for newer version of dwarf? libc uses this in ubuntu 14.04 */ + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + /* SGI/MIPS specific */ DW_CFA_MIPS_advance_loc8 = 0x1d, diff --git a/libIRDB/test/split_eh_frame.cpp b/libIRDB/test/split_eh_frame.cpp index 20223a7b485c79028b0426f1db7801ec915e8614..0a825830abc2c8dc066d923cc381ecfcadab80a0 100644 --- a/libIRDB/test/split_eh_frame.cpp +++ b/libIRDB/test/split_eh_frame.cpp @@ -393,6 +393,12 @@ class eh_program_insn_t print_uleb_operand(pos,data,max); cout<<endl; break; + case DW_CFA_def_cfa_sf: + cout<<" def_cfa_sf "; + print_uleb_operand(pos,data,max); + print_sleb_operand(pos,data,max); + cout<<endl; + break; case DW_CFA_def_cfa_expression: { @@ -415,13 +421,38 @@ class eh_program_insn_t pos+=uleb2; break; } - - - - /* Dwarf 2.1 */ - case DW_CFA_offset_extended_sf: - case DW_CFA_def_cfa_sf: + case DW_CFA_val_expression: + { + auto uleb1=uint64_t(0); + auto uleb2=uint64_t(0); + if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, data, max)) + return ; + if(eh_frame_util_t<ptrsize>::read_uleb128(uleb2, pos, data, max)) + return ; + cout<<" val_expression "<<dec<<uleb1<<" "<<uleb2<<endl; + pos+=uleb2; + break; + } case DW_CFA_def_cfa_offset_sf: + { + auto leb=int64_t(0); + if(eh_frame_util_t<ptrsize>::read_sleb128(leb, pos, data, max)) + return ; + cout<<" def_cfa_offset_sf "<<dec<<leb; + break; + } + case DW_CFA_offset_extended_sf: + { + auto uleb1=uint64_t(0); + auto sleb2=int64_t(0); + if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, data, max)) + return ; + if(eh_frame_util_t<ptrsize>::read_sleb128(sleb2, pos, data, max)) + return ; + cout<<" offset_extended_sf "<<dec<<uleb1<<" "<<sleb2<<endl; + break; + } + /* SGI/MIPS specific */ case DW_CFA_MIPS_advance_loc8: @@ -450,6 +481,16 @@ class eh_program_insn_t cout<<" "<<dec<<uleb; } + static void print_sleb_operand( + uint32_t pos, + const uint8_t* const data, + const uint32_t max) + { + auto leb=int64_t(0xdeadbeef); + eh_frame_util_t<ptrsize>::read_sleb128(leb, pos, data, max); + cout<<" "<<dec<<leb; + } + bool parse_insn( uint8_t opcode, uint32_t& pos, @@ -533,6 +574,16 @@ class eh_program_insn_t return true; break; } + case DW_CFA_def_cfa_sf: + { + uint64_t leb1=0; + int64_t leb2=0; + if(eh_frame_util_t<ptrsize>::read_uleb128(leb1, pos, data, max)) + return true; + if(eh_frame_util_t<ptrsize>::read_sleb128(leb2, pos, data, max)) + return true; + break; + } case DW_CFA_def_cfa_expression: { @@ -543,6 +594,7 @@ class eh_program_insn_t break; } case DW_CFA_expression: + case DW_CFA_val_expression: { uint64_t uleb1=0, uleb2=0; if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, data, max)) @@ -552,13 +604,27 @@ class eh_program_insn_t pos+=uleb2; break; } - - - - /* Dwarf 2.1 */ - case DW_CFA_offset_extended_sf: - case DW_CFA_def_cfa_sf: case DW_CFA_def_cfa_offset_sf: + { + auto leb=int64_t(0); + if(eh_frame_util_t<ptrsize>::read_sleb128(leb, pos, data, max)) + return true; + break; + } + case DW_CFA_offset_extended_sf: + { + auto uleb1=uint64_t(0); + auto sleb2=int64_t(0); + if(eh_frame_util_t<ptrsize>::read_uleb128(uleb1, pos, data, max)) + return true; + if(eh_frame_util_t<ptrsize>::read_sleb128(sleb2, pos, data, max)) + return true; + break; + } + /* Dwarf 2.1 */ + case DW_CFA_val_offset: + case DW_CFA_val_offset_sf: + /* SGI/MIPS specific */ case DW_CFA_MIPS_advance_loc8: @@ -568,11 +634,13 @@ class eh_program_insn_t case DW_CFA_GNU_negative_offset_extended: default: // Unhandled opcode cannot xform this eh-frame + cout<<"No decoder for opcode "<<+opcode<<endl; return true; } break; } default: + cout<<"No decoder for opcode "<<+opcode<<endl; return true; } @@ -754,7 +822,12 @@ class cie_contents_t : eh_frame_util_t<ptrsize> { if(this->read_type(personality_encoding, position, eh_frame_scoop_data, max)) return true; - if(this->read_type_with_encoding(personality_encoding, personality, position, eh_frame_scoop_data, max, eh_addr)) + + // indirect is OK as a personality encoding, but we don't need to go that far. + // we just need to record what's in the CIE, regardless of whether it's the actual + // personality routine or it's the pointer to the personality routine. + auto personality_encoding_sans_indirect = personality_encoding&(~DW_EH_PE_indirect); + if(this->read_type_with_encoding(personality_encoding_sans_indirect, personality, position, eh_frame_scoop_data, max, eh_addr)) return true; } @@ -876,9 +949,10 @@ class lsda_type_table_entry_t: private eh_frame_util_t<ptrsize> ) { auto size=uint32_t(0); - switch(tt_encoding) + switch(tt_encoding & 0xf) // get just the size field { case DW_EH_PE_udata4: + case DW_EH_PE_sdata4: size=4; break; default: @@ -1122,7 +1196,8 @@ class lsda_t : private eh_frame_util_t<ptrsize> for(int i=1;i<=max_tt_entry;i++) { lsda_type_table_entry_t <ptrsize> ltte; - if(ltte.parse(type_table_encoding, type_table_pos, i, data, max, data_addr )) + auto type_table_encoding_sans_indirect = type_table_encoding&(~DW_EH_PE_indirect); + if(ltte.parse(type_table_encoding_sans_indirect, type_table_pos, i, data, max, data_addr )) return true; type_table.push_back(ltte); }