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 "llvm/DebugInfo/DWARFFormValue.h"
     11 #include "DWARFCompileUnit.h"
     12 #include "DWARFContext.h"
     13 #include "llvm/Support/Debug.h"
     14 #include "llvm/Support/Dwarf.h"
     15 #include "llvm/Support/Format.h"
     16 #include "llvm/Support/raw_ostream.h"
     17 #include <cassert>
     18 using namespace llvm;
     19 using namespace dwarf;
     20 
     21 namespace {
     22 template <uint8_t AddrSize, uint8_t RefAddrSize> struct FixedFormSizes {
     23   static const uint8_t sizes[];
     24 };
     25 }
     26 
     27 template <uint8_t AddrSize, uint8_t RefAddrSize>
     28 const uint8_t FixedFormSizes<AddrSize, RefAddrSize>::sizes[] = {
     29   0,           // 0x00 unused
     30   AddrSize,    // 0x01 DW_FORM_addr
     31   0,           // 0x02 unused
     32   0,           // 0x03 DW_FORM_block2
     33   0,           // 0x04 DW_FORM_block4
     34   2,           // 0x05 DW_FORM_data2
     35   4,           // 0x06 DW_FORM_data4
     36   8,           // 0x07 DW_FORM_data8
     37   0,           // 0x08 DW_FORM_string
     38   0,           // 0x09 DW_FORM_block
     39   0,           // 0x0a DW_FORM_block1
     40   1,           // 0x0b DW_FORM_data1
     41   1,           // 0x0c DW_FORM_flag
     42   0,           // 0x0d DW_FORM_sdata
     43   4,           // 0x0e DW_FORM_strp
     44   0,           // 0x0f DW_FORM_udata
     45   RefAddrSize, // 0x10 DW_FORM_ref_addr
     46   1,           // 0x11 DW_FORM_ref1
     47   2,           // 0x12 DW_FORM_ref2
     48   4,           // 0x13 DW_FORM_ref4
     49   8,           // 0x14 DW_FORM_ref8
     50   0,           // 0x15 DW_FORM_ref_udata
     51   0,           // 0x16 DW_FORM_indirect
     52   4,           // 0x17 DW_FORM_sec_offset
     53   0,           // 0x18 DW_FORM_exprloc
     54   0,           // 0x19 DW_FORM_flag_present
     55   8,           // 0x20 DW_FORM_ref_sig8
     56 };
     57 
     58 static uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
     59   // FIXME: Support DWARF64.
     60   return (Version == 2) ? AddrSize : 4;
     61 }
     62 
     63 const uint8_t *
     64 DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, uint16_t Version) {
     65   uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
     66   if (AddrSize == 4 && RefAddrSize == 4)
     67     return FixedFormSizes<4, 4>::sizes;
     68   if (AddrSize == 4 && RefAddrSize == 8)
     69     return FixedFormSizes<4, 8>::sizes;
     70   if (AddrSize == 8 && RefAddrSize == 4)
     71     return FixedFormSizes<8, 4>::sizes;
     72   if (AddrSize == 8 && RefAddrSize == 8)
     73     return FixedFormSizes<8, 8>::sizes;
     74   return 0;
     75 }
     76 
     77 bool
     78 DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
     79                              const DWARFCompileUnit *cu) {
     80   bool indirect = false;
     81   bool is_block = false;
     82   Value.data = NULL;
     83   // Read the value for the form into value and follow and DW_FORM_indirect
     84   // instances we run into
     85   do {
     86     indirect = false;
     87     switch (Form) {
     88     case DW_FORM_addr:
     89     case DW_FORM_ref_addr: {
     90       uint16_t AddrSize =
     91           (Form == DW_FORM_addr)
     92               ? cu->getAddressByteSize()
     93               : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
     94       RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
     95       if (AI != cu->getRelocMap()->end()) {
     96         const std::pair<uint8_t, int64_t> &R = AI->second;
     97         Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
     98       } else
     99         Value.uval = data.getUnsigned(offset_ptr, AddrSize);
    100       break;
    101     }
    102     case DW_FORM_exprloc:
    103     case DW_FORM_block:
    104       Value.uval = data.getULEB128(offset_ptr);
    105       is_block = true;
    106       break;
    107     case DW_FORM_block1:
    108       Value.uval = data.getU8(offset_ptr);
    109       is_block = true;
    110       break;
    111     case DW_FORM_block2:
    112       Value.uval = data.getU16(offset_ptr);
    113       is_block = true;
    114       break;
    115     case DW_FORM_block4:
    116       Value.uval = data.getU32(offset_ptr);
    117       is_block = true;
    118       break;
    119     case DW_FORM_data1:
    120     case DW_FORM_ref1:
    121     case DW_FORM_flag:
    122       Value.uval = data.getU8(offset_ptr);
    123       break;
    124     case DW_FORM_data2:
    125     case DW_FORM_ref2:
    126       Value.uval = data.getU16(offset_ptr);
    127       break;
    128     case DW_FORM_data4:
    129     case DW_FORM_ref4: {
    130       RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
    131       Value.uval = data.getU32(offset_ptr);
    132       if (AI != cu->getRelocMap()->end())
    133         Value.uval += AI->second.second;
    134       break;
    135     }
    136     case DW_FORM_data8:
    137     case DW_FORM_ref8:
    138       Value.uval = data.getU64(offset_ptr);
    139       break;
    140     case DW_FORM_sdata:
    141       Value.sval = data.getSLEB128(offset_ptr);
    142       break;
    143     case DW_FORM_strp: {
    144       RelocAddrMap::const_iterator AI
    145         = cu->getRelocMap()->find(*offset_ptr);
    146       if (AI != cu->getRelocMap()->end()) {
    147         const std::pair<uint8_t, int64_t> &R = AI->second;
    148         Value.uval = data.getU32(offset_ptr) + R.second;
    149       } else
    150         Value.uval = data.getU32(offset_ptr);
    151       break;
    152     }
    153     case DW_FORM_udata:
    154     case DW_FORM_ref_udata:
    155       Value.uval = data.getULEB128(offset_ptr);
    156       break;
    157     case DW_FORM_string:
    158       Value.cstr = data.getCStr(offset_ptr);
    159       // Set the string value to also be the data for inlined cstr form
    160       // values only so we can tell the differnence between DW_FORM_string
    161       // and DW_FORM_strp form values
    162       Value.data = (const uint8_t*)Value.cstr;
    163       break;
    164     case DW_FORM_indirect:
    165       Form = data.getULEB128(offset_ptr);
    166       indirect = true;
    167       break;
    168     case DW_FORM_sec_offset: {
    169       // FIXME: This is 64-bit for DWARF64.
    170       RelocAddrMap::const_iterator AI
    171         = cu->getRelocMap()->find(*offset_ptr);
    172       if (AI != cu->getRelocMap()->end()) {
    173         const std::pair<uint8_t, int64_t> &R = AI->second;
    174         Value.uval = data.getU32(offset_ptr) + R.second;
    175       } else
    176         Value.uval = data.getU32(offset_ptr);
    177       break;
    178     }
    179     case DW_FORM_flag_present:
    180       Value.uval = 1;
    181       break;
    182     case DW_FORM_ref_sig8:
    183       Value.uval = data.getU64(offset_ptr);
    184       break;
    185     case DW_FORM_GNU_addr_index:
    186       Value.uval = data.getULEB128(offset_ptr);
    187       break;
    188     case DW_FORM_GNU_str_index:
    189       Value.uval = data.getULEB128(offset_ptr);
    190       break;
    191     default:
    192       return false;
    193     }
    194   } while (indirect);
    195 
    196   if (is_block) {
    197     StringRef str = data.getData().substr(*offset_ptr, Value.uval);
    198     Value.data = NULL;
    199     if (!str.empty()) {
    200       Value.data = reinterpret_cast<const uint8_t *>(str.data());
    201       *offset_ptr += Value.uval;
    202     }
    203   }
    204 
    205   return true;
    206 }
    207 
    208 bool
    209 DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
    210                           const DWARFCompileUnit *cu) const {
    211   return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
    212 }
    213 
    214 bool
    215 DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
    216                           uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
    217   bool indirect = false;
    218   do {
    219     switch (form) {
    220     // Blocks if inlined data that have a length field and the data bytes
    221     // inlined in the .debug_info
    222     case DW_FORM_exprloc:
    223     case DW_FORM_block: {
    224       uint64_t size = debug_info_data.getULEB128(offset_ptr);
    225       *offset_ptr += size;
    226       return true;
    227     }
    228     case DW_FORM_block1: {
    229       uint8_t size = debug_info_data.getU8(offset_ptr);
    230       *offset_ptr += size;
    231       return true;
    232     }
    233     case DW_FORM_block2: {
    234       uint16_t size = debug_info_data.getU16(offset_ptr);
    235       *offset_ptr += size;
    236       return true;
    237     }
    238     case DW_FORM_block4: {
    239       uint32_t size = debug_info_data.getU32(offset_ptr);
    240       *offset_ptr += size;
    241       return true;
    242     }
    243 
    244     // Inlined NULL terminated C-strings
    245     case DW_FORM_string:
    246       debug_info_data.getCStr(offset_ptr);
    247       return true;
    248 
    249     // Compile unit address sized values
    250     case DW_FORM_addr:
    251       *offset_ptr += cu->getAddressByteSize();
    252       return true;
    253     case DW_FORM_ref_addr:
    254       *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
    255       return true;
    256 
    257     // 0 byte values - implied from the form.
    258     case DW_FORM_flag_present:
    259       return true;
    260 
    261     // 1 byte values
    262     case DW_FORM_data1:
    263     case DW_FORM_flag:
    264     case DW_FORM_ref1:
    265       *offset_ptr += 1;
    266       return true;
    267 
    268     // 2 byte values
    269     case DW_FORM_data2:
    270     case DW_FORM_ref2:
    271       *offset_ptr += 2;
    272       return true;
    273 
    274     // 4 byte values
    275     case DW_FORM_strp:
    276     case DW_FORM_data4:
    277     case DW_FORM_ref4:
    278       *offset_ptr += 4;
    279       return true;
    280 
    281     // 8 byte values
    282     case DW_FORM_data8:
    283     case DW_FORM_ref8:
    284     case DW_FORM_ref_sig8:
    285       *offset_ptr += 8;
    286       return true;
    287 
    288     // signed or unsigned LEB 128 values
    289     //  case DW_FORM_APPLE_db_str:
    290     case DW_FORM_sdata:
    291     case DW_FORM_udata:
    292     case DW_FORM_ref_udata:
    293     case DW_FORM_GNU_str_index:
    294     case DW_FORM_GNU_addr_index:
    295       debug_info_data.getULEB128(offset_ptr);
    296       return true;
    297 
    298     case DW_FORM_indirect:
    299       indirect = true;
    300       form = debug_info_data.getULEB128(offset_ptr);
    301       break;
    302 
    303     // FIXME: 4 for DWARF32, 8 for DWARF64.
    304     case DW_FORM_sec_offset:
    305       *offset_ptr += 4;
    306       return true;
    307 
    308     default:
    309       return false;
    310     }
    311   } while (indirect);
    312   return true;
    313 }
    314 
    315 void
    316 DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
    317   DataExtractor debug_str_data(cu->getStringSection(), true, 0);
    318   DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
    319   uint64_t uvalue = getUnsigned();
    320   bool cu_relative_offset = false;
    321 
    322   switch (Form) {
    323   case DW_FORM_addr:      OS << format("0x%016" PRIx64, uvalue); break;
    324   case DW_FORM_GNU_addr_index: {
    325     StringRef AddrOffsetSec = cu->getAddrOffsetSection();
    326     OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
    327     if (AddrOffsetSec.size() != 0) {
    328       DataExtractor DA(AddrOffsetSec, true, cu->getAddressByteSize());
    329       OS << format("0x%016" PRIx64, getIndirectAddress(&DA, cu));
    330     } else
    331       OS << "<no .debug_addr section>";
    332     break;
    333   }
    334   case DW_FORM_flag_present: OS << "true"; break;
    335   case DW_FORM_flag:
    336   case DW_FORM_data1:     OS << format("0x%02x", (uint8_t)uvalue); break;
    337   case DW_FORM_data2:     OS << format("0x%04x", (uint16_t)uvalue); break;
    338   case DW_FORM_data4:     OS << format("0x%08x", (uint32_t)uvalue); break;
    339   case DW_FORM_ref_sig8:
    340   case DW_FORM_data8:     OS << format("0x%016" PRIx64, uvalue); break;
    341   case DW_FORM_string:
    342     OS << '"';
    343     OS.write_escaped(getAsCString(NULL));
    344     OS << '"';
    345     break;
    346   case DW_FORM_exprloc:
    347   case DW_FORM_block:
    348   case DW_FORM_block1:
    349   case DW_FORM_block2:
    350   case DW_FORM_block4:
    351     if (uvalue > 0) {
    352       switch (Form) {
    353       case DW_FORM_exprloc:
    354       case DW_FORM_block:  OS << format("<0x%" PRIx64 "> ", uvalue);     break;
    355       case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
    356       case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
    357       case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
    358       default: break;
    359       }
    360 
    361       const uint8_t* data_ptr = Value.data;
    362       if (data_ptr) {
    363         // uvalue contains size of block
    364         const uint8_t* end_data_ptr = data_ptr + uvalue;
    365         while (data_ptr < end_data_ptr) {
    366           OS << format("%2.2x ", *data_ptr);
    367           ++data_ptr;
    368         }
    369       }
    370       else
    371         OS << "NULL";
    372     }
    373     break;
    374 
    375   case DW_FORM_sdata:     OS << getSigned();   break;
    376   case DW_FORM_udata:     OS << getUnsigned(); break;
    377   case DW_FORM_strp: {
    378     OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
    379     const char* dbg_str = getAsCString(&debug_str_data);
    380     if (dbg_str) {
    381       OS << '"';
    382       OS.write_escaped(dbg_str);
    383       OS << '"';
    384     }
    385     break;
    386   }
    387   case DW_FORM_GNU_str_index: {
    388     OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
    389     const char *dbg_str = getIndirectCString(&debug_str_data,
    390                                              &debug_str_offset_data);
    391     if (dbg_str) {
    392       OS << '"';
    393       OS.write_escaped(dbg_str);
    394       OS << '"';
    395     }
    396     break;
    397   }
    398   case DW_FORM_ref_addr:
    399     OS << format("0x%016" PRIx64, uvalue);
    400     break;
    401   case DW_FORM_ref1:
    402     cu_relative_offset = true;
    403     OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
    404     break;
    405   case DW_FORM_ref2:
    406     cu_relative_offset = true;
    407     OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
    408     break;
    409   case DW_FORM_ref4:
    410     cu_relative_offset = true;
    411     OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
    412     break;
    413   case DW_FORM_ref8:
    414     cu_relative_offset = true;
    415     OS << format("cu + 0x%8.8" PRIx64, uvalue);
    416     break;
    417   case DW_FORM_ref_udata:
    418     cu_relative_offset = true;
    419     OS << format("cu + 0x%" PRIx64, uvalue);
    420     break;
    421 
    422     // All DW_FORM_indirect attributes should be resolved prior to calling
    423     // this function
    424   case DW_FORM_indirect:
    425     OS << "DW_FORM_indirect";
    426     break;
    427 
    428     // Should be formatted to 64-bit for DWARF64.
    429   case DW_FORM_sec_offset:
    430     OS << format("0x%08x", (uint32_t)uvalue);
    431     break;
    432 
    433   default:
    434     OS << format("DW_FORM(0x%4.4x)", Form);
    435     break;
    436   }
    437 
    438   if (cu_relative_offset)
    439     OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
    440 }
    441 
    442 const char*
    443 DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
    444   if (isInlinedCStr()) {
    445     return Value.cstr;
    446   } else if (debug_str_data_ptr) {
    447     uint32_t offset = Value.uval;
    448     return debug_str_data_ptr->getCStr(&offset);
    449   }
    450   return NULL;
    451 }
    452 
    453 const char*
    454 DWARFFormValue::getIndirectCString(const DataExtractor *DS,
    455                                    const DataExtractor *DSO) const {
    456   if (!DS || !DSO) return NULL;
    457 
    458   uint32_t offset = Value.uval * 4;
    459   uint32_t soffset = DSO->getU32(&offset);
    460   return DS->getCStr(&soffset);
    461 }
    462 
    463 uint64_t
    464 DWARFFormValue::getIndirectAddress(const DataExtractor *DA,
    465                                    const DWARFCompileUnit *cu) const {
    466   if (!DA) return 0;
    467 
    468   uint32_t offset = Value.uval * cu->getAddressByteSize();
    469   return DA->getAddress(&offset);
    470 }
    471 
    472 uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
    473   uint64_t die_offset = Value.uval;
    474   switch (Form) {
    475   case DW_FORM_ref1:
    476   case DW_FORM_ref2:
    477   case DW_FORM_ref4:
    478   case DW_FORM_ref8:
    479   case DW_FORM_ref_udata:
    480       die_offset += (cu ? cu->getOffset() : 0);
    481       break;
    482   default:
    483       break;
    484   }
    485 
    486   return die_offset;
    487 }
    488 
    489 bool
    490 DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) {
    491   switch (Form) {
    492   case DW_FORM_ref1:
    493   case DW_FORM_ref2:
    494   case DW_FORM_ref4:
    495   case DW_FORM_ref8:
    496   case DW_FORM_ref_udata:
    497     Value.uval += cu->getOffset();
    498     Form = DW_FORM_ref_addr;
    499     return true;
    500   default:
    501     break;
    502   }
    503   return false;
    504 }
    505 
    506 const uint8_t *DWARFFormValue::BlockData() const {
    507   if (!isInlinedCStr())
    508     return Value.data;
    509   return NULL;
    510 }
    511 
    512 bool DWARFFormValue::isBlockForm(uint16_t form) {
    513   switch (form) {
    514   case DW_FORM_exprloc:
    515   case DW_FORM_block:
    516   case DW_FORM_block1:
    517   case DW_FORM_block2:
    518   case DW_FORM_block4:
    519     return true;
    520   }
    521   return false;
    522 }
    523 
    524 bool DWARFFormValue::isDataForm(uint16_t form) {
    525   switch (form) {
    526   case DW_FORM_sdata:
    527   case DW_FORM_udata:
    528   case DW_FORM_data1:
    529   case DW_FORM_data2:
    530   case DW_FORM_data4:
    531   case DW_FORM_data8:
    532     return true;
    533   }
    534   return false;
    535 }
    536