forked from OSchip/llvm-project
Support 64-bit offsets in utility classes (1/5)
Using 64-bit offsets is required to fully implement 64-bit DWARF. As these classes are used in many different libraries they should temporarily support both 32- and 64-bit offsets. Differential Revision: https://reviews.llvm.org/D64006 llvm-svn: 368013
This commit is contained in:
parent
7b24dd741c
commit
f5f35c5cd1
|
@ -35,12 +35,12 @@ public:
|
|||
|
||||
/// Extracts a value and applies a relocation to the result if
|
||||
/// one exists for the given offset.
|
||||
uint64_t getRelocatedValue(uint32_t Size, uint32_t *Off,
|
||||
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off,
|
||||
uint64_t *SectionIndex = nullptr) const;
|
||||
|
||||
/// Extracts an address-sized value and applies a relocation to the result if
|
||||
/// one exists for the given offset.
|
||||
uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const {
|
||||
uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr) const {
|
||||
return getRelocatedValue(getAddressSize(), Off, SecIx);
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,23 @@ public:
|
|||
/// There is a DWARF encoding that uses a PC-relative adjustment.
|
||||
/// For these values, \p AbsPosOffset is used to fix them, which should
|
||||
/// reflect the absolute address of this pointer.
|
||||
Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
|
||||
Optional<uint64_t> getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
|
||||
uint64_t AbsPosOffset = 0) const;
|
||||
|
||||
size_t size() const { return Section == nullptr ? 0 : Section->Data.size(); }
|
||||
|
||||
// The following methods are temporarily kept in order to preserve
|
||||
// compatibility with existing code and migrate to 64-bit offsets smoothly.
|
||||
// They will be removed when the migration is finished.
|
||||
// Please do not use them in new code.
|
||||
uint64_t getRelocatedValue(uint32_t Size, uint32_t *Off,
|
||||
uint64_t *SectionIndex = nullptr) const;
|
||||
uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const {
|
||||
return getRelocatedValue(getAddressSize(), Off, SecIx);
|
||||
}
|
||||
Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
|
||||
uint64_t AbsPosOffset = 0) const;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -70,7 +70,7 @@ public:
|
|||
static DWARFFormValue createFromBlockValue(dwarf::Form F,
|
||||
ArrayRef<uint8_t> D);
|
||||
static DWARFFormValue createFromUnit(dwarf::Form F, const DWARFUnit *Unit,
|
||||
uint32_t *OffsetPtr);
|
||||
uint64_t *OffsetPtr);
|
||||
|
||||
dwarf::Form getForm() const { return Form; }
|
||||
uint64_t getRawUValue() const { return Value.uval; }
|
||||
|
@ -87,12 +87,12 @@ public:
|
|||
/// in \p FormParams is needed to interpret some forms. The optional
|
||||
/// \p Context and \p Unit allows extracting information if the form refers
|
||||
/// to other sections (e.g., .debug_str).
|
||||
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
|
||||
bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
|
||||
dwarf::FormParams FormParams,
|
||||
const DWARFContext *Context = nullptr,
|
||||
const DWARFUnit *Unit = nullptr);
|
||||
|
||||
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
|
||||
bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
|
||||
dwarf::FormParams FormParams, const DWARFUnit *U) {
|
||||
return extractValue(Data, OffsetPtr, FormParams, nullptr, U);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public:
|
|||
/// \param OffsetPtr A reference to the offset that will be updated.
|
||||
/// \param Params DWARF parameters to help interpret forms.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
|
||||
bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr,
|
||||
const dwarf::FormParams Params) const {
|
||||
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
|
||||
}
|
||||
|
@ -143,6 +143,28 @@ public:
|
|||
/// \param OffsetPtr A reference to the offset that will be updated.
|
||||
/// \param FormParams DWARF parameters to help interpret forms.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint64_t *OffsetPtr,
|
||||
const dwarf::FormParams FormParams);
|
||||
|
||||
// The following methods are temporarily kept in order to preserve
|
||||
// compatibility with existing code and migrate to 64-bit offsets smoothly.
|
||||
// They will be removed when the migration is finished.
|
||||
// Please do not use them in new code.
|
||||
static DWARFFormValue createFromUnit(dwarf::Form F, const DWARFUnit *Unit,
|
||||
uint32_t *OffsetPtr);
|
||||
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
|
||||
dwarf::FormParams FormParams,
|
||||
const DWARFContext *Context = nullptr,
|
||||
const DWARFUnit *Unit = nullptr);
|
||||
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
|
||||
dwarf::FormParams FormParams, const DWARFUnit *U) {
|
||||
return extractValue(Data, OffsetPtr, FormParams, nullptr, U);
|
||||
}
|
||||
bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
|
||||
const dwarf::FormParams Params) const {
|
||||
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
|
||||
}
|
||||
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint32_t *OffsetPtr,
|
||||
const dwarf::FormParams FormParams);
|
||||
|
|
|
@ -79,17 +79,17 @@ public:
|
|||
/// pointed to by \a offset_ptr is out of bounds, or if the
|
||||
/// offset plus the length of the C string is out of bounds,
|
||||
/// NULL will be returned.
|
||||
const char *getCStr(uint32_t *offset_ptr) const;
|
||||
const char *getCStr(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract a C string from \a *OffsetPtr.
|
||||
/// Extract a C string from \a *offset_ptr.
|
||||
///
|
||||
/// Returns a StringRef for the C String from the data at the offset
|
||||
/// pointed to by \a OffsetPtr. A variable length NULL terminated C
|
||||
/// string will be extracted and the \a OffsetPtr will be
|
||||
/// pointed to by \a offset_ptr. A variable length NULL terminated C
|
||||
/// string will be extracted and the \a offset_ptr will be
|
||||
/// updated with the offset of the byte that follows the NULL
|
||||
/// terminator byte.
|
||||
///
|
||||
/// \param[in,out] OffsetPtr
|
||||
/// \param[in,out] offset_ptr
|
||||
/// A pointer to an offset within the data that will be advanced
|
||||
/// by the appropriate number of bytes if the value is extracted
|
||||
/// correctly. If the offset is out of bounds or there are not
|
||||
|
@ -98,10 +98,10 @@ public:
|
|||
///
|
||||
/// \return
|
||||
/// A StringRef for the C string value in the data. If the offset
|
||||
/// pointed to by \a OffsetPtr is out of bounds, or if the
|
||||
/// pointed to by \a offset_ptr is out of bounds, or if the
|
||||
/// offset plus the length of the C string is out of bounds,
|
||||
/// a default-initialized StringRef will be returned.
|
||||
StringRef getCStrRef(uint32_t *OffsetPtr) const;
|
||||
StringRef getCStrRef(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract an unsigned integer of size \a byte_size from \a
|
||||
/// *offset_ptr.
|
||||
|
@ -127,7 +127,7 @@ public:
|
|||
/// @return
|
||||
/// The unsigned integer value that was extracted, or zero on
|
||||
/// failure.
|
||||
uint64_t getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const;
|
||||
uint64_t getUnsigned(uint64_t *offset_ptr, uint32_t byte_size) const;
|
||||
|
||||
/// Extract an signed integer of size \a byte_size from \a *offset_ptr.
|
||||
///
|
||||
|
@ -152,7 +152,7 @@ public:
|
|||
/// @return
|
||||
/// The sign extended signed integer value that was extracted,
|
||||
/// or zero on failure.
|
||||
int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const;
|
||||
int64_t getSigned(uint64_t *offset_ptr, uint32_t size) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Extract an pointer from \a *offset_ptr.
|
||||
|
@ -171,7 +171,7 @@ public:
|
|||
///
|
||||
/// @return
|
||||
/// The extracted pointer value as a 64 integer.
|
||||
uint64_t getAddress(uint32_t *offset_ptr) const {
|
||||
uint64_t getAddress(uint64_t *offset_ptr) const {
|
||||
return getUnsigned(offset_ptr, AddressSize);
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ public:
|
|||
///
|
||||
/// @return
|
||||
/// The extracted uint8_t value.
|
||||
uint8_t getU8(uint32_t *offset_ptr) const;
|
||||
uint8_t getU8(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract \a count uint8_t values from \a *offset_ptr.
|
||||
///
|
||||
|
@ -214,7 +214,7 @@ public:
|
|||
/// @return
|
||||
/// \a dst if all values were properly extracted and copied,
|
||||
/// NULL otherise.
|
||||
uint8_t *getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const;
|
||||
uint8_t *getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Extract a uint16_t value from \a *offset_ptr.
|
||||
|
@ -232,7 +232,7 @@ public:
|
|||
/// @return
|
||||
/// The extracted uint16_t value.
|
||||
//------------------------------------------------------------------
|
||||
uint16_t getU16(uint32_t *offset_ptr) const;
|
||||
uint16_t getU16(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract \a count uint16_t values from \a *offset_ptr.
|
||||
///
|
||||
|
@ -257,7 +257,7 @@ public:
|
|||
/// @return
|
||||
/// \a dst if all values were properly extracted and copied,
|
||||
/// NULL otherise.
|
||||
uint16_t *getU16(uint32_t *offset_ptr, uint16_t *dst, uint32_t count) const;
|
||||
uint16_t *getU16(uint64_t *offset_ptr, uint16_t *dst, uint32_t count) const;
|
||||
|
||||
/// Extract a 24-bit unsigned value from \a *offset_ptr and return it
|
||||
/// in a uint32_t.
|
||||
|
@ -274,7 +274,7 @@ public:
|
|||
///
|
||||
/// @return
|
||||
/// The extracted 24-bit value represented in a uint32_t.
|
||||
uint32_t getU24(uint32_t *offset_ptr) const;
|
||||
uint32_t getU24(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract a uint32_t value from \a *offset_ptr.
|
||||
///
|
||||
|
@ -290,7 +290,7 @@ public:
|
|||
///
|
||||
/// @return
|
||||
/// The extracted uint32_t value.
|
||||
uint32_t getU32(uint32_t *offset_ptr) const;
|
||||
uint32_t getU32(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract \a count uint32_t values from \a *offset_ptr.
|
||||
///
|
||||
|
@ -315,7 +315,7 @@ public:
|
|||
/// @return
|
||||
/// \a dst if all values were properly extracted and copied,
|
||||
/// NULL otherise.
|
||||
uint32_t *getU32(uint32_t *offset_ptr, uint32_t *dst, uint32_t count) const;
|
||||
uint32_t *getU32(uint64_t *offset_ptr, uint32_t *dst, uint32_t count) const;
|
||||
|
||||
/// Extract a uint64_t value from \a *offset_ptr.
|
||||
///
|
||||
|
@ -331,7 +331,7 @@ public:
|
|||
///
|
||||
/// @return
|
||||
/// The extracted uint64_t value.
|
||||
uint64_t getU64(uint32_t *offset_ptr) const;
|
||||
uint64_t getU64(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract \a count uint64_t values from \a *offset_ptr.
|
||||
///
|
||||
|
@ -356,7 +356,7 @@ public:
|
|||
/// @return
|
||||
/// \a dst if all values were properly extracted and copied,
|
||||
/// NULL otherise.
|
||||
uint64_t *getU64(uint32_t *offset_ptr, uint64_t *dst, uint32_t count) const;
|
||||
uint64_t *getU64(uint64_t *offset_ptr, uint64_t *dst, uint32_t count) const;
|
||||
|
||||
/// Extract a signed LEB128 value from \a *offset_ptr.
|
||||
///
|
||||
|
@ -374,7 +374,7 @@ public:
|
|||
///
|
||||
/// @return
|
||||
/// The extracted signed integer value.
|
||||
int64_t getSLEB128(uint32_t *offset_ptr) const;
|
||||
int64_t getSLEB128(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Extract a unsigned LEB128 value from \a *offset_ptr.
|
||||
///
|
||||
|
@ -392,21 +392,21 @@ public:
|
|||
///
|
||||
/// @return
|
||||
/// The extracted unsigned integer value.
|
||||
uint64_t getULEB128(uint32_t *offset_ptr) const;
|
||||
uint64_t getULEB128(uint64_t *offset_ptr) const;
|
||||
|
||||
/// Test the validity of \a offset.
|
||||
///
|
||||
/// @return
|
||||
/// \b true if \a offset is a valid offset into the data in this
|
||||
/// object, \b false otherwise.
|
||||
bool isValidOffset(uint32_t offset) const { return Data.size() > offset; }
|
||||
bool isValidOffset(uint64_t offset) const { return Data.size() > offset; }
|
||||
|
||||
/// Test the availability of \a length bytes of data from \a offset.
|
||||
///
|
||||
/// @return
|
||||
/// \b true if \a offset is a valid offset and there are \a
|
||||
/// length bytes available at that offset, \b false otherwise.
|
||||
bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const {
|
||||
bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const {
|
||||
return offset + length >= offset && isValidOffset(offset + length - 1);
|
||||
}
|
||||
|
||||
|
@ -417,9 +417,32 @@ public:
|
|||
/// \b true if \a offset is a valid offset and there are enough
|
||||
/// bytes for a pointer available at that offset, \b false
|
||||
/// otherwise.
|
||||
bool isValidOffsetForAddress(uint32_t offset) const {
|
||||
bool isValidOffsetForAddress(uint64_t offset) const {
|
||||
return isValidOffsetForDataOfSize(offset, AddressSize);
|
||||
}
|
||||
|
||||
// The following methods are temporarily kept in order to preserve
|
||||
// compatibility with existing code and migrate to 64-bit offsets smoothly.
|
||||
// They will be removed when the migration is finished.
|
||||
// Please do not use them in new code.
|
||||
const char *getCStr(uint32_t *offset_ptr) const;
|
||||
StringRef getCStrRef(uint32_t *offset_ptr) const;
|
||||
uint64_t getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const;
|
||||
int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const;
|
||||
uint64_t getAddress(uint32_t *offset_ptr) const {
|
||||
return getUnsigned(offset_ptr, AddressSize);
|
||||
}
|
||||
uint8_t getU8(uint32_t *offset_ptr) const;
|
||||
uint8_t *getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const;
|
||||
uint16_t getU16(uint32_t *offset_ptr) const;
|
||||
uint16_t *getU16(uint32_t *offset_ptr, uint16_t *dst, uint32_t count) const;
|
||||
uint32_t getU24(uint32_t *offset_ptr) const;
|
||||
uint32_t getU32(uint32_t *offset_ptr) const;
|
||||
uint32_t *getU32(uint32_t *offset_ptr, uint32_t *dst, uint32_t count) const;
|
||||
uint64_t getU64(uint32_t *offset_ptr) const;
|
||||
uint64_t *getU64(uint32_t *offset_ptr, uint64_t *dst, uint32_t count) const;
|
||||
int64_t getSLEB128(uint32_t *offset_ptr) const;
|
||||
uint64_t getULEB128(uint32_t *offset_ptr) const;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
using namespace llvm;
|
||||
|
||||
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
|
||||
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
|
||||
uint64_t *SecNdx) const {
|
||||
if (SecNdx)
|
||||
*SecNdx = object::SectionedAddress::UndefSection;
|
||||
|
@ -31,13 +31,13 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
|
|||
}
|
||||
|
||||
Optional<uint64_t>
|
||||
DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
|
||||
DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
|
||||
uint64_t PCRelOffset) const {
|
||||
if (Encoding == dwarf::DW_EH_PE_omit)
|
||||
return None;
|
||||
|
||||
uint64_t Result = 0;
|
||||
uint32_t OldOffset = *Offset;
|
||||
uint64_t OldOffset = *Offset;
|
||||
// First get value
|
||||
switch (Encoding & 0x0F) {
|
||||
case dwarf::DW_EH_PE_absptr:
|
||||
|
@ -97,3 +97,33 @@ DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
|
|||
|
||||
return Result;
|
||||
}
|
||||
|
||||
// The following is temporary code aimed to preserve compatibility with
|
||||
// existing code which uses 32-bit offsets.
|
||||
// It will be removed when migration to 64-bit offsets is finished.
|
||||
|
||||
namespace {
|
||||
|
||||
class WrapOffset {
|
||||
uint64_t Offset64;
|
||||
uint32_t *Offset32;
|
||||
|
||||
public:
|
||||
WrapOffset(uint32_t *Offset)
|
||||
: Offset64(*Offset), Offset32(Offset) {}
|
||||
~WrapOffset() { *Offset32 = Offset64; }
|
||||
operator uint64_t *() { return &Offset64; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
|
||||
uint64_t *SecNdx) const {
|
||||
return getRelocatedValue(Size, WrapOffset(Off), SecNdx);
|
||||
}
|
||||
|
||||
Optional<uint64_t>
|
||||
DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
|
||||
uint64_t PCRelOffset) const {
|
||||
return getEncodedPointer(WrapOffset(Offset), Encoding, PCRelOffset);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F,
|
|||
}
|
||||
|
||||
DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,
|
||||
uint32_t *OffsetPtr) {
|
||||
uint64_t *OffsetPtr) {
|
||||
DWARFFormValue FormValue(F);
|
||||
FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,
|
||||
U->getFormParams(), U);
|
||||
|
@ -106,7 +106,7 @@ DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,
|
|||
}
|
||||
|
||||
bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint32_t *OffsetPtr,
|
||||
uint64_t *OffsetPtr,
|
||||
const dwarf::FormParams Params) {
|
||||
bool Indirect = false;
|
||||
do {
|
||||
|
@ -234,7 +234,7 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
|
|||
}
|
||||
|
||||
bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
|
||||
uint32_t *OffsetPtr, dwarf::FormParams FP,
|
||||
uint64_t *OffsetPtr, dwarf::FormParams FP,
|
||||
const DWARFContext *Ctx,
|
||||
const DWARFUnit *CU) {
|
||||
if (!Ctx && CU)
|
||||
|
@ -590,7 +590,7 @@ Optional<const char *> DWARFFormValue::getAsCString() const {
|
|||
// FIXME: Add support for DW_FORM_GNU_strp_alt
|
||||
if (Form == DW_FORM_GNU_strp_alt || C == nullptr)
|
||||
return None;
|
||||
uint32_t Offset = Value.uval;
|
||||
uint64_t Offset = Value.uval;
|
||||
if (Form == DW_FORM_line_strp) {
|
||||
// .debug_line_str is tracked in the Context.
|
||||
if (const char *Str = C->getLineStringExtractor().getCStr(&Offset))
|
||||
|
@ -624,6 +624,7 @@ Optional<uint64_t> DWARFFormValue::getAsAddress() const {
|
|||
return SA->Address;
|
||||
return None;
|
||||
}
|
||||
|
||||
Optional<object::SectionedAddress>
|
||||
DWARFFormValue::getAsSectionedAddress() const {
|
||||
if (!isFormClass(FC_Address))
|
||||
|
@ -717,3 +718,40 @@ Optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
|
|||
return None;
|
||||
return Value.uval;
|
||||
}
|
||||
|
||||
// The following is temporary code aimed to preserve compatibility with
|
||||
// existing code which uses 32-bit offsets.
|
||||
// It will be removed when migration to 64-bit offsets is finished.
|
||||
|
||||
namespace {
|
||||
|
||||
class WrapOffset {
|
||||
uint64_t Offset64;
|
||||
uint32_t *Offset32;
|
||||
|
||||
public:
|
||||
WrapOffset(uint32_t *Offset)
|
||||
: Offset64(*Offset), Offset32(Offset) {}
|
||||
~WrapOffset() { *Offset32 = Offset64; }
|
||||
operator uint64_t *() { return &Offset64; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,
|
||||
uint32_t *OffsetPtr) {
|
||||
return createFromUnit(F, U, WrapOffset(OffsetPtr));
|
||||
}
|
||||
|
||||
bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint32_t *OffsetPtr,
|
||||
const dwarf::FormParams Params) {
|
||||
return skipValue(Form, DebugInfoData, WrapOffset(OffsetPtr), Params);
|
||||
}
|
||||
|
||||
bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
|
||||
uint32_t *OffsetPtr, dwarf::FormParams FP,
|
||||
const DWARFContext *Ctx,
|
||||
const DWARFUnit *CU) {
|
||||
return extractValue(Data, WrapOffset(OffsetPtr), FP, Ctx, CU);
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
using namespace llvm;
|
||||
|
||||
template <typename T>
|
||||
static T getU(uint32_t *offset_ptr, const DataExtractor *de,
|
||||
static T getU(uint64_t *offset_ptr, const DataExtractor *de,
|
||||
bool isLittleEndian, const char *Data) {
|
||||
T val = 0;
|
||||
uint32_t offset = *offset_ptr;
|
||||
uint64_t offset = *offset_ptr;
|
||||
if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) {
|
||||
std::memcpy(&val, &Data[offset], sizeof(val));
|
||||
if (sys::IsLittleEndianHost != isLittleEndian)
|
||||
|
@ -30,9 +30,9 @@ static T getU(uint32_t *offset_ptr, const DataExtractor *de,
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
|
||||
static T *getUs(uint64_t *offset_ptr, T *dst, uint32_t count,
|
||||
const DataExtractor *de, bool isLittleEndian, const char *Data){
|
||||
uint32_t offset = *offset_ptr;
|
||||
uint64_t offset = *offset_ptr;
|
||||
|
||||
if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) {
|
||||
for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
|
||||
|
@ -47,56 +47,55 @@ static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
|
||||
uint8_t DataExtractor::getU8(uint64_t *offset_ptr) const {
|
||||
return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data());
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
|
||||
DataExtractor::getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const {
|
||||
return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
|
||||
Data.data());
|
||||
}
|
||||
|
||||
|
||||
uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
|
||||
uint16_t DataExtractor::getU16(uint64_t *offset_ptr) const {
|
||||
return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data());
|
||||
}
|
||||
|
||||
uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
|
||||
uint16_t *DataExtractor::getU16(uint64_t *offset_ptr, uint16_t *dst,
|
||||
uint32_t count) const {
|
||||
return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
|
||||
Data.data());
|
||||
}
|
||||
|
||||
uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const {
|
||||
uint32_t DataExtractor::getU24(uint64_t *offset_ptr) const {
|
||||
uint24_t ExtractedVal =
|
||||
getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data());
|
||||
// The 3 bytes are in the correct byte order for the host.
|
||||
return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
|
||||
}
|
||||
|
||||
uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
|
||||
uint32_t DataExtractor::getU32(uint64_t *offset_ptr) const {
|
||||
return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data());
|
||||
}
|
||||
|
||||
uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
|
||||
uint32_t *DataExtractor::getU32(uint64_t *offset_ptr, uint32_t *dst,
|
||||
uint32_t count) const {
|
||||
return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
|
||||
Data.data());
|
||||
}
|
||||
|
||||
uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
|
||||
uint64_t DataExtractor::getU64(uint64_t *offset_ptr) const {
|
||||
return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data());
|
||||
}
|
||||
|
||||
uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
|
||||
uint64_t *DataExtractor::getU64(uint64_t *offset_ptr, uint64_t *dst,
|
||||
uint32_t count) const {
|
||||
return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
|
||||
Data.data());
|
||||
}
|
||||
|
||||
uint64_t
|
||||
DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
|
||||
DataExtractor::getUnsigned(uint64_t *offset_ptr, uint32_t byte_size) const {
|
||||
switch (byte_size) {
|
||||
case 1:
|
||||
return getU8(offset_ptr);
|
||||
|
@ -111,7 +110,7 @@ DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
|
|||
}
|
||||
|
||||
int64_t
|
||||
DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
|
||||
DataExtractor::getSigned(uint64_t *offset_ptr, uint32_t byte_size) const {
|
||||
switch (byte_size) {
|
||||
case 1:
|
||||
return (int8_t)getU8(offset_ptr);
|
||||
|
@ -125,8 +124,8 @@ DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
|
|||
llvm_unreachable("getSigned unhandled case!");
|
||||
}
|
||||
|
||||
const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
|
||||
uint32_t offset = *offset_ptr;
|
||||
const char *DataExtractor::getCStr(uint64_t *offset_ptr) const {
|
||||
uint64_t offset = *offset_ptr;
|
||||
StringRef::size_type pos = Data.find('\0', offset);
|
||||
if (pos != StringRef::npos) {
|
||||
*offset_ptr = pos + 1;
|
||||
|
@ -135,17 +134,17 @@ const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
StringRef DataExtractor::getCStrRef(uint32_t *OffsetPtr) const {
|
||||
uint32_t Start = *OffsetPtr;
|
||||
StringRef DataExtractor::getCStrRef(uint64_t *offset_ptr) const {
|
||||
uint64_t Start = *offset_ptr;
|
||||
StringRef::size_type Pos = Data.find('\0', Start);
|
||||
if (Pos != StringRef::npos) {
|
||||
*OffsetPtr = Pos + 1;
|
||||
*offset_ptr = Pos + 1;
|
||||
return StringRef(Data.data() + Start, Pos - Start);
|
||||
}
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
|
||||
uint64_t DataExtractor::getULEB128(uint64_t *offset_ptr) const {
|
||||
assert(*offset_ptr <= Data.size());
|
||||
|
||||
const char *error;
|
||||
|
@ -159,7 +158,7 @@ uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
|
||||
int64_t DataExtractor::getSLEB128(uint64_t *offset_ptr) const {
|
||||
assert(*offset_ptr <= Data.size());
|
||||
|
||||
const char *error;
|
||||
|
@ -172,3 +171,88 @@ int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
|
|||
*offset_ptr += bytes_read;
|
||||
return result;
|
||||
}
|
||||
|
||||
// The following is temporary code aimed to preserve compatibility with
|
||||
// existing code which uses 32-bit offsets.
|
||||
// It will be removed when migration to 64-bit offsets is finished.
|
||||
|
||||
namespace {
|
||||
|
||||
class WrapOffset {
|
||||
uint64_t offset64;
|
||||
uint32_t *offset32_ptr;
|
||||
|
||||
public:
|
||||
WrapOffset(uint32_t *offset_ptr)
|
||||
: offset64(*offset_ptr), offset32_ptr(offset_ptr) {}
|
||||
~WrapOffset() { *offset32_ptr = offset64; }
|
||||
operator uint64_t *() { return &offset64; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const {
|
||||
return getU8(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const {
|
||||
return getU8(WrapOffset(offset_ptr), dst, count);
|
||||
}
|
||||
|
||||
uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const {
|
||||
return getU16(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst,
|
||||
uint32_t count) const {
|
||||
return getU16(WrapOffset(offset_ptr), dst, count);
|
||||
}
|
||||
|
||||
uint32_t DataExtractor::getU24(uint32_t *offset_ptr) const {
|
||||
return getU24(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const {
|
||||
return getU32(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst,
|
||||
uint32_t count) const {
|
||||
return getU32(WrapOffset(offset_ptr), dst, count);
|
||||
}
|
||||
|
||||
uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const {
|
||||
return getU64(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst,
|
||||
uint32_t count) const {
|
||||
return getU64(WrapOffset(offset_ptr), dst, count);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const {
|
||||
return getUnsigned(WrapOffset(offset_ptr), byte_size);
|
||||
}
|
||||
|
||||
int64_t
|
||||
DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const {
|
||||
return getSigned(WrapOffset(offset_ptr), byte_size);
|
||||
}
|
||||
|
||||
const char *DataExtractor::getCStr(uint32_t *offset_ptr) const {
|
||||
return getCStr(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
StringRef DataExtractor::getCStrRef(uint32_t *offset_ptr) const {
|
||||
return getCStrRef(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
|
||||
return getULEB128(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
||||
int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
|
||||
return getSLEB128(WrapOffset(offset_ptr));
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ template<typename RawTypeT>
|
|||
DWARFFormValue createDataXFormValue(dwarf::Form Form, RawTypeT Value) {
|
||||
char Raw[sizeof(RawTypeT)];
|
||||
memcpy(Raw, &Value, sizeof(RawTypeT));
|
||||
uint32_t Offset = 0;
|
||||
uint64_t Offset = 0;
|
||||
DWARFFormValue Result(Form);
|
||||
DWARFDataExtractor Data(StringRef(Raw, sizeof(RawTypeT)),
|
||||
sys::IsLittleEndianHost, sizeof(void *));
|
||||
|
@ -53,7 +53,7 @@ DWARFFormValue createULEBFormValue(uint64_t Value) {
|
|||
SmallString<10> RawData;
|
||||
raw_svector_ostream OS(RawData);
|
||||
encodeULEB128(Value, OS);
|
||||
uint32_t Offset = 0;
|
||||
uint64_t Offset = 0;
|
||||
DWARFFormValue Result(DW_FORM_udata);
|
||||
DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *));
|
||||
Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32});
|
||||
|
@ -64,7 +64,7 @@ DWARFFormValue createSLEBFormValue(int64_t Value) {
|
|||
SmallString<10> RawData;
|
||||
raw_svector_ostream OS(RawData);
|
||||
encodeSLEB128(Value, OS);
|
||||
uint32_t Offset = 0;
|
||||
uint64_t Offset = 0;
|
||||
DWARFFormValue Result(DW_FORM_sdata);
|
||||
DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *));
|
||||
Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32});
|
||||
|
@ -112,7 +112,7 @@ TEST(DWARFFormValue, SignedConstantForms) {
|
|||
DWARFFormValue Data16(DW_FORM_data16);
|
||||
DWARFDataExtractor DE16(StringRef(Cksum, 16), sys::IsLittleEndianHost,
|
||||
sizeof(void *));
|
||||
uint32_t Offset = 0;
|
||||
uint64_t Offset = 0;
|
||||
Data16.extractValue(DE16, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32});
|
||||
SmallString<32> Str;
|
||||
raw_svector_ostream Res(Str);
|
||||
|
|
|
@ -12,19 +12,27 @@ using namespace llvm;
|
|||
|
||||
namespace {
|
||||
|
||||
// Test fixture
|
||||
template <typename T>
|
||||
class DataExtractorTest : public ::testing::Test { };
|
||||
|
||||
// Test DataExtractor with both types which can be used for offsets.
|
||||
typedef ::testing::Types<uint32_t, uint64_t> TestTypes;
|
||||
TYPED_TEST_CASE(DataExtractorTest, TestTypes);
|
||||
|
||||
const char numberData[] = "\x80\x90\xFF\xFF\x80\x00\x00\x00";
|
||||
const char stringData[] = "hellohello\0hello";
|
||||
const char leb128data[] = "\xA6\x49";
|
||||
const char bigleb128data[] = "\xAA\xA9\xFF\xAA\xFF\xAA\xFF\x4A";
|
||||
|
||||
TEST(DataExtractorTest, OffsetOverflow) {
|
||||
TYPED_TEST(DataExtractorTest, OffsetOverflow) {
|
||||
DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
|
||||
EXPECT_FALSE(DE.isValidOffsetForDataOfSize(-2U, 5));
|
||||
}
|
||||
|
||||
TEST(DataExtractorTest, UnsignedNumbers) {
|
||||
TYPED_TEST(DataExtractorTest, UnsignedNumbers) {
|
||||
DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
|
||||
uint32_t offset = 0;
|
||||
TypeParam offset = 0;
|
||||
|
||||
EXPECT_EQ(0x80U, DE.getU8(&offset));
|
||||
EXPECT_EQ(1U, offset);
|
||||
|
@ -70,9 +78,9 @@ TEST(DataExtractorTest, UnsignedNumbers) {
|
|||
EXPECT_EQ(8U, offset);
|
||||
}
|
||||
|
||||
TEST(DataExtractorTest, SignedNumbers) {
|
||||
TYPED_TEST(DataExtractorTest, SignedNumbers) {
|
||||
DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
|
||||
uint32_t offset = 0;
|
||||
TypeParam offset = 0;
|
||||
|
||||
EXPECT_EQ(-128, DE.getSigned(&offset, 1));
|
||||
EXPECT_EQ(1U, offset);
|
||||
|
@ -87,9 +95,9 @@ TEST(DataExtractorTest, SignedNumbers) {
|
|||
EXPECT_EQ(8U, offset);
|
||||
}
|
||||
|
||||
TEST(DataExtractorTest, Strings) {
|
||||
TYPED_TEST(DataExtractorTest, Strings) {
|
||||
DataExtractor DE(StringRef(stringData, sizeof(stringData)-1), false, 8);
|
||||
uint32_t offset = 0;
|
||||
TypeParam offset = 0;
|
||||
|
||||
EXPECT_EQ(stringData, DE.getCStr(&offset));
|
||||
EXPECT_EQ(11U, offset);
|
||||
|
@ -97,9 +105,9 @@ TEST(DataExtractorTest, Strings) {
|
|||
EXPECT_EQ(11U, offset);
|
||||
}
|
||||
|
||||
TEST(DataExtractorTest, LEB128) {
|
||||
TYPED_TEST(DataExtractorTest, LEB128) {
|
||||
DataExtractor DE(StringRef(leb128data, sizeof(leb128data)-1), false, 8);
|
||||
uint32_t offset = 0;
|
||||
TypeParam offset = 0;
|
||||
|
||||
EXPECT_EQ(9382ULL, DE.getULEB128(&offset));
|
||||
EXPECT_EQ(2U, offset);
|
||||
|
@ -116,9 +124,9 @@ TEST(DataExtractorTest, LEB128) {
|
|||
EXPECT_EQ(8U, offset);
|
||||
}
|
||||
|
||||
TEST(DataExtractorTest, LEB128_error) {
|
||||
TYPED_TEST(DataExtractorTest, LEB128_error) {
|
||||
DataExtractor DE(StringRef("\x81"), false, 8);
|
||||
uint32_t Offset = 0;
|
||||
TypeParam Offset = 0;
|
||||
EXPECT_EQ(0U, DE.getULEB128(&Offset));
|
||||
EXPECT_EQ(0U, Offset);
|
||||
|
||||
|
|
Loading…
Reference in New Issue