Fix a bug introduced by the move of AddressRanges.h into ADT.
authorGreg Clayton <gclayton@fb.com>
Tue, 14 Jun 2022 23:44:21 +0000 (16:44 -0700)
committerGreg Clayton <gclayton@fb.com>
Thu, 16 Jun 2022 17:50:46 +0000 (10:50 -0700)
The bug was introduced when the AddressRange class was no longer able to modify the End address directly and the entire range of the .text address range that contained the trailing empty symbol was replaced. There was no unit test for this, so it wasn't caught. I fixed the bug and added a unit test for it.

The effects of this bug are serious as the AddressOffsetSize in the header would be incorrectly calculated and an invalid GSYM would be created.

Differential Revision: https://reviews.llvm.org/D127811

llvm/lib/DebugInfo/GSYM/GsymCreator.cpp
llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp

index 415e6d1..8281938 100644 (file)
@@ -292,7 +292,7 @@ llvm::Error GsymCreator::finalize(llvm::raw_ostream &OS) {
   if (!Funcs.empty() && Funcs.back().Range.size() == 0 && ValidTextRanges) {
     if (auto Range =
             ValidTextRanges->getRangeThatContains(Funcs.back().Range.start())) {
-      Funcs.back().Range = *Range;
+      Funcs.back().Range = {Funcs.back().Range.start(), Range->end()};
     }
   }
   OS << "Pruned " << NumBefore - Funcs.size() << " functions, ended with "
index 9ee8eb8..67c004a 100644 (file)
@@ -1644,6 +1644,35 @@ TEST(GSYMTest, TestDWARFTextRanges) {
   EXPECT_EQ(MethodName, "main");
 }
 
+TEST(GSYMTest, TestEmptySymbolEndAddressOfTextRanges) {
+  // Test that if we have valid text ranges and we have a symbol with no size
+  // as the last FunctionInfo entry that the size of the symbol gets set to the
+  // end address of the text range.
+  GsymCreator GC;
+  AddressRanges TextRanges;
+  TextRanges.insert(AddressRange(0x1000, 0x2000));
+  GC.SetValidTextRanges(TextRanges);
+  GC.addFunctionInfo(FunctionInfo(0x1500, 0, GC.insertString("symbol")));
+  auto &OS = llvm::nulls();
+  ASSERT_THAT_ERROR(GC.finalize(OS), Succeeded());
+  SmallString<512> Str;
+  raw_svector_ostream OutStrm(Str);
+  const auto ByteOrder = support::endian::system_endianness();
+  FileWriter FW(OutStrm, ByteOrder);
+  ASSERT_THAT_ERROR(GC.encode(FW), Succeeded());
+  Expected<GsymReader> GR = GsymReader::copyBuffer(OutStrm.str());
+  ASSERT_THAT_EXPECTED(GR, Succeeded());
+  // There should only be one function in our GSYM.
+  EXPECT_EQ(GR->getNumAddresses(), 1u);
+  auto ExpFI = GR->getFunctionInfo(0x1500);
+  ASSERT_THAT_EXPECTED(ExpFI, Succeeded());
+  ASSERT_EQ(ExpFI->Range, AddressRange(0x1500, 0x2000));
+  EXPECT_FALSE(ExpFI->OptLineTable.hasValue());
+  EXPECT_FALSE(ExpFI->Inline.hasValue());
+  StringRef MethodName = GR->getString(ExpFI->Name);
+  EXPECT_EQ(MethodName, "symbol");
+}
+
 TEST(GSYMTest, TestDWARFInlineInfo) {
   // Make sure we parse the line table and inline information correctly from
   // DWARF.