58 _buf += 8; 59 } 60 return length; 61 } 62 63 bool DwarfParser::process_cie(unsigned char *start_of_entry, uint32_t id) { 64 unsigned char *orig_pos = _buf; 65 _buf = start_of_entry - id; 66 67 uint64_t length = get_entry_length(); 68 if (length == 0L) { 69 return false; 70 } 71 unsigned char *end = _buf + length; 72 73 _buf += 4; // Skip ID (This value of CIE would be always 0) 74 _buf++; // Skip version (assume to be "1") 75 76 char *augmentation_string = reinterpret_cast<char *>(_buf); 77 bool has_ehdata = (strcmp("eh", augmentation_string) == 0); 78 bool fde_encoded = (strchr(augmentation_string, 'R') != NULL); 79 _buf += strlen(augmentation_string) + 1; // includes '\0' 80 if (has_ehdata) { 81 _buf += sizeof(void *); // Skip EH data 82 } 83 84 _code_factor = read_leb(false); 85 _data_factor = static_cast<int>(read_leb(true)); 86 _return_address_reg = static_cast<enum DWARF_Register>(*_buf++); 87 88 if (fde_encoded) { 89 uintptr_t augmentation_length = read_leb(false); 90 _encoding = *_buf++; 91 } 92 93 // Clear state 94 _current_pc = 0L; 95 _cfa_reg = RSP; 96 _return_address_reg = RA; 97 _cfa_offset = 0; 98 _ra_cfa_offset = 0; 99 _bp_cfa_offset = 0; 100 _bp_offset_available = false; 101 102 parse_dwarf_instructions(0L, static_cast<uintptr_t>(-1L), end); 103 104 _buf = orig_pos; 105 return true; 106 } 107 108 void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const unsigned char *end) { 109 uintptr_t operand1; 268 break; 269 default: 270 return 0; 271 } 272 273 // On x86-64, we have to handle it as 32 bit value, and it is PC relative. 274 // https://gcc.gnu.org/ml/gcc-help/2010-09/msg00166.html 275 #if defined(_LP64) 276 if ((size == 8) || (size == 2)) { 277 size = 4; 278 } 279 #endif 280 281 _buf += size; 282 return static_cast<unsigned int>(result); 283 } 284 285 bool DwarfParser::process_dwarf(const uintptr_t pc) { 286 // https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html 287 _buf = _lib->eh_frame.data; 288 while (true) { 289 uint64_t length = get_entry_length(); 290 if (length == 0L) { 291 return false; 292 } 293 unsigned char *next_entry = _buf + length; 294 unsigned char *start_of_entry = _buf; 295 uint32_t id = *(reinterpret_cast<uint32_t *>(_buf)); 296 _buf += 4; 297 if (id != 0) { // FDE 298 uintptr_t pc_begin = get_decoded_value() + _lib->eh_frame.library_base_addr; 299 uintptr_t pc_end = pc_begin + get_pc_range(); 300 301 if ((pc >= pc_begin) && (pc < pc_end)) { 302 // Process CIE 303 if (!process_cie(start_of_entry, id)) { 304 return false; 305 } 306 307 // Skip Augumenation 308 uintptr_t augmentation_length = read_leb(false); 309 _buf += augmentation_length; // skip 310 311 // Process FDE 312 parse_dwarf_instructions(pc_begin, pc, next_entry); 313 break; 314 } 315 } 316 317 _buf = next_entry; 318 } 319 320 return true; 321 } | 58 _buf += 8; 59 } 60 return length; 61 } 62 63 bool DwarfParser::process_cie(unsigned char *start_of_entry, uint32_t id) { 64 unsigned char *orig_pos = _buf; 65 _buf = start_of_entry - id; 66 67 uint64_t length = get_entry_length(); 68 if (length == 0L) { 69 return false; 70 } 71 unsigned char *end = _buf + length; 72 73 _buf += 4; // Skip ID (This value of CIE would be always 0) 74 _buf++; // Skip version (assume to be "1") 75 76 char *augmentation_string = reinterpret_cast<char *>(_buf); 77 bool has_ehdata = (strcmp("eh", augmentation_string) == 0); 78 _buf += strlen(augmentation_string) + 1; // includes '\0' 79 if (has_ehdata) { 80 _buf += sizeof(void *); // Skip EH data 81 } 82 83 _code_factor = read_leb(false); 84 _data_factor = static_cast<int>(read_leb(true)); 85 _return_address_reg = static_cast<enum DWARF_Register>(*_buf++); 86 87 if (strpbrk(augmentation_string, "LP") != NULL) { 88 // Language personality routine (P) and Language Specific Data Area (LSDA:L) 89 // are not supported because we need compliant Unwind Library Interface, 90 // but we want to unwind without it. 91 // 92 // Unwind Library Interface (SysV ABI AMD64 6.2) 93 // https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf 94 return false; 95 } else if (strchr(augmentation_string, 'R') != NULL) { 96 read_leb(false); // augmentation length 97 _encoding = *_buf++; 98 } 99 100 // Clear state 101 _current_pc = 0L; 102 _cfa_reg = RSP; 103 _return_address_reg = RA; 104 _cfa_offset = 0; 105 _ra_cfa_offset = 0; 106 _bp_cfa_offset = 0; 107 _bp_offset_available = false; 108 109 parse_dwarf_instructions(0L, static_cast<uintptr_t>(-1L), end); 110 111 _buf = orig_pos; 112 return true; 113 } 114 115 void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const unsigned char *end) { 116 uintptr_t operand1; 275 break; 276 default: 277 return 0; 278 } 279 280 // On x86-64, we have to handle it as 32 bit value, and it is PC relative. 281 // https://gcc.gnu.org/ml/gcc-help/2010-09/msg00166.html 282 #if defined(_LP64) 283 if ((size == 8) || (size == 2)) { 284 size = 4; 285 } 286 #endif 287 288 _buf += size; 289 return static_cast<unsigned int>(result); 290 } 291 292 bool DwarfParser::process_dwarf(const uintptr_t pc) { 293 // https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html 294 _buf = _lib->eh_frame.data; 295 unsigned char *end = _lib->eh_frame.data + _lib->eh_frame.size; 296 while (_buf <= end) { 297 uint64_t length = get_entry_length(); 298 if (length == 0L) { 299 return false; 300 } 301 unsigned char *next_entry = _buf + length; 302 unsigned char *start_of_entry = _buf; 303 uint32_t id = *(reinterpret_cast<uint32_t *>(_buf)); 304 _buf += 4; 305 if (id != 0) { // FDE 306 uintptr_t pc_begin = get_decoded_value() + _lib->eh_frame.library_base_addr; 307 uintptr_t pc_end = pc_begin + get_pc_range(); 308 309 if ((pc >= pc_begin) && (pc < pc_end)) { 310 // Process CIE 311 if (!process_cie(start_of_entry, id)) { 312 return false; 313 } 314 315 // Skip Augumenation 316 uintptr_t augmentation_length = read_leb(false); 317 _buf += augmentation_length; // skip 318 319 // Process FDE 320 parse_dwarf_instructions(pc_begin, pc, next_entry); 321 return true; 322 } 323 } 324 325 _buf = next_entry; 326 } 327 328 return false; 329 } |