Home | History | Annotate | Download | only in DebugInfo
      1 //===-- DWARFFormValue.cpp ------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "DWARFFormValue.h"
     11 #include "DWARFCompileUnit.h"
     12 #include "DWARFContext.h"
     13 #include "llvm/Support/Dwarf.h"
     14 #include "llvm/Support/Format.h"
     15 #include "llvm/Support/raw_ostream.h"
     16 #include <cassert>
     17 using namespace llvm;
     18 using namespace dwarf;
     19 
     20 static const uint8_t form_sizes_addr4[] = {
     21   0, // 0x00 unused
     22   4, // 0x01 DW_FORM_addr
     23   0, // 0x02 unused
     24   0, // 0x03 DW_FORM_block2
     25   0, // 0x04 DW_FORM_block4
     26   2, // 0x05 DW_FORM_data2
     27   4, // 0x06 DW_FORM_data4
     28   8, // 0x07 DW_FORM_data8
     29   0, // 0x08 DW_FORM_string
     30   0, // 0x09 DW_FORM_block
     31   0, // 0x0a DW_FORM_block1
     32   1, // 0x0b DW_FORM_data1
     33   1, // 0x0c DW_FORM_flag
     34   0, // 0x0d DW_FORM_sdata
     35   4, // 0x0e DW_FORM_strp
     36   0, // 0x0f DW_FORM_udata
     37   4, // 0x10 DW_FORM_ref_addr
     38   1, // 0x11 DW_FORM_ref1
     39   2, // 0x12 DW_FORM_ref2
     40   4, // 0x13 DW_FORM_ref4
     41   8, // 0x14 DW_FORM_ref8
     42   0, // 0x15 DW_FORM_ref_udata
     43   0, // 0x16 DW_FORM_indirect
     44 };
     45 
     46 static const uint8_t form_sizes_addr8[] = {
     47   0, // 0x00 unused
     48   8, // 0x01 DW_FORM_addr
     49   0, // 0x02 unused
     50   0, // 0x03 DW_FORM_block2
     51   0, // 0x04 DW_FORM_block4
     52   2, // 0x05 DW_FORM_data2
     53   4, // 0x06 DW_FORM_data4
     54   8, // 0x07 DW_FORM_data8
     55   0, // 0x08 DW_FORM_string
     56   0, // 0x09 DW_FORM_block
     57   0, // 0x0a DW_FORM_block1
     58   1, // 0x0b DW_FORM_data1
     59   1, // 0x0c DW_FORM_flag
     60   0, // 0x0d DW_FORM_sdata
     61   4, // 0x0e DW_FORM_strp
     62   0, // 0x0f DW_FORM_udata
     63   8, // 0x10 DW_FORM_ref_addr
     64   1, // 0x11 DW_FORM_ref1
     65   2, // 0x12 DW_FORM_ref2
     66   4, // 0x13 DW_FORM_ref4
     67   8, // 0x14 DW_FORM_ref8
     68   0, // 0x15 DW_FORM_ref_udata
     69   0, // 0x16 DW_FORM_indirect
     70 };
     71 
     72 const uint8_t *
     73 DWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) {
     74   switch (addr_size) {
     75   case 4: return form_sizes_addr4;
     76   case 8: return form_sizes_addr8;
     77   }
     78   return NULL;
     79 }
     80 
     81 bool
     82 DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
     83                              const DWARFCompileUnit *cu) {
     84   bool indirect = false;
     85   bool is_block = false;
     86   Value.data = NULL;
     87   // Read the value for the form into value and follow and DW_FORM_indirect
     88   // instances we run into
     89   do {
     90     indirect = false;
     91     switch (Form) {
     92     case DW_FORM_addr:
     93     case DW_FORM_ref_addr:
     94       Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
     95       break;
     96     case DW_FORM_block:
     97       Value.uval = data.getULEB128(offset_ptr);
     98       is_block = true;
     99       break;
    100     case DW_FORM_block1:
    101       Value.uval = data.getU8(offset_ptr);
    102       is_block = true;
    103       break;
    104     case DW_FORM_block2:
    105       Value.uval = data.getU16(offset_ptr);
    106       is_block = true;
    107       break;
    108     case DW_FORM_block4:
    109       Value.uval = data.getU32(offset_ptr);
    110       is_block = true;
    111       break;
    112     case DW_FORM_data1:
    113     case DW_FORM_ref1:
    114     case DW_FORM_flag:
    115       Value.uval = data.getU8(offset_ptr);
    116       break;
    117     case DW_FORM_data2:
    118     case DW_FORM_ref2:
    119       Value.uval = data.getU16(offset_ptr);
    120       break;
    121     case DW_FORM_data4:
    122     case DW_FORM_ref4:
    123       Value.uval = data.getU32(offset_ptr);
    124       break;
    125     case DW_FORM_data8:
    126     case DW_FORM_ref8:
    127       Value.uval = data.getU64(offset_ptr);
    128       break;
    129     case DW_FORM_sdata:
    130       Value.sval = data.getSLEB128(offset_ptr);
    131       break;
    132     case DW_FORM_strp:
    133       Value.uval = data.getU32(offset_ptr);
    134       break;
    135     case DW_FORM_udata:
    136     case DW_FORM_ref_udata:
    137       Value.uval = data.getULEB128(offset_ptr);
    138       break;
    139     case DW_FORM_string:
    140       Value.cstr = data.getCStr(offset_ptr);
    141       // Set the string value to also be the data for inlined cstr form
    142       // values only so we can tell the differnence between DW_FORM_string
    143       // and DW_FORM_strp form values
    144       Value.data = (uint8_t*)Value.cstr;
    145       break;
    146     case DW_FORM_indirect:
    147       Form = data.getULEB128(offset_ptr);
    148       indirect = true;
    149       break;
    150     default:
    151       return false;
    152     }
    153   } while (indirect);
    154 
    155   if (is_block) {
    156     StringRef str = data.getData().substr(*offset_ptr, Value.uval);
    157     Value.data = NULL;
    158     if (!str.empty()) {
    159       Value.data = reinterpret_cast<const uint8_t *>(str.data());
    160       *offset_ptr += Value.uval;
    161     }
    162   }
    163 
    164   return true;
    165 }
    166 
    167 bool
    168 DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
    169                           const DWARFCompileUnit *cu) const {
    170   return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
    171 }
    172 
    173 bool
    174 DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
    175                           uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
    176   bool indirect = false;
    177   do {
    178     indirect = false;
    179     switch (form) {
    180     // Blocks if inlined data that have a length field and the data bytes
    181     // inlined in the .debug_info
    182     case DW_FORM_block: {
    183       uint64_t size = debug_info_data.getULEB128(offset_ptr);
    184       *offset_ptr += size;
    185       return true;
    186     }
    187     case DW_FORM_block1: {
    188       uint8_t size = debug_info_data.getU8(offset_ptr);
    189       *offset_ptr += size;
    190       return true;
    191     }
    192     case DW_FORM_block2: {
    193       uint16_t size = debug_info_data.getU16(offset_ptr);
    194       *offset_ptr += size;
    195       return true;
    196     }
    197     case DW_FORM_block4: {
    198       uint32_t size = debug_info_data.getU32(offset_ptr);
    199       *offset_ptr += size;
    200       return true;
    201     }
    202 
    203     // Inlined NULL terminated C-strings
    204     case DW_FORM_string:
    205       debug_info_data.getCStr(offset_ptr);
    206       return true;
    207 
    208     // Compile unit address sized values
    209     case DW_FORM_addr:
    210     case DW_FORM_ref_addr:
    211       *offset_ptr += cu->getAddressByteSize();
    212       return true;
    213 
    214     // 1 byte values
    215     case DW_FORM_data1:
    216     case DW_FORM_flag:
    217     case DW_FORM_ref1:
    218       *offset_ptr += 1;
    219       return true;
    220 
    221     // 2 byte values
    222     case DW_FORM_data2:
    223     case DW_FORM_ref2:
    224       *offset_ptr += 2;
    225       return true;
    226 
    227     // 4 byte values
    228     case DW_FORM_strp:
    229     case DW_FORM_data4:
    230     case DW_FORM_ref4:
    231       *offset_ptr += 4;
    232       return true;
    233 
    234     // 8 byte values
    235     case DW_FORM_data8:
    236     case DW_FORM_ref8:
    237       *offset_ptr += 8;
    238       return true;
    239 
    240     // signed or unsigned LEB 128 values
    241     //  case DW_FORM_APPLE_db_str:
    242     case DW_FORM_sdata:
    243     case DW_FORM_udata:
    244     case DW_FORM_ref_udata:
    245       debug_info_data.getULEB128(offset_ptr);
    246       return true;
    247 
    248     case DW_FORM_indirect:
    249       indirect = true;
    250       form = debug_info_data.getULEB128(offset_ptr);
    251       break;
    252     default:
    253       return false;
    254     }
    255   } while (indirect);
    256   return true;
    257 }
    258 
    259 void
    260 DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
    261   DataExtractor debug_str_data(cu->getContext().getStringSection(), true, 0);
    262   uint64_t uvalue = getUnsigned();
    263   bool cu_relative_offset = false;
    264 
    265   switch (Form) {
    266   case DW_FORM_addr:      OS << format("0x%016x", uvalue); break;
    267   case DW_FORM_flag:
    268   case DW_FORM_data1:     OS << format("0x%02x", uvalue);  break;
    269   case DW_FORM_data2:     OS << format("0x%04x", uvalue);  break;
    270   case DW_FORM_data4:     OS << format("0x%08x", uvalue);  break;
    271   case DW_FORM_data8:     OS << format("0x%016x", uvalue); break;
    272   case DW_FORM_string:
    273     OS << '"';
    274     OS.write_escaped(getAsCString(NULL));
    275     OS << '"';
    276     break;
    277   case DW_FORM_block:
    278   case DW_FORM_block1:
    279   case DW_FORM_block2:
    280   case DW_FORM_block4:
    281     if (uvalue > 0) {
    282       switch (Form) {
    283       case DW_FORM_block:  OS << format("<0x%llx> ", uvalue);            break;
    284       case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
    285       case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
    286       case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
    287       default: break;
    288       }
    289 
    290       const uint8_t* data_ptr = Value.data;
    291       if (data_ptr) {
    292         // uvalue contains size of block
    293         const uint8_t* end_data_ptr = data_ptr + uvalue;
    294         while (data_ptr < end_data_ptr) {
    295           OS << format("%2.2x ", *data_ptr);
    296           ++data_ptr;
    297         }
    298       }
    299       else
    300         OS << "NULL";
    301     }
    302     break;
    303 
    304   case DW_FORM_sdata:     OS << getSigned();   break;
    305   case DW_FORM_udata:     OS << getUnsigned(); break;
    306   case DW_FORM_strp: {
    307     OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
    308     const char* dbg_str = getAsCString(&debug_str_data);
    309     if (dbg_str) {
    310       OS << '"';
    311       OS.write_escaped(dbg_str);
    312       OS << '"';
    313     }
    314     break;
    315   }
    316   case DW_FORM_ref_addr:
    317     OS << format("0x%016x", uvalue);
    318     break;
    319   case DW_FORM_ref1:
    320     cu_relative_offset = true;
    321     OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
    322     break;
    323   case DW_FORM_ref2:
    324     cu_relative_offset = true;
    325     OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
    326     break;
    327   case DW_FORM_ref4:
    328     cu_relative_offset = true;
    329     OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
    330     break;
    331   case DW_FORM_ref8:
    332     cu_relative_offset = true;
    333     OS << format("cu + 0x%8.8llx", uvalue);
    334     break;
    335   case DW_FORM_ref_udata:
    336     cu_relative_offset = true;
    337     OS << format("cu + 0x%llx", uvalue);
    338     break;
    339 
    340     // All DW_FORM_indirect attributes should be resolved prior to calling
    341     // this function
    342   case DW_FORM_indirect:
    343     OS << "DW_FORM_indirect";
    344     break;
    345   default:
    346     OS << format("DW_FORM(0x%4.4x)", Form);
    347     break;
    348   }
    349 
    350   if (cu_relative_offset)
    351     OS << format(" => {0x%8.8x}", (uvalue + (cu ? cu->getOffset() : 0)));
    352 }
    353 
    354 const char*
    355 DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
    356   if (isInlinedCStr()) {
    357     return Value.cstr;
    358   } else if (debug_str_data_ptr) {
    359     uint32_t offset = Value.uval;
    360     return debug_str_data_ptr->getCStr(&offset);
    361   }
    362   return NULL;
    363 }
    364 
    365 uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
    366   uint64_t die_offset = Value.uval;
    367   switch (Form) {
    368   case DW_FORM_ref1:
    369   case DW_FORM_ref2:
    370   case DW_FORM_ref4:
    371   case DW_FORM_ref8:
    372   case DW_FORM_ref_udata:
    373       die_offset += (cu ? cu->getOffset() : 0);
    374       break;
    375   default:
    376       break;
    377   }
    378 
    379   return die_offset;
    380 }
    381 
    382 bool
    383 DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) {
    384   switch (Form) {
    385   case DW_FORM_ref1:
    386   case DW_FORM_ref2:
    387   case DW_FORM_ref4:
    388   case DW_FORM_ref8:
    389   case DW_FORM_ref_udata:
    390     Value.uval += cu->getOffset();
    391     Form = DW_FORM_ref_addr;
    392     return true;
    393   default:
    394     break;
    395   }
    396   return false;
    397 }
    398 
    399 const uint8_t *DWARFFormValue::BlockData() const {
    400   if (!isInlinedCStr())
    401     return Value.data;
    402   return NULL;
    403 }
    404 
    405 bool DWARFFormValue::isBlockForm(uint16_t form) {
    406   switch (form) {
    407   case DW_FORM_block:
    408   case DW_FORM_block1:
    409   case DW_FORM_block2:
    410   case DW_FORM_block4:
    411     return true;
    412   }
    413   return false;
    414 }
    415 
    416 bool DWARFFormValue::isDataForm(uint16_t form) {
    417   switch (form) {
    418   case DW_FORM_sdata:
    419   case DW_FORM_udata:
    420   case DW_FORM_data1:
    421   case DW_FORM_data2:
    422   case DW_FORM_data4:
    423   case DW_FORM_data8:
    424     return true;
    425   }
    426   return false;
    427 }
    428