brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.4 KiB · 7f477f1 Raw
291 lines · cpp
1//===-- SymbolFileDWARFTests.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "gtest/gtest.h"10 11#include "llvm/ADT/STLExtras.h"12#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"13#include "llvm/DebugInfo/PDB/PDBSymbolData.h"14#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"15#include "llvm/Support/FileSystem.h"16#include "llvm/Support/Path.h"17 18#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"19#include "Plugins/SymbolFile/DWARF/DWARFDataExtractor.h"20#include "Plugins/SymbolFile/DWARF/DWARFDebugAranges.h"21#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"22#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"23#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"24#include "TestingSupport/SubsystemRAII.h"25#include "TestingSupport/TestUtilities.h"26#include "lldb/Core/Address.h"27#include "lldb/Core/Module.h"28#include "lldb/Core/ModuleSpec.h"29#include "lldb/Host/FileSystem.h"30#include "lldb/Host/HostInfo.h"31#include "lldb/Symbol/CompileUnit.h"32#include "lldb/Symbol/LineTable.h"33#include "lldb/Utility/ArchSpec.h"34#include "lldb/Utility/DataEncoder.h"35#include "lldb/Utility/FileSpec.h"36#include "lldb/Utility/StreamString.h"37 38using namespace lldb;39using namespace lldb_private;40using namespace lldb_private::plugin::dwarf;41using namespace llvm::dwarf;42using llvm::DWARFDebugArangeSet;43 44class SymbolFileDWARFTests : public testing::Test {45  SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileDWARF,46                TypeSystemClang, SymbolFilePDB>47      subsystems;48 49public:50  void SetUp() override {51    m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");52  }53 54protected:55  std::string m_dwarf_test_exe;56};57 58TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) {59  // Test that when we have Dwarf debug info, SymbolFileDWARF is used.60  FileSpec fspec(m_dwarf_test_exe);61  ArchSpec aspec("i686-pc-windows");62  lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);63 64  SymbolFile *symfile = module->GetSymbolFile();65  ASSERT_NE(nullptr, symfile);66  EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic());67 68  uint32_t expected_abilities = SymbolFile::kAllAbilities;69  EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());70}71 72TEST_F(SymbolFileDWARFTests, ParseArangesNonzeroSegmentSize) {73  // This `.debug_aranges` table header is a valid 32bit big-endian section74  // according to the DWARFv5 spec:6.2.1, but contains segment selectors which75  // are not supported by lldb, and should be gracefully rejected76  const unsigned char binary_data[] = {77      0, 0, 0, 41, // unit_length (length field not including this field itself)78      0, 2,        // DWARF version number (half)79      0, 0, 0, 0, // offset into the .debug_info_table (ignored for the purposes80                  // of this test81      4,          // address size82      1,          // segment size83      // alignment for the first tuple which "begins at an offset that is a84      // multiple of the size of a single tuple". Tuples are nine bytes in this85      // example.86      0, 0, 0, 0, 0, 0,87      // BEGIN TUPLES88      1, 0, 0, 0, 4, 0, 0, 0,89      1, // a 1byte object starting at address 4 in segment 190      0, 0, 0, 0, 4, 0, 0, 0,91      1, // a 1byte object starting at address 4 in segment 092      // END TUPLES93      0, 0, 0, 0, 0, 0, 0, 0, 0 // terminator94  };95  llvm::DWARFDataExtractor data(llvm::ArrayRef<unsigned char>(binary_data),96                                /*isLittleEndian=*/false, /*AddrSize=*/4);97 98  DWARFDebugArangeSet debug_aranges;99  offset_t off = 0;100  llvm::Error error = debug_aranges.extract(data, &off);101  EXPECT_TRUE(bool(error));102  EXPECT_EQ("non-zero segment selector size in address range table at offset "103            "0x0 is not supported",104            llvm::toString(std::move(error)));105  EXPECT_EQ(off, 12U); // Parser should read no further than the segment size106}107 108TEST_F(SymbolFileDWARFTests, ParseArangesWithMultipleTerminators) {109  // This .debug_aranges set has multiple terminator entries which appear in110  // binaries produced by popular linux compilers and linker combinations. We111  // must be able to parse all the way through the data for each112  // DWARFDebugArangeSet. Previously the DWARFDebugArangeSet::extract()113  // function would stop parsing as soon as we ran into a terminator even114  // though the length field stated that there was more data that follows. This115  // would cause the next DWARFDebugArangeSet to be parsed immediately116  // following the first terminator and it would attempt to decode the117  // DWARFDebugArangeSet header using the remaining segment + address pairs118  // from the remaining bytes.119  unsigned char binary_data[] = {120      0, 0, 0, 0,   // unit_length that will be set correctly after this121      0, 2,         // DWARF version number (uint16_t)122      0, 0, 0, 255, // CU offset123      4,            // address size124      0,            // segment size125      0, 0, 0, 0,   // alignment for the first tuple126      // BEGIN TUPLES127      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator128      0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)129      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // premature terminator130      0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010)131      // END TUPLES132      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator133  };134  // Set the big endian length correctly.135  const offset_t binary_data_size = sizeof(binary_data);136  binary_data[3] = (uint8_t)binary_data_size - 4;137  DWARFDataExtractor data;138  data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,139               lldb::ByteOrder::eByteOrderBig);140  DWARFDebugAranges debug_aranges;141  debug_aranges.extract(data);142  // Parser should read all terminators to the end of the length specified.143  ASSERT_EQ(debug_aranges.GetNumRanges(), 2U);144  EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);145  EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u);146  EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u);147  EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);148  EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);149  EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u);150  EXPECT_EQ(debug_aranges.FindAddress(0x2010 - 1), 255u);151  EXPECT_EQ(debug_aranges.FindAddress(0x2010), DW_INVALID_OFFSET);152}153 154TEST_F(SymbolFileDWARFTests, ParseArangesIgnoreEmpty) {155  // This .debug_aranges set has some address ranges which have zero length156  // and we ensure that these are ignored by our DWARFDebugArangeSet parser157  // and not included in the descriptors that are returned.158  unsigned char binary_data[] = {159      0, 0, 0, 0,   // unit_length that will be set correctly after this160      0, 2,         // DWARF version number (uint16_t)161      0, 0, 0, 255, // CU offset162      4,            // address size163      0,            // segment size164      0, 0, 0, 0,   // alignment for the first tuple165      // BEGIN TUPLES166      0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)167      0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x1100-0x1100)168      0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, // [0x2000-0x2010)169      0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // [0x2010-0x2010)170      // END TUPLES171      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator172  };173  // Set the big endian length correctly.174  const offset_t binary_data_size = sizeof(binary_data);175  binary_data[3] = (uint8_t)binary_data_size - 4;176  DWARFDataExtractor data;177  data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,178               lldb::ByteOrder::eByteOrderBig);179  DWARFDebugAranges debug_aranges;180  debug_aranges.extract(data);181  // Parser should read all terminators to the end of the length specified.182  // Previously the DWARFDebugArangeSet would stop at the first terminator183  // entry and leave the offset in the middle of the current184  // DWARFDebugArangeSet data, and that would cause the next extracted185  // DWARFDebugArangeSet to fail.186  ASSERT_EQ(debug_aranges.GetNumRanges(), 2U);187  EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);188  EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u);189  EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u);190  EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);191  EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);192  EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u);193  EXPECT_EQ(debug_aranges.FindAddress(0x2010 - 1), 255u);194  EXPECT_EQ(debug_aranges.FindAddress(0x2010), DW_INVALID_OFFSET);195}196 197TEST_F(SymbolFileDWARFTests, ParseAranges) {198  // Test we can successfully parse a DWARFDebugAranges. The initial error199  // checking code had a bug where it would always return an empty address200  // ranges for everything in .debug_aranges and no error.201  unsigned char binary_data[] = {202      0, 0, 0, 0,   // unit_length that will be set correctly after this203      2, 0,         // DWARF version number204      255, 0, 0, 0, // offset into the .debug_info_table205      8,            // address size206      0,            // segment size207      0, 0, 0, 0,   // pad bytes208      // BEGIN TUPLES209      // First tuple: [0x1000-0x1100)210      0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x1000211      0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size    0x0100212      // Second tuple: [0x2000-0x2100)213      0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address 0x2000214      0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size    0x0100215      // Terminating tuple216      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator217      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Terminator218  };219  // Set the little endian length correctly.220  binary_data[0] = sizeof(binary_data) - 4;221  DWARFDataExtractor data;222  data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,223               lldb::ByteOrder::eByteOrderLittle);224  DWARFDebugAranges debug_aranges;225  debug_aranges.extract(data);226  EXPECT_EQ(debug_aranges.GetNumRanges(), 2u);227  EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);228  EXPECT_EQ(debug_aranges.FindAddress(0x1000), 255u);229  EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 255u);230  EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);231  EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);232  EXPECT_EQ(debug_aranges.FindAddress(0x2000), 255u);233  EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 255u);234  EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET);235}236 237TEST_F(SymbolFileDWARFTests, ParseArangesSkipErrors) {238  // Test we can successfully parse a DWARFDebugAranges that contains some239  // valid DWARFDebugArangeSet objects and some with errors as long as their240  // length is set correctly. This helps LLDB ensure that it can parse newer241  // .debug_aranges version that LLDB currently doesn't support, or ignore242  // errors in individual DWARFDebugArangeSet objects as long as the length243  // is set correctly.244  const unsigned char binary_data[] = {245      // This DWARFDebugArangeSet is well formed and has a single address range246      // for [0x1000-0x1100) with a CU offset of 0x00000000.247      0, 0, 0, 28, // unit_length that will be set correctly after this248      0, 2,        // DWARF version number (uint16_t)249      0, 0, 0, 0,  // CU offset = 0x00000000250      4,           // address size251      0,           // segment size252      0, 0, 0, 0,  // alignment for the first tuple253      0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x1000-0x1100)254      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator255      // This DWARFDebugArangeSet has the correct length, but an invalid256      // version. We need to be able to skip this correctly and ignore it.257      0, 0, 0, 20, // unit_length that will be set correctly after this258      0, 44,       // invalid DWARF version number (uint16_t)259      0, 0, 1, 0,  // CU offset = 0x00000100260      4,           // address size261      0,           // segment size262      0, 0, 0, 0,  // alignment for the first tuple263      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator264      // This DWARFDebugArangeSet is well formed and has a single address range265      // for [0x2000-0x2100) with a CU offset of 0x00000000.266      0, 0, 0, 28, // unit_length that will be set correctly after this267      0, 2,        // DWARF version number (uint16_t)268      0, 0, 2, 0,  // CU offset = 0x00000200269      4,           // address size270      0,           // segment size271      0, 0, 0, 0,  // alignment for the first tuple272      0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, // [0x2000-0x2100)273      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // terminator274  };275 276  DWARFDataExtractor data;277  data.SetData(static_cast<const void *>(binary_data), sizeof binary_data,278               lldb::ByteOrder::eByteOrderBig);279  DWARFDebugAranges debug_aranges;280  debug_aranges.extract(data);281  EXPECT_EQ(debug_aranges.GetNumRanges(), 2u);282  EXPECT_EQ(debug_aranges.FindAddress(0x0fff), DW_INVALID_OFFSET);283  EXPECT_EQ(debug_aranges.FindAddress(0x1000), 0u);284  EXPECT_EQ(debug_aranges.FindAddress(0x1100 - 1), 0u);285  EXPECT_EQ(debug_aranges.FindAddress(0x1100), DW_INVALID_OFFSET);286  EXPECT_EQ(debug_aranges.FindAddress(0x1fff), DW_INVALID_OFFSET);287  EXPECT_EQ(debug_aranges.FindAddress(0x2000), 0x200u);288  EXPECT_EQ(debug_aranges.FindAddress(0x2100 - 1), 0x200u);289  EXPECT_EQ(debug_aranges.FindAddress(0x2100), DW_INVALID_OFFSET);290}291