Home | History | Annotate | Download | only in dwarf
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
     18 #define ART_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
     19 
     20 #include <cstdint>
     21 #include <unordered_map>
     22 
     23 #include "base/casts.h"
     24 #include "debug/dwarf/debug_abbrev_writer.h"
     25 #include "debug/dwarf/dwarf_constants.h"
     26 #include "debug/dwarf/expression.h"
     27 #include "debug/dwarf/writer.h"
     28 #include "leb128.h"
     29 
     30 namespace art {
     31 namespace dwarf {
     32 
     33 /*
     34  * Writer for debug information entries (DIE).
     35  *
     36  * Usage:
     37  *   StartTag(DW_TAG_compile_unit);
     38  *     WriteStrp(DW_AT_producer, "Compiler name", debug_str);
     39  *     StartTag(DW_TAG_subprogram);
     40  *       WriteStrp(DW_AT_name, "Foo", debug_str);
     41  *     EndTag();
     42  *   EndTag();
     43  */
     44 template <typename Vector = std::vector<uint8_t>>
     45 class DebugInfoEntryWriter FINAL : private Writer<Vector> {
     46   static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
     47 
     48  public:
     49   static constexpr size_t kCompilationUnitHeaderSize = 11;
     50 
     51   // Start debugging information entry.
     52   // Returns offset of the entry in compilation unit.
     53   size_t StartTag(Tag tag) {
     54     if (inside_entry_) {
     55       // Write abbrev code for the previous entry.
     56       // Parent entry is finalized before any children are written.
     57       this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_yes));
     58       inside_entry_ = false;
     59     }
     60     debug_abbrev_->StartAbbrev(tag);
     61     // Abbrev code placeholder of sufficient size.
     62     abbrev_code_offset_ = this->data()->size();
     63     this->PushUleb128(debug_abbrev_->NextAbbrevCode());
     64     depth_++;
     65     inside_entry_ = true;
     66     return abbrev_code_offset_ + kCompilationUnitHeaderSize;
     67   }
     68 
     69   // End debugging information entry.
     70   void EndTag() {
     71     DCHECK_GT(depth_, 0);
     72     if (inside_entry_) {
     73       // Write abbrev code for this entry.
     74       this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_no));
     75       inside_entry_ = false;
     76       // This entry has no children and so there is no terminator.
     77     } else {
     78       // The entry has been already finalized so it must be parent entry
     79       // and we need to write the terminator required by DW_CHILDREN_yes.
     80       this->PushUint8(0);
     81     }
     82     depth_--;
     83   }
     84 
     85   void WriteAddr(Attribute attrib, uint64_t value) {
     86     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_addr);
     87     patch_locations_.push_back(this->data()->size());
     88     if (is64bit_) {
     89       this->PushUint64(value);
     90     } else {
     91       this->PushUint32(value);
     92     }
     93   }
     94 
     95   void WriteBlock(Attribute attrib, const uint8_t* ptr, size_t num_bytes) {
     96     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_block);
     97     this->PushUleb128(num_bytes);
     98     this->PushData(ptr, num_bytes);
     99   }
    100 
    101   void WriteExprLoc(Attribute attrib, const Expression& expr) {
    102     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_exprloc);
    103     this->PushUleb128(dchecked_integral_cast<uint32_t>(expr.size()));
    104     this->PushData(expr.data());
    105   }
    106 
    107   void WriteData1(Attribute attrib, uint8_t value) {
    108     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data1);
    109     this->PushUint8(value);
    110   }
    111 
    112   void WriteData2(Attribute attrib, uint16_t value) {
    113     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data2);
    114     this->PushUint16(value);
    115   }
    116 
    117   void WriteData4(Attribute attrib, uint32_t value) {
    118     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data4);
    119     this->PushUint32(value);
    120   }
    121 
    122   void WriteData8(Attribute attrib, uint64_t value) {
    123     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data8);
    124     this->PushUint64(value);
    125   }
    126 
    127   void WriteSecOffset(Attribute attrib, uint32_t offset) {
    128     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sec_offset);
    129     this->PushUint32(offset);
    130   }
    131 
    132   void WriteSdata(Attribute attrib, int value) {
    133     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sdata);
    134     this->PushSleb128(value);
    135   }
    136 
    137   void WriteUdata(Attribute attrib, int value) {
    138     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata);
    139     this->PushUleb128(value);
    140   }
    141 
    142   void WriteUdata(Attribute attrib, uint32_t value) {
    143     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata);
    144     this->PushUleb128(value);
    145   }
    146 
    147   void WriteFlag(Attribute attrib, bool value) {
    148     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag);
    149     this->PushUint8(value ? 1 : 0);
    150   }
    151 
    152   void WriteFlagPresent(Attribute attrib) {
    153     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag_present);
    154   }
    155 
    156   void WriteRef4(Attribute attrib, uint32_t cu_offset) {
    157     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref4);
    158     this->PushUint32(cu_offset);
    159   }
    160 
    161   void WriteRef(Attribute attrib, uint32_t cu_offset) {
    162     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref_udata);
    163     this->PushUleb128(cu_offset);
    164   }
    165 
    166   void WriteString(Attribute attrib, const char* value) {
    167     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_string);
    168     this->PushString(value);
    169   }
    170 
    171   void WriteStrp(Attribute attrib, size_t debug_str_offset) {
    172     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
    173     this->PushUint32(dchecked_integral_cast<uint32_t>(debug_str_offset));
    174   }
    175 
    176   void WriteStrp(Attribute attrib, const char* str, size_t len,
    177                  std::vector<uint8_t>* debug_str) {
    178     debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
    179     this->PushUint32(debug_str->size());
    180     debug_str->insert(debug_str->end(), str, str + len);
    181     debug_str->push_back(0);
    182   }
    183 
    184   void WriteStrp(Attribute attrib, const char* str, std::vector<uint8_t>* debug_str) {
    185     WriteStrp(attrib, str, strlen(str), debug_str);
    186   }
    187 
    188   bool Is64bit() const { return is64bit_; }
    189 
    190   const std::vector<uintptr_t>& GetPatchLocations() const {
    191     return patch_locations_;
    192   }
    193 
    194   int Depth() const { return depth_; }
    195 
    196   using Writer<Vector>::data;
    197   using Writer<Vector>::size;
    198   using Writer<Vector>::UpdateUint32;
    199 
    200   DebugInfoEntryWriter(bool is64bitArch,
    201                        DebugAbbrevWriter<Vector>* debug_abbrev,
    202                        const typename Vector::allocator_type& alloc =
    203                            typename Vector::allocator_type())
    204       : Writer<Vector>(&entries_),
    205         debug_abbrev_(debug_abbrev),
    206         entries_(alloc),
    207         is64bit_(is64bitArch) {
    208   }
    209 
    210   ~DebugInfoEntryWriter() {
    211     DCHECK(!inside_entry_);
    212     DCHECK_EQ(depth_, 0);
    213   }
    214 
    215  private:
    216   DebugAbbrevWriter<Vector>* debug_abbrev_;
    217   Vector entries_;
    218   bool is64bit_;
    219   int depth_ = 0;
    220   size_t abbrev_code_offset_ = 0;  // Location to patch once we know the code.
    221   bool inside_entry_ = false;  // Entry ends at first child (if any).
    222   std::vector<uintptr_t> patch_locations_;
    223 };
    224 
    225 }  // namespace dwarf
    226 }  // namespace art
    227 
    228 #endif  // ART_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
    229