summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/DebugInfo
diff options
context:
space:
mode:
authorGreg Clayton <clayborg@gmail.com>2019-08-21 21:48:11 +0000
committerGreg Clayton <clayborg@gmail.com>2019-08-21 21:48:11 +0000
commitbf9ee07afa3f1a15277018f60787a1a205ec08d8 (patch)
treeaae9e69103534d60db4dbc08f1cdc26bebc572ce /llvm/unittests/DebugInfo
parenta41b239081c19c4f36d9a616d9f502a5c87c5deb (diff)
downloadbcm5719-llvm-bf9ee07afa3f1a15277018f60787a1a205ec08d8.tar.gz
bcm5719-llvm-bf9ee07afa3f1a15277018f60787a1a205ec08d8.zip
Add FileWriter to GSYM and encode/decode functions to AddressRange and AddressRanges
The full GSYM patch started with: https://reviews.llvm.org/D53379 This patch add the ability to encode data using the new llvm::gsym::FileWriter class. FileWriter is a simplified binary data writer class that doesn't require targets, target definitions, architectures, or require any other optional compile time libraries to be enabled via the build process. This class needs the ability to seek to different spots in the binary data that it produces to fix up offsets and sizes in GSYM data. It currently uses std::ostream over llvm::raw_ostream because llvm::raw_ostream doesn't support seeking which is required when encoding and decoding GSYM data. AddressRange objects are encoded and decoded to be relative to a base address. This will be the FunctionInfo's start address if the AddressRange is directly contained in a FunctionInfo, or a base address of the containing parent AddressRange or AddressRanges. This allows address ranges to be efficiently encoded using ULEB128 encodings as we encode the offset and size of each range instead of full addresses. This also makes encoded addresses easy to relocate as we just need to relocate one base address. Differential Revision: https://reviews.llvm.org/D63828 llvm-svn: 369587
Diffstat (limited to 'llvm/unittests/DebugInfo')
-rw-r--r--llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp120
1 files changed, 119 insertions, 1 deletions
diff --git a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
index dc346916fff..38e57a8363c 100644
--- a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
+++ b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
@@ -8,12 +8,15 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/GSYM/FileEntry.h"
+#include "llvm/DebugInfo/GSYM/FileWriter.h"
#include "llvm/DebugInfo/GSYM/FunctionInfo.h"
#include "llvm/DebugInfo/GSYM/InlineInfo.h"
#include "llvm/DebugInfo/GSYM/Range.h"
#include "llvm/DebugInfo/GSYM/StringTable.h"
-#include "llvm/Testing/Support/Error.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Endian.h"
#include "gtest/gtest.h"
#include <string>
@@ -379,3 +382,118 @@ TEST(GSYMTest, TestStringTable) {
// Test pointing to past end gets empty string.
EXPECT_EQ(StrTab.getString(13), "");
}
+
+static void TestFileWriterHelper(llvm::support::endianness ByteOrder) {
+ SmallString<512> Str;
+ raw_svector_ostream OutStrm(Str);
+ FileWriter FW(OutStrm, ByteOrder);
+ const int64_t MinSLEB = INT64_MIN;
+ const int64_t MaxSLEB = INT64_MAX;
+ const uint64_t MinULEB = 0;
+ const uint64_t MaxULEB = UINT64_MAX;
+ const uint8_t U8 = 0x10;
+ const uint16_t U16 = 0x1122;
+ const uint32_t U32 = 0x12345678;
+ const uint64_t U64 = 0x33445566778899aa;
+ const char *Hello = "hello";
+ FW.writeU8(U8);
+ FW.writeU16(U16);
+ FW.writeU32(U32);
+ FW.writeU64(U64);
+ FW.alignTo(16);
+ const off_t FixupOffset = FW.tell();
+ FW.writeU32(0);
+ FW.writeSLEB(MinSLEB);
+ FW.writeSLEB(MaxSLEB);
+ FW.writeULEB(MinULEB);
+ FW.writeULEB(MaxULEB);
+ FW.writeNullTerminated(Hello);
+ // Test Seek, Tell using Fixup32.
+ FW.fixup32(U32, FixupOffset);
+
+ std::string Bytes(OutStrm.str());
+ uint8_t AddressSize = 4;
+ DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
+ uint64_t Offset = 0;
+ EXPECT_EQ(Data.getU8(&Offset), U8);
+ EXPECT_EQ(Data.getU16(&Offset), U16);
+ EXPECT_EQ(Data.getU32(&Offset), U32);
+ EXPECT_EQ(Data.getU64(&Offset), U64);
+ Offset = alignTo(Offset, 16);
+ EXPECT_EQ(Data.getU32(&Offset), U32);
+ EXPECT_EQ(Data.getSLEB128(&Offset), MinSLEB);
+ EXPECT_EQ(Data.getSLEB128(&Offset), MaxSLEB);
+ EXPECT_EQ(Data.getULEB128(&Offset), MinULEB);
+ EXPECT_EQ(Data.getULEB128(&Offset), MaxULEB);
+ EXPECT_EQ(Data.getCStrRef(&Offset), StringRef(Hello));
+}
+
+TEST(GSYMTest, TestFileWriter) {
+ TestFileWriterHelper(llvm::support::little);
+ TestFileWriterHelper(llvm::support::big);
+}
+
+TEST(GSYMTest, TestAddressRangeEncodeDecode) {
+ // Test encoding and decoding AddressRange objects. AddressRange objects
+ // are always stored as offsets from the a base address. The base address
+ // is the FunctionInfo's base address for function level ranges, and is
+ // the base address of the parent range for subranges.
+ SmallString<512> Str;
+ raw_svector_ostream OutStrm(Str);
+ const auto ByteOrder = llvm::support::endian::system_endianness();
+ FileWriter FW(OutStrm, ByteOrder);
+ const uint64_t BaseAddr = 0x1000;
+ const AddressRange Range1(0x1000, 0x1010);
+ const AddressRange Range2(0x1020, 0x1030);
+ Range1.encode(FW, BaseAddr);
+ Range2.encode(FW, BaseAddr);
+ std::string Bytes(OutStrm.str());
+ uint8_t AddressSize = 4;
+ DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
+
+ AddressRange DecodedRange1, DecodedRange2;
+ uint64_t Offset = 0;
+ DecodedRange1.decode(Data, BaseAddr, Offset);
+ DecodedRange2.decode(Data, BaseAddr, Offset);
+ EXPECT_EQ(Range1, DecodedRange1);
+ EXPECT_EQ(Range2, DecodedRange2);
+}
+
+static void TestAddressRangeEncodeDecodeHelper(const AddressRanges &Ranges,
+ const uint64_t BaseAddr) {
+ SmallString<512> Str;
+ raw_svector_ostream OutStrm(Str);
+ const auto ByteOrder = llvm::support::endian::system_endianness();
+ FileWriter FW(OutStrm, ByteOrder);
+ Ranges.encode(FW, BaseAddr);
+
+ std::string Bytes(OutStrm.str());
+ uint8_t AddressSize = 4;
+ DataExtractor Data(Bytes, ByteOrder == llvm::support::little, AddressSize);
+
+ AddressRanges DecodedRanges;
+ uint64_t Offset = 0;
+ DecodedRanges.decode(Data, BaseAddr, Offset);
+ EXPECT_EQ(Ranges, DecodedRanges);
+}
+
+TEST(GSYMTest, TestAddressRangesEncodeDecode) {
+ // Test encoding and decoding AddressRanges. AddressRanges objects contain
+ // ranges that are stored as offsets from the a base address. The base address
+ // is the FunctionInfo's base address for function level ranges, and is the
+ // base address of the parent range for subranges.
+ const uint64_t BaseAddr = 0x1000;
+
+ // Test encoding and decoding with no ranges.
+ AddressRanges Ranges;
+ TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
+
+ // Test encoding and decoding with 1 range.
+ Ranges.insert(AddressRange(0x1000, 0x1010));
+ TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
+
+ // Test encoding and decoding with multiple ranges.
+ Ranges.insert(AddressRange(0x1020, 0x1030));
+ Ranges.insert(AddressRange(0x1050, 0x1070));
+ TestAddressRangeEncodeDecodeHelper(Ranges, BaseAddr);
+}
OpenPOWER on IntegriCloud