< prev index next >

src/jdk.hotspot.agent/linux/native/libsaproc/dwarf.cpp

Print this page




  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 }
< prev index next >