mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-01 10:02:42 +00:00
f5acbc29d8
In preparation for a follow on patch that improves DWARF parsing speed, clean up DWARFFormValue so that we have can get the fixed byte size of a form value given a DWARFUnit or given the version, address byte size and dwarf32/64. This patch cleans up code so that everyone is using one of the new DWARFFormValue functions: static Optional<uint8_t> DWARFFormValue::getFixedByteSize(dwarf::Form Form, const DWARFUnit *U = nullptr); static Optional<uint8_t> DWARFFormValue::getFixedByteSize(dwarf::Form Form, uint16_t Version, uint8_t AddrSize, bool Dwarf32); This patch changes DWARFFormValue::skipValue() to rely on the output of DWARFFormValue::getFixedByteSize(...) instead of duplicating the code in each function. This will reduce the number of changes we need to make to DWARF to fewer places in DWARFFormValue when we add support for new form. This patch also starts to support DWARF64 so that we can get correct byte sizes for forms that vary according the DWARF 32/64. To reduce the code duplication a new FormSizeHelper pure virtual class was created that can be created as a FormSizeHelperDWARFUnit when you have a DWARFUnit, or FormSizeHelperManual where you manually specify the DWARF version, address byte size and DWARF32/DWARF64. There is now a single implementation of a function that gets the fixed byte size (instead of two where one took a DWARFUnit and one took the DWARF version, address byte size and DWARFFormat enum) and one function to skip the form values. https://reviews.llvm.org/D26526 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286597 91177308-0d34-0410-b5e6-96231b3b80d8
157 lines
6.3 KiB
C++
157 lines
6.3 KiB
C++
//===- llvm/unittest/DebugInfo/DWARFFormValueTest.cpp ---------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/Support/Dwarf.h"
|
|
#include "llvm/Support/Host.h"
|
|
#include "llvm/Support/LEB128.h"
|
|
#include "gtest/gtest.h"
|
|
#include <climits>
|
|
using namespace llvm;
|
|
using namespace dwarf;
|
|
|
|
namespace {
|
|
|
|
TEST(DWARFFormValue, FixedFormSizes) {
|
|
Optional<uint8_t> RefSize;
|
|
Optional<uint8_t> AddrSize;
|
|
// Test 32 bit DWARF version 2 with 4 byte addresses.
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32);
|
|
AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_TRUE(AddrSize.hasValue());
|
|
EXPECT_EQ(*RefSize, *AddrSize);
|
|
|
|
// Test 32 bit DWARF version 2 with 8 byte addresses.
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32);
|
|
AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_TRUE(AddrSize.hasValue());
|
|
EXPECT_EQ(*RefSize, *AddrSize);
|
|
|
|
// DW_FORM_ref_addr is 4 bytes in DWARF 32 in DWARF version 3 and beyond.
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 4, DWARF32);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_EQ(*RefSize, 4);
|
|
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 4, DWARF32);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_EQ(*RefSize, 4);
|
|
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 4, DWARF32);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_EQ(*RefSize, 4);
|
|
|
|
// DW_FORM_ref_addr is 8 bytes in DWARF 64 in DWARF version 3 and beyond.
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 8, DWARF64);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_EQ(*RefSize, 8);
|
|
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 8, DWARF64);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_EQ(*RefSize, 8);
|
|
|
|
RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 8, DWARF64);
|
|
EXPECT_TRUE(RefSize.hasValue());
|
|
EXPECT_EQ(*RefSize, 8);
|
|
}
|
|
|
|
bool isFormClass(dwarf::Form Form, DWARFFormValue::FormClass FC) {
|
|
return DWARFFormValue(Form).isFormClass(FC);
|
|
}
|
|
|
|
TEST(DWARFFormValue, FormClass) {
|
|
EXPECT_TRUE(isFormClass(DW_FORM_addr, DWARFFormValue::FC_Address));
|
|
EXPECT_FALSE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Address));
|
|
EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Constant));
|
|
EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_SectionOffset));
|
|
EXPECT_TRUE(
|
|
isFormClass(DW_FORM_sec_offset, DWARFFormValue::FC_SectionOffset));
|
|
EXPECT_TRUE(isFormClass(DW_FORM_GNU_str_index, DWARFFormValue::FC_String));
|
|
EXPECT_TRUE(isFormClass(DW_FORM_GNU_addr_index, DWARFFormValue::FC_Address));
|
|
EXPECT_FALSE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Address));
|
|
EXPECT_TRUE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Reference));
|
|
EXPECT_TRUE(isFormClass(DW_FORM_ref_sig8, DWARFFormValue::FC_Reference));
|
|
}
|
|
|
|
template<typename RawTypeT>
|
|
DWARFFormValue createDataXFormValue(dwarf::Form Form, RawTypeT Value) {
|
|
char Raw[sizeof(RawTypeT)];
|
|
memcpy(Raw, &Value, sizeof(RawTypeT));
|
|
uint32_t Offset = 0;
|
|
DWARFFormValue Result(Form);
|
|
DataExtractor Data(StringRef(Raw, sizeof(RawTypeT)),
|
|
sys::IsLittleEndianHost, sizeof(void*));
|
|
Result.extractValue(Data, &Offset, nullptr);
|
|
return Result;
|
|
}
|
|
|
|
DWARFFormValue createULEBFormValue(uint64_t Value) {
|
|
SmallString<10> RawData;
|
|
raw_svector_ostream OS(RawData);
|
|
encodeULEB128(Value, OS);
|
|
uint32_t Offset = 0;
|
|
DWARFFormValue Result(DW_FORM_udata);
|
|
DataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void*));
|
|
Result.extractValue(Data, &Offset, nullptr);
|
|
return Result;
|
|
}
|
|
|
|
DWARFFormValue createSLEBFormValue(int64_t Value) {
|
|
SmallString<10> RawData;
|
|
raw_svector_ostream OS(RawData);
|
|
encodeSLEB128(Value, OS);
|
|
uint32_t Offset = 0;
|
|
DWARFFormValue Result(DW_FORM_sdata);
|
|
DataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void*));
|
|
Result.extractValue(Data, &Offset, nullptr);
|
|
return Result;
|
|
}
|
|
|
|
TEST(DWARFFormValue, SignedConstantForms) {
|
|
// Check that we correctly sign extend fixed size forms.
|
|
auto Sign1 = createDataXFormValue<uint8_t>(DW_FORM_data1, -123);
|
|
auto Sign2 = createDataXFormValue<uint16_t>(DW_FORM_data2, -12345);
|
|
auto Sign4 = createDataXFormValue<uint32_t>(DW_FORM_data4, -123456789);
|
|
auto Sign8 = createDataXFormValue<uint64_t>(DW_FORM_data8, -1);
|
|
EXPECT_EQ(Sign1.getAsSignedConstant().getValue(), -123);
|
|
EXPECT_EQ(Sign2.getAsSignedConstant().getValue(), -12345);
|
|
EXPECT_EQ(Sign4.getAsSignedConstant().getValue(), -123456789);
|
|
EXPECT_EQ(Sign8.getAsSignedConstant().getValue(), -1);
|
|
|
|
// Check that we can handle big positive values, but that we return
|
|
// an error just over the limit.
|
|
auto UMax = createULEBFormValue(LLONG_MAX);
|
|
auto TooBig = createULEBFormValue(uint64_t(LLONG_MAX) + 1);
|
|
EXPECT_EQ(UMax.getAsSignedConstant().getValue(), LLONG_MAX);
|
|
EXPECT_EQ(TooBig.getAsSignedConstant().hasValue(), false);
|
|
|
|
// Sanity check some other forms.
|
|
auto Data1 = createDataXFormValue<uint8_t>(DW_FORM_data1, 120);
|
|
auto Data2 = createDataXFormValue<uint16_t>(DW_FORM_data2, 32000);
|
|
auto Data4 = createDataXFormValue<uint32_t>(DW_FORM_data4, 2000000000);
|
|
auto Data8 = createDataXFormValue<uint64_t>(DW_FORM_data8, 0x1234567812345678LL);
|
|
auto LEBMin = createSLEBFormValue(LLONG_MIN);
|
|
auto LEBMax = createSLEBFormValue(LLONG_MAX);
|
|
auto LEB1 = createSLEBFormValue(-42);
|
|
auto LEB2 = createSLEBFormValue(42);
|
|
EXPECT_EQ(Data1.getAsSignedConstant().getValue(), 120);
|
|
EXPECT_EQ(Data2.getAsSignedConstant().getValue(), 32000);
|
|
EXPECT_EQ(Data4.getAsSignedConstant().getValue(), 2000000000);
|
|
EXPECT_EQ(Data8.getAsSignedConstant().getValue(), 0x1234567812345678LL);
|
|
EXPECT_EQ(LEBMin.getAsSignedConstant().getValue(), LLONG_MIN);
|
|
EXPECT_EQ(LEBMax.getAsSignedConstant().getValue(), LLONG_MAX);
|
|
EXPECT_EQ(LEB1.getAsSignedConstant().getValue(), -42);
|
|
EXPECT_EQ(LEB2.getAsSignedConstant().getValue(), 42);
|
|
}
|
|
|
|
} // end anonymous namespace
|