diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp')
-rw-r--r-- | source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp | 374 |
1 files changed, 151 insertions, 223 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 5d2a8ffdb85b3..046ae67446af4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -1,169 +1,30 @@ //===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include <assert.h> +#include "lldb/Core/Module.h" #include "lldb/Core/dwarf.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/Stream.h" -#include "DWARFUnit.h" +#include "DWARFDebugInfo.h" #include "DWARFFormValue.h" +#include "DWARFUnit.h" class DWARFUnit; using namespace lldb_private; -static uint8_t g_form_sizes_addr4[] = { - 0, // 0x00 unused - 4, // 0x01 DW_FORM_addr - 0, // 0x02 unused - 0, // 0x03 DW_FORM_block2 - 0, // 0x04 DW_FORM_block4 - 2, // 0x05 DW_FORM_data2 - 4, // 0x06 DW_FORM_data4 - 8, // 0x07 DW_FORM_data8 - 0, // 0x08 DW_FORM_string - 0, // 0x09 DW_FORM_block - 0, // 0x0a DW_FORM_block1 - 1, // 0x0b DW_FORM_data1 - 1, // 0x0c DW_FORM_flag - 0, // 0x0d DW_FORM_sdata - 4, // 0x0e DW_FORM_strp - 0, // 0x0f DW_FORM_udata - 0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - 1, // 0x11 DW_FORM_ref1 - 2, // 0x12 DW_FORM_ref2 - 4, // 0x13 DW_FORM_ref4 - 8, // 0x14 DW_FORM_ref8 - 0, // 0x15 DW_FORM_ref_udata - 0, // 0x16 DW_FORM_indirect - 4, // 0x17 DW_FORM_sec_offset - 0, // 0x18 DW_FORM_exprloc - 0, // 0x19 DW_FORM_flag_present - 0, // 0x1a - 0, // 0x1b - 0, // 0x1c - 0, // 0x1d - 0, // 0x1e - 0, // 0x1f - 8, // 0x20 DW_FORM_ref_sig8 - -}; - -static uint8_t g_form_sizes_addr8[] = { - 0, // 0x00 unused - 8, // 0x01 DW_FORM_addr - 0, // 0x02 unused - 0, // 0x03 DW_FORM_block2 - 0, // 0x04 DW_FORM_block4 - 2, // 0x05 DW_FORM_data2 - 4, // 0x06 DW_FORM_data4 - 8, // 0x07 DW_FORM_data8 - 0, // 0x08 DW_FORM_string - 0, // 0x09 DW_FORM_block - 0, // 0x0a DW_FORM_block1 - 1, // 0x0b DW_FORM_data1 - 1, // 0x0c DW_FORM_flag - 0, // 0x0d DW_FORM_sdata - 4, // 0x0e DW_FORM_strp - 0, // 0x0f DW_FORM_udata - 0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - 1, // 0x11 DW_FORM_ref1 - 2, // 0x12 DW_FORM_ref2 - 4, // 0x13 DW_FORM_ref4 - 8, // 0x14 DW_FORM_ref8 - 0, // 0x15 DW_FORM_ref_udata - 0, // 0x16 DW_FORM_indirect - 4, // 0x17 DW_FORM_sec_offset - 0, // 0x18 DW_FORM_exprloc - 0, // 0x19 DW_FORM_flag_present - 0, // 0x1a - 0, // 0x1b - 0, // 0x1c - 0, // 0x1d - 0, // 0x1e - 0, // 0x1f - 8, // 0x20 DW_FORM_ref_sig8 -}; - -// Difference with g_form_sizes_addr8: -// DW_FORM_strp and DW_FORM_sec_offset are 8 instead of 4 -static uint8_t g_form_sizes_addr8_dwarf64[] = { - 0, // 0x00 unused - 8, // 0x01 DW_FORM_addr - 0, // 0x02 unused - 0, // 0x03 DW_FORM_block2 - 0, // 0x04 DW_FORM_block4 - 2, // 0x05 DW_FORM_data2 - 4, // 0x06 DW_FORM_data4 - 8, // 0x07 DW_FORM_data8 - 0, // 0x08 DW_FORM_string - 0, // 0x09 DW_FORM_block - 0, // 0x0a DW_FORM_block1 - 1, // 0x0b DW_FORM_data1 - 1, // 0x0c DW_FORM_flag - 0, // 0x0d DW_FORM_sdata - 8, // 0x0e DW_FORM_strp - 0, // 0x0f DW_FORM_udata - 0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - 1, // 0x11 DW_FORM_ref1 - 2, // 0x12 DW_FORM_ref2 - 4, // 0x13 DW_FORM_ref4 - 8, // 0x14 DW_FORM_ref8 - 0, // 0x15 DW_FORM_ref_udata - 0, // 0x16 DW_FORM_indirect - 8, // 0x17 DW_FORM_sec_offset - 0, // 0x18 DW_FORM_exprloc - 0, // 0x19 DW_FORM_flag_present - 0, // 0x1a - 0, // 0x1b - 0, // 0x1c - 0, // 0x1d - 0, // 0x1e - 0, // 0x1f - 8, // 0x20 DW_FORM_ref_sig8 -}; - -DWARFFormValue::FixedFormSizes -DWARFFormValue::GetFixedFormSizesForAddressSize(uint8_t addr_size, - bool is_dwarf64) { - if (!is_dwarf64) { - switch (addr_size) { - case 4: - return FixedFormSizes(g_form_sizes_addr4, sizeof(g_form_sizes_addr4)); - case 8: - return FixedFormSizes(g_form_sizes_addr8, sizeof(g_form_sizes_addr8)); - } - } else { - if (addr_size == 8) - return FixedFormSizes(g_form_sizes_addr8_dwarf64, - sizeof(g_form_sizes_addr8_dwarf64)); - // is_dwarf64 && addr_size == 4 : no provider does this. - } - return FixedFormSizes(); -} - -DWARFFormValue::DWARFFormValue() : m_cu(NULL), m_form(0), m_value() {} - -DWARFFormValue::DWARFFormValue(const DWARFUnit *cu) - : m_cu(cu), m_form(0), m_value() {} - -DWARFFormValue::DWARFFormValue(const DWARFUnit *cu, dw_form_t form) - : m_cu(cu), m_form(form), m_value() {} - void DWARFFormValue::Clear() { - m_cu = nullptr; + m_unit = nullptr; m_form = 0; - memset(&m_value, 0, sizeof(m_value)); + m_value = ValueTypeTag(); } bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, @@ -173,7 +34,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, bool indirect = false; bool is_block = false; - m_value.data = NULL; + m_value.data = nullptr; uint8_t ref_addr_size; // Read the value for the form into value and follow and DW_FORM_indirect // instances we run into @@ -181,9 +42,9 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, indirect = false; switch (m_form) { case DW_FORM_addr: - assert(m_cu); + assert(m_unit); m_value.value.uval = - data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_cu)); + data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit)); break; case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); @@ -215,9 +76,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, case DW_FORM_strp: case DW_FORM_line_strp: case DW_FORM_sec_offset: - assert(m_cu); - m_value.value.uval = - data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4); + m_value.value.uval = data.GetMaxU64(offset_ptr, 4); break; case DW_FORM_addrx1: case DW_FORM_strx1: @@ -257,11 +116,11 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, m_value.value.uval = data.GetULEB128(offset_ptr); break; case DW_FORM_ref_addr: - assert(m_cu); - if (m_cu->GetVersion() <= 2) - ref_addr_size = m_cu->GetAddressByteSize(); + assert(m_unit); + if (m_unit->GetVersion() <= 2) + ref_addr_size = m_unit->GetAddressByteSize(); else - ref_addr_size = m_cu->IsDWARF64() ? 8 : 4; + ref_addr_size = 4; m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size); break; case DW_FORM_indirect: @@ -278,7 +137,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, if (is_block) { m_value.data = data.PeekData(*offset_ptr, m_value.value.uval); - if (m_value.data != NULL) { + if (m_value.data != nullptr) { *offset_ptr += m_value.value.uval; } } @@ -286,15 +145,68 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, return true; } +struct FormSize { + uint8_t valid:1, size:7; +}; +static FormSize g_form_sizes[] = { + {0,0}, // 0x00 unused + {0,0}, // 0x01 DW_FORM_addr + {0,0}, // 0x02 unused + {0,0}, // 0x03 DW_FORM_block2 + {0,0}, // 0x04 DW_FORM_block4 + {1,2}, // 0x05 DW_FORM_data2 + {1,4}, // 0x06 DW_FORM_data4 + {1,8}, // 0x07 DW_FORM_data8 + {0,0}, // 0x08 DW_FORM_string + {0,0}, // 0x09 DW_FORM_block + {0,0}, // 0x0a DW_FORM_block1 + {1,1}, // 0x0b DW_FORM_data1 + {1,1}, // 0x0c DW_FORM_flag + {0,0}, // 0x0d DW_FORM_sdata + {1,4}, // 0x0e DW_FORM_strp + {0,0}, // 0x0f DW_FORM_udata + {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for + // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later + {1,1}, // 0x11 DW_FORM_ref1 + {1,2}, // 0x12 DW_FORM_ref2 + {1,4}, // 0x13 DW_FORM_ref4 + {1,8}, // 0x14 DW_FORM_ref8 + {0,0}, // 0x15 DW_FORM_ref_udata + {0,0}, // 0x16 DW_FORM_indirect + {1,4}, // 0x17 DW_FORM_sec_offset + {0,0}, // 0x18 DW_FORM_exprloc + {1,0}, // 0x19 DW_FORM_flag_present + {0,0}, // 0x1a + {0,0}, // 0x1b + {0,0}, // 0x1c + {0,0}, // 0x1d + {0,0}, // 0x1e + {0,0}, // 0x1f + {1,8}, // 0x20 DW_FORM_ref_sig8 +}; + +llvm::Optional<uint8_t> +DWARFFormValue::GetFixedSize(dw_form_t form, const DWARFUnit *u) { + if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid) + return g_form_sizes[form].size; + if (form == DW_FORM_addr && u) + return u->GetAddressByteSize(); + return llvm::None; +} + +llvm::Optional<uint8_t> DWARFFormValue::GetFixedSize() const { + return GetFixedSize(m_form, m_unit); +} + bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr) const { - return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_cu); + return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit); } bool DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr, - const DWARFUnit *cu) { + const DWARFUnit *unit) { uint8_t ref_addr_size; switch (form) { // Blocks if inlined data that have a length field and the data bytes inlined @@ -328,17 +240,17 @@ bool DWARFFormValue::SkipValue(dw_form_t form, // Compile unit address sized values case DW_FORM_addr: - *offset_ptr += DWARFUnit::GetAddressByteSize(cu); + *offset_ptr += DWARFUnit::GetAddressByteSize(unit); return true; case DW_FORM_ref_addr: ref_addr_size = 4; - assert(cu); // CU must be valid for DW_FORM_ref_addr objects or we will get - // this wrong - if (cu->GetVersion() <= 2) - ref_addr_size = cu->GetAddressByteSize(); + assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will + // get this wrong + if (unit->GetVersion() <= 2) + ref_addr_size = unit->GetAddressByteSize(); else - ref_addr_size = cu->IsDWARF64() ? 8 : 4; + ref_addr_size = 4; *offset_ptr += ref_addr_size; return true; @@ -373,8 +285,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, // 32 bit for DWARF 32, 64 for DWARF 64 case DW_FORM_sec_offset: case DW_FORM_strp: - assert(cu); - *offset_ptr += (cu->IsDWARF64() ? 8 : 4); + *offset_ptr += 4; return true; // 4 byte values @@ -407,7 +318,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, case DW_FORM_indirect: { dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr); return DWARFFormValue::SkipValue(indirect_form, debug_info_data, offset_ptr, - cu); + unit); } default: @@ -418,7 +329,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, void DWARFFormValue::Dump(Stream &s) const { uint64_t uvalue = Unsigned(); - bool cu_relative_offset = false; + bool unit_relative_offset = false; switch (m_form) { case DW_FORM_addr: @@ -495,9 +406,9 @@ void DWARFFormValue::Dump(Stream &s) const { } break; case DW_FORM_ref_addr: { - assert(m_cu); // CU must be valid for DW_FORM_ref_addr objects or we will - // get this wrong - if (m_cu->GetVersion() <= 2) + assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we + // will get this wrong + if (m_unit->GetVersion() <= 2) s.Address(uvalue, sizeof(uint64_t) * 2); else s.Address(uvalue, 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't @@ -505,19 +416,19 @@ void DWARFFormValue::Dump(Stream &s) const { break; } case DW_FORM_ref1: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref2: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref4: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref8: - cu_relative_offset = true; + unit_relative_offset = true; break; case DW_FORM_ref_udata: - cu_relative_offset = true; + unit_relative_offset = true; break; // All DW_FORM_indirect attributes should be resolved prior to calling this @@ -532,33 +443,29 @@ void DWARFFormValue::Dump(Stream &s) const { break; } - if (cu_relative_offset) { - assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile - // unit relative or we will get this wrong - s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_cu->GetOffset()); + if (unit_relative_offset) { + assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile + // unit relative or we will get this wrong + s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset()); } } const char *DWARFFormValue::AsCString() const { - SymbolFileDWARF *symbol_file = m_cu->GetSymbolFileDWARF(); + SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); if (m_form == DW_FORM_string) { return m_value.value.cstr; } else if (m_form == DW_FORM_strp) { - if (!symbol_file) - return nullptr; - - return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval); + return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( + m_value.value.uval); } else if (m_form == DW_FORM_GNU_str_index) { - if (!symbol_file) - return nullptr; - - uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4; + uint32_t index_size = 4; lldb::offset_t offset = m_value.value.uval * index_size; dw_offset_t str_offset = - symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, - index_size); - return symbol_file->get_debug_str_data().PeekCStr(str_offset); + symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( + &offset, index_size); + return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr( + str_offset); } if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 || @@ -566,44 +473,41 @@ const char *DWARFFormValue::AsCString() const { m_form == DW_FORM_strx4) { // The same code as above. - if (!symbol_file) - return nullptr; - - uint32_t indexSize = m_cu->IsDWARF64() ? 8 : 4; + uint32_t indexSize = 4; lldb::offset_t offset = - m_cu->GetStrOffsetsBase() + m_value.value.uval * indexSize; + m_unit->GetStrOffsetsBase() + m_value.value.uval * indexSize; dw_offset_t strOffset = - symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, indexSize); - return symbol_file->get_debug_str_data().PeekCStr(strOffset); + symbol_file.GetDWARFContext().getOrLoadStrOffsetsData().GetMaxU64( + &offset, indexSize); + return symbol_file.GetDWARFContext().getOrLoadStrData().PeekCStr(strOffset); } if (m_form == DW_FORM_line_strp) - return symbol_file->get_debug_line_str_data().PeekCStr(m_value.value.uval); + return symbol_file.GetDWARFContext().getOrLoadLineStrData().PeekCStr( + m_value.value.uval); return nullptr; } dw_addr_t DWARFFormValue::Address() const { - SymbolFileDWARF *symbol_file = m_cu->GetSymbolFileDWARF(); + SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF(); if (m_form == DW_FORM_addr) return Unsigned(); - assert(m_cu); + assert(m_unit); assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx || m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 || m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4); - if (!symbol_file) - return 0; - - uint32_t index_size = m_cu->GetAddressByteSize(); - dw_offset_t addr_base = m_cu->GetAddrBase(); + uint32_t index_size = m_unit->GetAddressByteSize(); + dw_offset_t addr_base = m_unit->GetAddrBase(); lldb::offset_t offset = addr_base + m_value.value.uval * index_size; - return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size); + return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64( + &offset, index_size); } -uint64_t DWARFFormValue::Reference() const { +DWARFDIE DWARFFormValue::Reference() const { uint64_t value = m_value.value.uval; switch (m_form) { case DW_FORM_ref1: @@ -611,17 +515,40 @@ uint64_t DWARFFormValue::Reference() const { case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile - // unit relative or we will get this wrong - return value + m_cu->GetOffset(); + assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile + // unit relative or we will get this wrong + value += m_unit->GetOffset(); + if (!m_unit->ContainsDIEOffset(value)) { + m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU", + value); + return {}; + } + return const_cast<DWARFUnit *>(m_unit)->GetDIE(value); - case DW_FORM_ref_addr: - case DW_FORM_ref_sig8: - case DW_FORM_GNU_ref_alt: - return value; + case DW_FORM_ref_addr: { + DWARFUnit *ref_cu = + m_unit->GetSymbolFileDWARF().DebugInfo()->GetUnitContainingDIEOffset( + DIERef::Section::DebugInfo, value); + if (!ref_cu) { + m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU", + value); + return {}; + } + return ref_cu->GetDIE(value); + } + + case DW_FORM_ref_sig8: { + DWARFTypeUnit *tu = + m_unit->GetSymbolFileDWARF().DebugInfo()->GetTypeUnitForHash(value); + if (!tu) + return {}; + return tu->GetDIE(tu->GetTypeOffset()); + } default: - return DW_INVALID_OFFSET; + return {}; } } @@ -682,6 +609,7 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, return 1; switch (a_form) { case DW_FORM_addr: + case DW_FORM_addrx: case DW_FORM_flag: case DW_FORM_data1: case DW_FORM_data2: @@ -721,7 +649,7 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, return 0; else if (a_string && b_string) return strcmp(a_string, b_string); - else if (a_string == NULL) + else if (a_string == nullptr) return -1; // A string is NULL, and B is valid else return 1; // A string valid, and B is NULL @@ -747,8 +675,8 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: { - uint64_t a = a_value.Reference(); - uint64_t b = b_value.Reference(); + uint64_t a = a_value.m_value.value.uval; + uint64_t b = b_value.m_value.value.uval; if (a < b) return -1; if (a > b) |