[DebugInfo] add SectionedAddress to DebugInfo interfaces.

That patch is the fix for https://bugs.llvm.org/show_bug.cgi?id=40703
   "wrong line number info for obj file compiled with -ffunction-sections"
   bug. The problem happened with only .o files. If object file contains
   several .text sections then line number information showed incorrectly.
   The reason for this is that DwarfLineTable could not detect section which
   corresponds to specified address(because address is the local to the
   section). And as the result it could not select proper sequence in the
   line table. The fix is to pass SectionIndex with the address. So that it
   would be possible to differentiate addresses from various sections. With
   this fix llvm-objdump shows correct line numbers for disassembled code.

   Differential review: https://reviews.llvm.org/D58194

llvm-svn: 354972
This commit is contained in:
Alexey Lapshin 2019-02-27 13:17:36 +00:00
parent ef92035827
commit 77fc1f6049
45 changed files with 796 additions and 329 deletions

View File

@ -205,14 +205,25 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *S,
uint64_t Offset) { uint64_t Offset) {
llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); }); llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });
// Detect SectionIndex for specified section.
uint64_t SectionIndex = object::SectionedAddress::UndefSection;
ArrayRef<InputSectionBase *> Sections = S->File->getSections();
for (uint64_t CurIndex = 0; CurIndex < Sections.size(); ++CurIndex) {
if (S == Sections[CurIndex]) {
SectionIndex = CurIndex;
break;
}
}
// Use fake address calcuated by adding section file offset and offset in // Use fake address calcuated by adding section file offset and offset in
// section. See comments for ObjectInfo class. // section. See comments for ObjectInfo class.
DILineInfo Info; DILineInfo Info;
for (const llvm::DWARFDebugLine::LineTable *LT : LineTables) for (const llvm::DWARFDebugLine::LineTable *LT : LineTables) {
if (LT->getFileLineInfoForAddress( if (LT->getFileLineInfoForAddress(
S->getOffsetInFile() + Offset, nullptr, {S->getOffsetInFile() + Offset, SectionIndex}, nullptr,
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info)) DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info))
return Info; return Info;
}
return None; return None;
} }

View File

@ -203,11 +203,14 @@ public:
return true; return true;
} }
virtual DILineInfo getLineInfoForAddress(uint64_t Address, virtual DILineInfo getLineInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, virtual DILineInfoTable getLineInfoForAddressRange(
uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; object::SectionedAddress Address, uint64_t Size,
virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DIInliningInfo getInliningInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
private: private:

View File

@ -317,13 +317,18 @@ public:
/// Get the compilation unit, the function DIE and lexical block DIE for the /// Get the compilation unit, the function DIE and lexical block DIE for the
/// given address where applicable. /// given address where applicable.
/// TODO: change input parameter from "uint64_t Address"
/// into "SectionedAddress Address"
DIEsForAddress getDIEsForAddress(uint64_t Address); DIEsForAddress getDIEsForAddress(uint64_t Address);
DILineInfo getLineInfoForAddress(uint64_t Address, DILineInfo getLineInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, DILineInfoTable getLineInfoForAddressRange(
object::SectionedAddress Address, uint64_t Size,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DIInliningInfo getInliningInfoForAddress(uint64_t Address, DIInliningInfo getInliningInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
bool isLittleEndian() const { return DObj->isLittleEndian(); } bool isLittleEndian() const { return DObj->isLittleEndian(); }
@ -366,6 +371,8 @@ public:
private: private:
/// Return the compile unit which contains instruction with provided /// Return the compile unit which contains instruction with provided
/// address. /// address.
/// TODO: change input parameter from "uint64_t Address"
/// into "SectionedAddress Address"
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
}; };

View File

@ -139,12 +139,16 @@ public:
static void dumpTableHeader(raw_ostream &OS); static void dumpTableHeader(raw_ostream &OS);
static bool orderByAddress(const Row &LHS, const Row &RHS) { static bool orderByAddress(const Row &LHS, const Row &RHS) {
return LHS.Address < RHS.Address; return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) <
std::tie(RHS.Address.SectionIndex, RHS.Address.Address);
} }
/// The program-counter value corresponding to a machine instruction /// The program-counter value corresponding to a machine instruction
/// generated by the compiler. /// generated by the compiler and section index pointing to the section
uint64_t Address; /// containg this PC. If relocation information is present then section
/// index is the index of the section which contains above address.
/// Otherwise this is object::SectionedAddress::Undef value.
object::SectionedAddress Address;
/// An unsigned integer indicating a source line number. Lines are numbered /// An unsigned integer indicating a source line number. Lines are numbered
/// beginning at 1. The compiler may emit the value 0 in cases where an /// beginning at 1. The compiler may emit the value 0 in cases where an
/// instruction cannot be attributed to any source line. /// instruction cannot be attributed to any source line.
@ -192,6 +196,10 @@ public:
/// and is described by line table rows [FirstRowIndex, LastRowIndex). /// and is described by line table rows [FirstRowIndex, LastRowIndex).
uint64_t LowPC; uint64_t LowPC;
uint64_t HighPC; uint64_t HighPC;
/// If relocation information is present then this is the index of the
/// section which contains above addresses. Otherwise this is
/// object::SectionedAddress::Undef value.
uint64_t SectionIndex;
unsigned FirstRowIndex; unsigned FirstRowIndex;
unsigned LastRowIndex; unsigned LastRowIndex;
bool Empty; bool Empty;
@ -199,14 +207,18 @@ public:
void reset(); void reset();
static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) { static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) {
return LHS.LowPC < RHS.LowPC; return std::tie(LHS.SectionIndex, LHS.LowPC) <
std::tie(RHS.SectionIndex, RHS.LowPC);
} }
bool isValid() const { bool isValid() const {
return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex);
} }
bool containsPC(uint64_t PC) const { return (LowPC <= PC && PC < HighPC); } bool containsPC(object::SectionedAddress PC) const {
return SectionIndex == PC.SectionIndex &&
(LowPC <= PC.Address && PC.Address < HighPC);
}
}; };
struct LineTable { struct LineTable {
@ -223,9 +235,9 @@ public:
/// Returns the index of the row with file/line info for a given address, /// Returns the index of the row with file/line info for a given address,
/// or UnknownRowIndex if there is no such row. /// or UnknownRowIndex if there is no such row.
uint32_t lookupAddress(uint64_t Address) const; uint32_t lookupAddress(object::SectionedAddress Address) const;
bool lookupAddressRange(uint64_t Address, uint64_t Size, bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size,
std::vector<uint32_t> &Result) const; std::vector<uint32_t> &Result) const;
bool hasFileAtIndex(uint64_t FileIndex) const; bool hasFileAtIndex(uint64_t FileIndex) const;
@ -238,7 +250,8 @@ public:
/// Fills the Result argument with the file and line information /// Fills the Result argument with the file and line information
/// corresponding to Address. Returns true on success. /// corresponding to Address. Returns true on success.
bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, bool getFileLineInfoForAddress(object::SectionedAddress Address,
const char *CompDir,
DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfoSpecifier::FileLineInfoKind Kind,
DILineInfo &Result) const; DILineInfo &Result) const;
@ -263,10 +276,15 @@ public:
private: private:
uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
uint64_t Address) const; object::SectionedAddress Address) const;
Optional<StringRef> Optional<StringRef>
getSourceByIndex(uint64_t FileIndex, getSourceByIndex(uint64_t FileIndex,
DILineInfoSpecifier::FileLineInfoKind Kind) const; DILineInfoSpecifier::FileLineInfoKind Kind) const;
uint32_t lookupAddressImpl(object::SectionedAddress Address) const;
bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size,
std::vector<uint32_t> &Result) const;
}; };
const LineTable *getLineTable(uint32_t Offset) const; const LineTable *getLineTable(uint32_t Offset) const;

View File

@ -76,7 +76,7 @@ public:
/// list. Has to be passed base address of the compile unit referencing this /// list. Has to be passed base address of the compile unit referencing this
/// range list. /// range list.
DWARFAddressRangesVector DWARFAddressRangesVector
getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr) const; getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr) const;
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -37,7 +37,7 @@ struct RangeListEntry : public DWARFListEntryBase {
Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr);
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
uint64_t &CurrentBase, DIDumpOptions DumpOpts, uint64_t &CurrentBase, DIDumpOptions DumpOpts,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)> llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress) const; LookupPooledAddress) const;
bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; }
}; };
@ -47,7 +47,7 @@ class DWARFDebugRnglist : public DWARFListType<RangeListEntry> {
public: public:
/// Build a DWARFAddressRangesVector from a rangelist. /// Build a DWARFAddressRangesVector from a rangelist.
DWARFAddressRangesVector DWARFAddressRangesVector
getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr,
DWARFUnit &U) const; DWARFUnit &U) const;
}; };

View File

@ -79,7 +79,7 @@ public:
const DWARFUnit *getUnit() const { return U; } const DWARFUnit *getUnit() const { return U; }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const;
void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts,
SectionedAddress SA) const; object::SectionedAddress SA) const;
static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,
DIDumpOptions DumpOpts, uint64_t SectionIndex); DIDumpOptions DumpOpts, uint64_t SectionIndex);
@ -108,7 +108,7 @@ public:
Optional<int64_t> getAsSignedConstant() const; Optional<int64_t> getAsSignedConstant() const;
Optional<const char *> getAsCString() const; Optional<const char *> getAsCString() const;
Optional<uint64_t> getAsAddress() const; Optional<uint64_t> getAsAddress() const;
Optional<SectionedAddress> getAsSectionedAddress() const; Optional<object::SectionedAddress> getAsSectionedAddress() const;
Optional<uint64_t> getAsSectionOffset() const; Optional<uint64_t> getAsSectionOffset() const;
Optional<ArrayRef<uint8_t>> getAsBlock() const; Optional<ArrayRef<uint8_t>> getAsBlock() const;
Optional<uint64_t> getAsCStringOffset() const; Optional<uint64_t> getAsCStringOffset() const;
@ -246,7 +246,7 @@ inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue> &V) {
return None; return None;
} }
inline Optional<SectionedAddress> inline Optional<object::SectionedAddress>
toSectionedAddress(const Optional<DWARFFormValue> &V) { toSectionedAddress(const Optional<DWARFFormValue> &V) {
if (V) if (V)
return V->getAsSectionedAddress(); return V->getAsSectionedAddress();

View File

@ -157,7 +157,7 @@ public:
uint8_t getAddrSize() const { return Header.getAddrSize(); } uint8_t getAddrSize() const { return Header.getAddrSize(); }
void dump(raw_ostream &OS, void dump(raw_ostream &OS,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)> llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress, LookupPooledAddress,
DIDumpOptions DumpOpts = {}) const; DIDumpOptions DumpOpts = {}) const;
@ -234,7 +234,7 @@ Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
template <typename DWARFListType> template <typename DWARFListType>
void DWARFListTableBase<DWARFListType>::dump( void DWARFListTableBase<DWARFListType>::dump(
raw_ostream &OS, raw_ostream &OS,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)> llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress, LookupPooledAddress,
DIDumpOptions DumpOpts) const { DIDumpOptions DumpOpts) const {
Header.dump(OS, DumpOpts); Header.dump(OS, DumpOpts);

View File

@ -22,11 +22,6 @@ struct SectionName {
bool IsNameUnique; bool IsNameUnique;
}; };
struct SectionedAddress {
uint64_t Address;
uint64_t SectionIndex;
};
} // end namespace llvm } // end namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H #endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H

View File

@ -217,7 +217,7 @@ class DWARFUnit {
Optional<DWARFDebugRnglistTable> RngListTable; Optional<DWARFDebugRnglistTable> RngListTable;
mutable const DWARFAbbreviationDeclarationSet *Abbrevs; mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
llvm::Optional<SectionedAddress> BaseAddr; llvm::Optional<object::SectionedAddress> BaseAddr;
/// The compile unit debug information entry items. /// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray; std::vector<DWARFDebugInfoEntry> DieArray;
@ -304,7 +304,8 @@ public:
RangeSectionBase = Base; RangeSectionBase = Base;
} }
Optional<SectionedAddress> getAddrOffsetSectionItem(uint32_t Index) const; Optional<object::SectionedAddress>
getAddrOffsetSectionItem(uint32_t Index) const;
Optional<uint64_t> getStringOffsetSectionItem(uint32_t Index) const; Optional<uint64_t> getStringOffsetSectionItem(uint32_t Index) const;
DWARFDataExtractor getDebugInfoExtractor() const; DWARFDataExtractor getDebugInfoExtractor() const;
@ -375,7 +376,7 @@ public:
llvm_unreachable("Invalid UnitType."); llvm_unreachable("Invalid UnitType.");
} }
llvm::Optional<SectionedAddress> getBaseAddress(); llvm::Optional<object::SectionedAddress> getBaseAddress();
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
extractDIEsIfNeeded(ExtractUnitDIEOnly); extractDIEsIfNeeded(ExtractUnitDIEOnly);

View File

@ -43,13 +43,13 @@ namespace pdb {
void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override; void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override;
DILineInfo getLineInfoForAddress( DILineInfo getLineInfoForAddress(
uint64_t Address, object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DILineInfoTable getLineInfoForAddressRange( DILineInfoTable getLineInfoForAddressRange(
uint64_t Address, uint64_t Size, object::SectionedAddress Address, uint64_t Size,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DIInliningInfo getInliningInfoForAddress( DIInliningInfo getInliningInfoForAddress(
uint64_t Address, object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
private: private:

View File

@ -24,13 +24,14 @@ class SymbolizableModule {
public: public:
virtual ~SymbolizableModule() = default; virtual ~SymbolizableModule() = default;
virtual DILineInfo symbolizeCode(uint64_t ModuleOffset, virtual DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset,
FunctionNameKind FNKind, FunctionNameKind FNKind,
bool UseSymbolTable) const = 0; bool UseSymbolTable) const = 0;
virtual DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset, virtual DIInliningInfo
FunctionNameKind FNKind, symbolizeInlinedCode(object::SectionedAddress ModuleOffset,
bool UseSymbolTable) const = 0; FunctionNameKind FNKind, bool UseSymbolTable) const = 0;
virtual DIGlobal symbolizeData(uint64_t ModuleOffset) const = 0; virtual DIGlobal
symbolizeData(object::SectionedAddress ModuleOffset) const = 0;
// Return true if this is a 32-bit x86 PE COFF module. // Return true if this is a 32-bit x86 PE COFF module.
virtual bool isWin32Module() const = 0; virtual bool isWin32Module() const = 0;

View File

@ -60,13 +60,14 @@ public:
} }
Expected<DILineInfo> symbolizeCode(const std::string &ModuleName, Expected<DILineInfo> symbolizeCode(const std::string &ModuleName,
uint64_t ModuleOffset, object::SectionedAddress ModuleOffset,
StringRef DWPName = ""); StringRef DWPName = "");
Expected<DIInliningInfo> symbolizeInlinedCode(const std::string &ModuleName, Expected<DIInliningInfo>
uint64_t ModuleOffset, symbolizeInlinedCode(const std::string &ModuleName,
StringRef DWPName = ""); object::SectionedAddress ModuleOffset,
StringRef DWPName = "");
Expected<DIGlobal> symbolizeData(const std::string &ModuleName, Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
uint64_t ModuleOffset); object::SectionedAddress ModuleOffset);
void flush(); void flush();
static std::string static std::string

View File

@ -135,6 +135,30 @@ public:
const ObjectFile *getObject() const; const ObjectFile *getObject() const;
}; };
struct SectionedAddress {
// TODO: constructors could be removed when C++14 would be adopted.
SectionedAddress() {}
SectionedAddress(uint64_t Addr, uint64_t SectIdx)
: Address(Addr), SectionIndex(SectIdx) {}
const static uint64_t UndefSection = UINT64_MAX;
uint64_t Address = 0;
uint64_t SectionIndex = UndefSection;
};
inline bool operator<(const SectionedAddress &LHS,
const SectionedAddress &RHS) {
return std::tie(LHS.SectionIndex, LHS.Address) <
std::tie(RHS.SectionIndex, RHS.Address);
}
inline bool operator==(const SectionedAddress &LHS,
const SectionedAddress &RHS) {
return std::tie(LHS.SectionIndex, LHS.Address) ==
std::tie(RHS.SectionIndex, RHS.Address);
}
/// This is a value type class that represents a single symbol in the list of /// This is a value type class that represents a single symbol in the list of
/// symbols in the object file. /// symbols in the object file.
class SymbolRef : public BasicSymbolRef { class SymbolRef : public BasicSymbolRef {

View File

@ -268,11 +268,11 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
} }
// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
static void static void dumpRnglistsSection(
dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, raw_ostream &OS, DWARFDataExtractor &rnglistData,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)> llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress, LookupPooledAddress,
DIDumpOptions DumpOpts) { DIDumpOptions DumpOpts) {
uint32_t Offset = 0; uint32_t Offset = 0;
while (rnglistData.isValidOffset(Offset)) { while (rnglistData.isValidOffset(Offset)) {
llvm::DWARFDebugRnglistTable Rnglists; llvm::DWARFDebugRnglistTable Rnglists;
@ -938,6 +938,8 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) {
return Result; return Result;
} }
/// TODO: change input parameter from "uint64_t Address"
/// into "SectionedAddress Address"
static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
uint64_t Address, uint64_t Address,
FunctionNameKind Kind, FunctionNameKind Kind,
@ -966,36 +968,37 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
return FoundResult; return FoundResult;
} }
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Spec) { DILineInfoSpecifier Spec) {
DILineInfo Result; DILineInfo Result;
DWARFCompileUnit *CU = getCompileUnitForAddress(Address); DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
if (!CU) if (!CU)
return Result; return Result;
getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind,
Result.FunctionName, getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
Result.StartLine); Result.FunctionName, Result.StartLine);
if (Spec.FLIKind != FileLineInfoKind::None) { if (Spec.FLIKind != FileLineInfoKind::None) {
if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), LineTable->getFileLineInfoForAddress(
Spec.FLIKind, Result); {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
Spec.FLIKind, Result);
}
} }
return Result; return Result;
} }
DILineInfoTable DILineInfoTable DWARFContext::getLineInfoForAddressRange(
DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {
DILineInfoSpecifier Spec) {
DILineInfoTable Lines; DILineInfoTable Lines;
DWARFCompileUnit *CU = getCompileUnitForAddress(Address); DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
if (!CU) if (!CU)
return Lines; return Lines;
std::string FunctionName = "<invalid>"; std::string FunctionName = "<invalid>";
uint32_t StartLine = 0; uint32_t StartLine = 0;
getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName, getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
StartLine); FunctionName, StartLine);
// If the Specifier says we don't need FileLineInfo, just // If the Specifier says we don't need FileLineInfo, just
// return the top-most function at the starting address. // return the top-most function at the starting address.
@ -1003,7 +1006,7 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
DILineInfo Result; DILineInfo Result;
Result.FunctionName = FunctionName; Result.FunctionName = FunctionName;
Result.StartLine = StartLine; Result.StartLine = StartLine;
Lines.push_back(std::make_pair(Address, Result)); Lines.push_back(std::make_pair(Address.Address, Result));
return Lines; return Lines;
} }
@ -1011,8 +1014,10 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
// Get the index of row we're looking for in the line table. // Get the index of row we're looking for in the line table.
std::vector<uint32_t> RowVector; std::vector<uint32_t> RowVector;
if (!LineTable->lookupAddressRange(Address, Size, RowVector)) if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
Size, RowVector)) {
return Lines; return Lines;
}
for (uint32_t RowIndex : RowVector) { for (uint32_t RowIndex : RowVector) {
// Take file number and line/column from the row. // Take file number and line/column from the row.
@ -1024,33 +1029,33 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
Result.Line = Row.Line; Result.Line = Row.Line;
Result.Column = Row.Column; Result.Column = Row.Column;
Result.StartLine = StartLine; Result.StartLine = StartLine;
Lines.push_back(std::make_pair(Row.Address, Result)); Lines.push_back(std::make_pair(Row.Address.Address, Result));
} }
return Lines; return Lines;
} }
DIInliningInfo DIInliningInfo
DWARFContext::getInliningInfoForAddress(uint64_t Address, DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Spec) { DILineInfoSpecifier Spec) {
DIInliningInfo InliningInfo; DIInliningInfo InliningInfo;
DWARFCompileUnit *CU = getCompileUnitForAddress(Address); DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
if (!CU) if (!CU)
return InliningInfo; return InliningInfo;
const DWARFLineTable *LineTable = nullptr; const DWARFLineTable *LineTable = nullptr;
SmallVector<DWARFDie, 4> InlinedChain; SmallVector<DWARFDie, 4> InlinedChain;
CU->getInlinedChainForAddress(Address, InlinedChain); CU->getInlinedChainForAddress(Address.Address, InlinedChain);
if (InlinedChain.size() == 0) { if (InlinedChain.size() == 0) {
// If there is no DIE for address (e.g. it is in unavailable .dwo file), // If there is no DIE for address (e.g. it is in unavailable .dwo file),
// try to at least get file/line info from symbol table. // try to at least get file/line info from symbol table.
if (Spec.FLIKind != FileLineInfoKind::None) { if (Spec.FLIKind != FileLineInfoKind::None) {
DILineInfo Frame; DILineInfo Frame;
LineTable = getLineTableForUnit(CU); LineTable = getLineTableForUnit(CU);
if (LineTable && if (LineTable && LineTable->getFileLineInfoForAddress(
LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), {Address.Address, Address.SectionIndex},
Spec.FLIKind, Frame)) CU->getCompilationDir(), Spec.FLIKind, Frame))
InliningInfo.addFrame(Frame); InliningInfo.addFrame(Frame);
} }
return InliningInfo; return InliningInfo;
@ -1072,8 +1077,9 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
LineTable = getLineTableForUnit(CU); LineTable = getLineTableForUnit(CU);
// For the topmost routine, get file/line info from line table. // For the topmost routine, get file/line info from line table.
if (LineTable) if (LineTable)
LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), LineTable->getFileLineInfoForAddress(
Spec.FLIKind, Frame); {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
Spec.FLIKind, Frame);
} else { } else {
// Otherwise, use call file, call line and call column from // Otherwise, use call file, call line and call column from
// previous DIE in inlined chain. // previous DIE in inlined chain.

View File

@ -15,7 +15,7 @@ using namespace llvm;
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
uint64_t *SecNdx) const { uint64_t *SecNdx) const {
if (SecNdx) if (SecNdx)
*SecNdx = -1ULL; *SecNdx = object::SectionedAddress::UndefSection;
if (!Section) if (!Section)
return getUnsigned(Off, Size); return getUnsigned(Off, Size);
Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off); Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off);

View File

@ -353,7 +353,8 @@ void DWARFDebugLine::Row::postAppend() {
} }
void DWARFDebugLine::Row::reset(bool DefaultIsStmt) { void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
Address = 0; Address.Address = 0;
Address.SectionIndex = object::SectionedAddress::UndefSection;
Line = 1; Line = 1;
Column = 0; Column = 0;
File = 1; File = 1;
@ -373,7 +374,7 @@ void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
} }
void DWARFDebugLine::Row::dump(raw_ostream &OS) const { void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column) OS << format("0x%16.16" PRIx64 " %6u %6u", Address.Address, Line, Column)
<< format(" %6u %3u %13u ", File, Isa, Discriminator) << format(" %6u %3u %13u ", File, Isa, Discriminator)
<< (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "") << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")
<< (PrologueEnd ? " prologue_end" : "") << (PrologueEnd ? " prologue_end" : "")
@ -386,6 +387,7 @@ DWARFDebugLine::Sequence::Sequence() { reset(); }
void DWARFDebugLine::Sequence::reset() { void DWARFDebugLine::Sequence::reset() {
LowPC = 0; LowPC = 0;
HighPC = 0; HighPC = 0;
SectionIndex = object::SectionedAddress::UndefSection;
FirstRowIndex = 0; FirstRowIndex = 0;
LastRowIndex = 0; LastRowIndex = 0;
Empty = true; Empty = true;
@ -426,15 +428,16 @@ void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t Offset) {
if (Sequence.Empty) { if (Sequence.Empty) {
// Record the beginning of instruction sequence. // Record the beginning of instruction sequence.
Sequence.Empty = false; Sequence.Empty = false;
Sequence.LowPC = Row.Address; Sequence.LowPC = Row.Address.Address;
Sequence.FirstRowIndex = RowNumber; Sequence.FirstRowIndex = RowNumber;
} }
++RowNumber; ++RowNumber;
LineTable->appendRow(Row); LineTable->appendRow(Row);
if (Row.EndSequence) { if (Row.EndSequence) {
// Record the end of instruction sequence. // Record the end of instruction sequence.
Sequence.HighPC = Row.Address; Sequence.HighPC = Row.Address.Address;
Sequence.LastRowIndex = RowNumber; Sequence.LastRowIndex = RowNumber;
Sequence.SectionIndex = Row.Address.SectionIndex;
if (Sequence.isValid()) if (Sequence.isValid())
LineTable->appendSequence(Sequence); LineTable->appendSequence(Sequence);
Sequence.reset(); Sequence.reset();
@ -565,9 +568,10 @@ Error DWARFDebugLine::LineTable::parse(
ExtOffset, DebugLineData.getAddressSize(), ExtOffset, DebugLineData.getAddressSize(),
Len - 1); Len - 1);
} }
State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr); State.Row.Address.Address = DebugLineData.getRelocatedAddress(
OffsetPtr, &State.Row.Address.SectionIndex);
if (OS) if (OS)
*OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address); *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address);
break; break;
case DW_LNE_define_file: case DW_LNE_define_file:
@ -654,7 +658,7 @@ Error DWARFDebugLine::LineTable::parse(
{ {
uint64_t AddrOffset = uint64_t AddrOffset =
DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength; DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength;
State.Row.Address += AddrOffset; State.Row.Address.Address += AddrOffset;
if (OS) if (OS)
*OS << " (" << AddrOffset << ")"; *OS << " (" << AddrOffset << ")";
} }
@ -712,7 +716,7 @@ Error DWARFDebugLine::LineTable::parse(
uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase; uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase;
uint64_t AddrOffset = uint64_t AddrOffset =
(AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength; (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
State.Row.Address += AddrOffset; State.Row.Address.Address += AddrOffset;
if (OS) if (OS)
*OS *OS
<< format(" (0x%16.16" PRIx64 ")", AddrOffset); << format(" (0x%16.16" PRIx64 ")", AddrOffset);
@ -731,7 +735,7 @@ Error DWARFDebugLine::LineTable::parse(
// can use DW_LNS_fixed_advance_pc instead, sacrificing compression. // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
{ {
uint16_t PCOffset = DebugLineData.getU16(OffsetPtr); uint16_t PCOffset = DebugLineData.getU16(OffsetPtr);
State.Row.Address += PCOffset; State.Row.Address.Address += PCOffset;
if (OS) if (OS)
*OS *OS
<< format(" (0x%16.16" PRIx64 ")", PCOffset); << format(" (0x%16.16" PRIx64 ")", PCOffset);
@ -814,7 +818,7 @@ Error DWARFDebugLine::LineTable::parse(
int32_t LineOffset = int32_t LineOffset =
Prologue.LineBase + (AdjustOpcode % Prologue.LineRange); Prologue.LineBase + (AdjustOpcode % Prologue.LineRange);
State.Row.Line += LineOffset; State.Row.Line += LineOffset;
State.Row.Address += AddrOffset; State.Row.Address.Address += AddrOffset;
if (OS) { if (OS) {
*OS << "address += " << AddrOffset << ", line += " << LineOffset *OS << "address += " << AddrOffset << ", line += " << LineOffset
@ -850,11 +854,12 @@ Error DWARFDebugLine::LineTable::parse(
return Error::success(); return Error::success();
} }
uint32_t uint32_t DWARFDebugLine::LineTable::findRowInSeq(
DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq, const DWARFDebugLine::Sequence &Seq,
uint64_t Address) const { object::SectionedAddress Address) const {
if (!Seq.containsPC(Address)) if (!Seq.containsPC(Address))
return UnknownRowIndex; return UnknownRowIndex;
assert(Seq.SectionIndex == Address.SectionIndex);
// Search for instruction address in the rows describing the sequence. // Search for instruction address in the rows describing the sequence.
// Rows are stored in a vector, so we may use arithmetical operations with // Rows are stored in a vector, so we may use arithmetical operations with
// iterators. // iterators.
@ -867,8 +872,9 @@ DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq,
if (RowPos == LastRow) { if (RowPos == LastRow) {
return Seq.LastRowIndex - 1; return Seq.LastRowIndex - 1;
} }
assert(Seq.SectionIndex == RowPos->Address.SectionIndex);
uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow); uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow);
if (RowPos->Address > Address) { if (RowPos->Address.Address > Address.Address) {
if (RowPos == FirstRow) if (RowPos == FirstRow)
return UnknownRowIndex; return UnknownRowIndex;
else else
@ -877,42 +883,81 @@ DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq,
return Index; return Index;
} }
uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const { uint32_t DWARFDebugLine::LineTable::lookupAddress(
object::SectionedAddress Address) const {
// Search for relocatable addresses
uint32_t Result = lookupAddressImpl(Address);
if (Result != UnknownRowIndex ||
Address.SectionIndex == object::SectionedAddress::UndefSection)
return Result;
// Search for absolute addresses
Address.SectionIndex = object::SectionedAddress::UndefSection;
return lookupAddressImpl(Address);
}
uint32_t DWARFDebugLine::LineTable::lookupAddressImpl(
object::SectionedAddress Address) const {
if (Sequences.empty()) if (Sequences.empty())
return UnknownRowIndex; return UnknownRowIndex;
// First, find an instruction sequence containing the given address. // First, find an instruction sequence containing the given address.
DWARFDebugLine::Sequence Sequence; DWARFDebugLine::Sequence Sequence;
Sequence.LowPC = Address; Sequence.SectionIndex = Address.SectionIndex;
Sequence.LowPC = Address.Address;
SequenceIter FirstSeq = Sequences.begin(); SequenceIter FirstSeq = Sequences.begin();
SequenceIter LastSeq = Sequences.end(); SequenceIter LastSeq = Sequences.end();
SequenceIter SeqPos = std::lower_bound( SequenceIter SeqPos = std::lower_bound(
FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC); FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
DWARFDebugLine::Sequence FoundSeq; DWARFDebugLine::Sequence FoundSeq;
if (SeqPos == LastSeq) { if (SeqPos == LastSeq) {
FoundSeq = Sequences.back(); FoundSeq = Sequences.back();
} else if (SeqPos->LowPC == Address) { } else if (SeqPos->LowPC == Address.Address &&
SeqPos->SectionIndex == Address.SectionIndex) {
FoundSeq = *SeqPos; FoundSeq = *SeqPos;
} else { } else {
if (SeqPos == FirstSeq) if (SeqPos == FirstSeq)
return UnknownRowIndex; return UnknownRowIndex;
FoundSeq = *(SeqPos - 1); FoundSeq = *(SeqPos - 1);
} }
if (FoundSeq.SectionIndex != Address.SectionIndex)
return UnknownRowIndex;
return findRowInSeq(FoundSeq, Address); return findRowInSeq(FoundSeq, Address);
} }
bool DWARFDebugLine::LineTable::lookupAddressRange( bool DWARFDebugLine::LineTable::lookupAddressRange(
uint64_t Address, uint64_t Size, std::vector<uint32_t> &Result) const { object::SectionedAddress Address, uint64_t Size,
std::vector<uint32_t> &Result) const {
// Search for relocatable addresses
if (lookupAddressRangeImpl(Address, Size, Result))
return true;
if (Address.SectionIndex == object::SectionedAddress::UndefSection)
return false;
// Search for absolute addresses
Address.SectionIndex = object::SectionedAddress::UndefSection;
return lookupAddressRangeImpl(Address, Size, Result);
}
bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(
object::SectionedAddress Address, uint64_t Size,
std::vector<uint32_t> &Result) const {
if (Sequences.empty()) if (Sequences.empty())
return false; return false;
uint64_t EndAddr = Address + Size; uint64_t EndAddr = Address.Address + Size;
// First, find an instruction sequence containing the given address. // First, find an instruction sequence containing the given address.
DWARFDebugLine::Sequence Sequence; DWARFDebugLine::Sequence Sequence;
Sequence.LowPC = Address; Sequence.SectionIndex = Address.SectionIndex;
Sequence.LowPC = Address.Address;
SequenceIter FirstSeq = Sequences.begin(); SequenceIter FirstSeq = Sequences.begin();
SequenceIter LastSeq = Sequences.end(); SequenceIter LastSeq = Sequences.end();
SequenceIter SeqPos = std::lower_bound( SequenceIter SeqPos = std::lower_bound(
FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC); FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
if (SeqPos == LastSeq || SeqPos->LowPC != Address) { if (SeqPos == LastSeq || !SeqPos->containsPC(Address)) {
if (SeqPos == FirstSeq) if (SeqPos == FirstSeq)
return false; return false;
SeqPos--; SeqPos--;
@ -934,7 +979,8 @@ bool DWARFDebugLine::LineTable::lookupAddressRange(
FirstRowIndex = findRowInSeq(CurSeq, Address); FirstRowIndex = findRowInSeq(CurSeq, Address);
// Figure out the last row in the range. // Figure out the last row in the range.
uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1); uint32_t LastRowIndex =
findRowInSeq(CurSeq, {EndAddr - 1, Address.SectionIndex});
if (LastRowIndex == UnknownRowIndex) if (LastRowIndex == UnknownRowIndex)
LastRowIndex = CurSeq.LastRowIndex - 1; LastRowIndex = CurSeq.LastRowIndex - 1;
@ -1011,8 +1057,8 @@ bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
} }
bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
uint64_t Address, const char *CompDir, FileLineInfoKind Kind, object::SectionedAddress Address, const char *CompDir,
DILineInfo &Result) const { FileLineInfoKind Kind, DILineInfo &Result) const {
// Get the index of row we're looking for in the line table. // Get the index of row we're looking for in the line table.
uint32_t RowIndex = lookupAddress(Address); uint32_t RowIndex = lookupAddress(Address);
if (RowIndex == -1U) if (RowIndex == -1U)

View File

@ -68,7 +68,7 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const {
} }
DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
llvm::Optional<SectionedAddress> BaseAddr) const { llvm::Optional<object::SectionedAddress> BaseAddr) const {
DWARFAddressRangesVector Res; DWARFAddressRangesVector Res;
for (const RangeListEntry &RLE : Entries) { for (const RangeListEntry &RLE : Entries) {
if (RLE.isBaseAddressSelectionEntry(AddressSize)) { if (RLE.isBaseAddressSelectionEntry(AddressSize)) {

View File

@ -112,9 +112,8 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
return Error::success(); return Error::success();
} }
DWARFAddressRangesVector DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {
DWARFUnit &U) const {
DWARFAddressRangesVector Res; DWARFAddressRangesVector Res;
for (const RangeListEntry &RLE : Entries) { for (const RangeListEntry &RLE : Entries) {
if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
@ -174,7 +173,7 @@ DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr,
void RangeListEntry::dump( void RangeListEntry::dump(
raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
uint64_t &CurrentBase, DIDumpOptions DumpOpts, uint64_t &CurrentBase, DIDumpOptions DumpOpts,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)> llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress) const { LookupPooledAddress) const {
auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
uint8_t AddrSize, DIDumpOptions DumpOpts) { uint8_t AddrSize, DIDumpOptions DumpOpts) {

View File

@ -100,7 +100,7 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
auto LL = DebugLoc.parseOneLocationList(Data, &Offset); auto LL = DebugLoc.parseOneLocationList(Data, &Offset);
if (LL) { if (LL) {
uint64_t BaseAddr = 0; uint64_t BaseAddr = 0;
if (Optional<SectionedAddress> BA = U->getBaseAddress()) if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
BaseAddr = BA->Address; BaseAddr = BA->Address;
LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U,
BaseAddr, Indent); BaseAddr, Indent);
@ -125,7 +125,7 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
Data, &Offset, UseLocLists ? U->getVersion() : 4); Data, &Offset, UseLocLists ? U->getVersion() : 4);
uint64_t BaseAddr = 0; uint64_t BaseAddr = 0;
if (Optional<SectionedAddress> BA = U->getBaseAddress()) if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
BaseAddr = BA->Address; BaseAddr = BA->Address;
if (LL) if (LL)

View File

@ -360,7 +360,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS,
DIDumpOptions DumpOpts, DIDumpOptions DumpOpts,
SectionedAddress SA) const { object::SectionedAddress SA) const {
OS << format("0x%016" PRIx64, SA.Address); OS << format("0x%016" PRIx64, SA.Address);
dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts,
SA.SectionIndex); SA.SectionIndex);
@ -397,7 +397,7 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
case DW_FORM_addrx3: case DW_FORM_addrx3:
case DW_FORM_addrx4: case DW_FORM_addrx4:
case DW_FORM_GNU_addr_index: { case DW_FORM_GNU_addr_index: {
Optional<SectionedAddress> A = U->getAddrOffsetSectionItem(UValue); Optional<object::SectionedAddress> A = U->getAddrOffsetSectionItem(UValue);
if (!A || DumpOpts.Verbose) if (!A || DumpOpts.Verbose)
AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);
if (U == nullptr) if (U == nullptr)
@ -618,14 +618,15 @@ Optional<uint64_t> DWARFFormValue::getAsAddress() const {
return SA->Address; return SA->Address;
return None; return None;
} }
Optional<SectionedAddress> DWARFFormValue::getAsSectionedAddress() const { Optional<object::SectionedAddress>
DWARFFormValue::getAsSectionedAddress() const {
if (!isFormClass(FC_Address)) if (!isFormClass(FC_Address))
return None; return None;
if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) { if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) {
uint32_t Index = Value.uval; uint32_t Index = Value.uval;
if (!U) if (!U)
return None; return None;
Optional<SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); Optional<object::SectionedAddress> SA = U->getAddrOffsetSectionItem(Index);
if (!SA) if (!SA)
return None; return None;
return SA; return SA;

View File

@ -197,7 +197,7 @@ DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
getAddressByteSize()); getAddressByteSize());
} }
Optional<SectionedAddress> Optional<object::SectionedAddress>
DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
if (IsDWO) { if (IsDWO) {
auto R = Context.info_section_units(); auto R = Context.info_section_units();
@ -744,7 +744,7 @@ const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
return Abbrevs; return Abbrevs;
} }
llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() { llvm::Optional<object::SectionedAddress> DWARFUnit::getBaseAddress() {
if (BaseAddr) if (BaseAddr)
return BaseAddr; return BaseAddr;

View File

@ -772,7 +772,7 @@ void DWARFVerifier::verifyDebugLineRows() {
uint32_t RowIndex = 0; uint32_t RowIndex = 0;
for (const auto &Row : LineTable->Rows) { for (const auto &Row : LineTable->Rows) {
// Verify row address. // Verify row address.
if (Row.Address < PrevAddress) { if (Row.Address.Address < PrevAddress) {
++NumDebugLineErrors; ++NumDebugLineErrors;
error() << ".debug_line[" error() << ".debug_line["
<< format("0x%08" PRIx64, << format("0x%08" PRIx64,
@ -802,7 +802,7 @@ void DWARFVerifier::verifyDebugLineRows() {
if (Row.EndSequence) if (Row.EndSequence)
PrevAddress = 0; PrevAddress = 0;
else else
PrevAddress = Row.Address; PrevAddress = Row.Address.Address;
++RowIndex; ++RowIndex;
} }
} }

View File

@ -30,14 +30,14 @@ PDBContext::PDBContext(const COFFObjectFile &Object,
void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){} void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){}
DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address, DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Specifier) { DILineInfoSpecifier Specifier) {
DILineInfo Result; DILineInfo Result;
Result.FunctionName = getFunctionName(Address, Specifier.FNKind); Result.FunctionName = getFunctionName(Address.Address, Specifier.FNKind);
uint32_t Length = 1; uint32_t Length = 1;
std::unique_ptr<PDBSymbol> Symbol = std::unique_ptr<PDBSymbol> Symbol =
Session->findSymbolByAddress(Address, PDB_SymType::None); Session->findSymbolByAddress(Address.Address, PDB_SymType::None);
if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) { if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) {
Length = Func->getLength(); Length = Func->getLength();
} else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) { } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) {
@ -46,7 +46,7 @@ DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
// If we couldn't find a symbol, then just assume 1 byte, so that we get // If we couldn't find a symbol, then just assume 1 byte, so that we get
// only the line number of the first instruction. // only the line number of the first instruction.
auto LineNumbers = Session->findLineNumbersByAddress(Address, Length); auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Length);
if (!LineNumbers || LineNumbers->getChildCount() == 0) if (!LineNumbers || LineNumbers->getChildCount() == 0)
return Result; return Result;
@ -63,26 +63,27 @@ DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
} }
DILineInfoTable DILineInfoTable
PDBContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address,
uint64_t Size,
DILineInfoSpecifier Specifier) { DILineInfoSpecifier Specifier) {
if (Size == 0) if (Size == 0)
return DILineInfoTable(); return DILineInfoTable();
DILineInfoTable Table; DILineInfoTable Table;
auto LineNumbers = Session->findLineNumbersByAddress(Address, Size); auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Size);
if (!LineNumbers || LineNumbers->getChildCount() == 0) if (!LineNumbers || LineNumbers->getChildCount() == 0)
return Table; return Table;
while (auto LineInfo = LineNumbers->getNext()) { while (auto LineInfo = LineNumbers->getNext()) {
DILineInfo LineEntry = DILineInfo LineEntry = getLineInfoForAddress(
getLineInfoForAddress(LineInfo->getVirtualAddress(), Specifier); {LineInfo->getVirtualAddress(), Address.SectionIndex}, Specifier);
Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry)); Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry));
} }
return Table; return Table;
} }
DIInliningInfo DIInliningInfo
PDBContext::getInliningInfoForAddress(uint64_t Address, PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Specifier) { DILineInfoSpecifier Specifier) {
DIInliningInfo InlineInfo; DIInliningInfo InlineInfo;
DILineInfo Frame = getLineInfoForAddress(Address, Specifier); DILineInfo Frame = getLineInfoForAddress(Address, Specifier);

View File

@ -222,9 +222,10 @@ bool SymbolizableObjectFile::shouldOverrideWithSymbolTable(
isa<DWARFContext>(DebugInfoContext.get()); isa<DWARFContext>(DebugInfoContext.get());
} }
DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset, DILineInfo
FunctionNameKind FNKind, SymbolizableObjectFile::symbolizeCode(object::SectionedAddress ModuleOffset,
bool UseSymbolTable) const { FunctionNameKind FNKind,
bool UseSymbolTable) const {
DILineInfo LineInfo; DILineInfo LineInfo;
if (DebugInfoContext) { if (DebugInfoContext) {
LineInfo = DebugInfoContext->getLineInfoForAddress( LineInfo = DebugInfoContext->getLineInfoForAddress(
@ -234,7 +235,7 @@ DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset,
if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) {
std::string FunctionName; std::string FunctionName;
uint64_t Start, Size; uint64_t Start, Size;
if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address,
FunctionName, Start, Size)) { FunctionName, Start, Size)) {
LineInfo.FunctionName = FunctionName; LineInfo.FunctionName = FunctionName;
} }
@ -243,7 +244,8 @@ DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset,
} }
DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode(
uint64_t ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const { object::SectionedAddress ModuleOffset, FunctionNameKind FNKind,
bool UseSymbolTable) const {
DIInliningInfo InlinedContext; DIInliningInfo InlinedContext;
if (DebugInfoContext) if (DebugInfoContext)
@ -257,7 +259,7 @@ DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode(
if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) {
std::string FunctionName; std::string FunctionName;
uint64_t Start, Size; uint64_t Start, Size;
if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address,
FunctionName, Start, Size)) { FunctionName, Start, Size)) {
InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1) InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1)
->FunctionName = FunctionName; ->FunctionName = FunctionName;
@ -267,9 +269,10 @@ DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode(
return InlinedContext; return InlinedContext;
} }
DIGlobal SymbolizableObjectFile::symbolizeData(uint64_t ModuleOffset) const { DIGlobal SymbolizableObjectFile::symbolizeData(
object::SectionedAddress ModuleOffset) const {
DIGlobal Res; DIGlobal Res;
getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Res.Name, Res.Start, getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset.Address, Res.Name,
Res.Size); Res.Start, Res.Size);
return Res; return Res;
} }

View File

@ -33,12 +33,13 @@ public:
static ErrorOr<std::unique_ptr<SymbolizableObjectFile>> static ErrorOr<std::unique_ptr<SymbolizableObjectFile>>
create(object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx); create(object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx);
DILineInfo symbolizeCode(uint64_t ModuleOffset, FunctionNameKind FNKind, DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset,
FunctionNameKind FNKind,
bool UseSymbolTable) const override; bool UseSymbolTable) const override;
DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset, DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset,
FunctionNameKind FNKind, FunctionNameKind FNKind,
bool UseSymbolTable) const override; bool UseSymbolTable) const override;
DIGlobal symbolizeData(uint64_t ModuleOffset) const override; DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override;
// Return true if this is a 32-bit x86 PE COFF module. // Return true if this is a 32-bit x86 PE COFF module.
bool isWin32Module() const override; bool isWin32Module() const override;

View File

@ -52,7 +52,8 @@ namespace symbolize {
Expected<DILineInfo> Expected<DILineInfo>
LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
uint64_t ModuleOffset, StringRef DWPName) { object::SectionedAddress ModuleOffset,
StringRef DWPName) {
SymbolizableModule *Info; SymbolizableModule *Info;
if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName)) if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName))
Info = InfoOrErr.get(); Info = InfoOrErr.get();
@ -67,7 +68,7 @@ LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
// If the user is giving us relative addresses, add the preferred base of the // If the user is giving us relative addresses, add the preferred base of the
// object to the offset before we do the query. It's what DIContext expects. // object to the offset before we do the query. It's what DIContext expects.
if (Opts.RelativeAddresses) if (Opts.RelativeAddresses)
ModuleOffset += Info->getModulePreferredBase(); ModuleOffset.Address += Info->getModulePreferredBase();
DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions, DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions,
Opts.UseSymbolTable); Opts.UseSymbolTable);
@ -78,7 +79,8 @@ LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
Expected<DIInliningInfo> Expected<DIInliningInfo>
LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
uint64_t ModuleOffset, StringRef DWPName) { object::SectionedAddress ModuleOffset,
StringRef DWPName) {
SymbolizableModule *Info; SymbolizableModule *Info;
if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName)) if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName))
Info = InfoOrErr.get(); Info = InfoOrErr.get();
@ -93,7 +95,7 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
// If the user is giving us relative addresses, add the preferred base of the // If the user is giving us relative addresses, add the preferred base of the
// object to the offset before we do the query. It's what DIContext expects. // object to the offset before we do the query. It's what DIContext expects.
if (Opts.RelativeAddresses) if (Opts.RelativeAddresses)
ModuleOffset += Info->getModulePreferredBase(); ModuleOffset.Address += Info->getModulePreferredBase();
DIInliningInfo InlinedContext = Info->symbolizeInlinedCode( DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable); ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable);
@ -106,8 +108,9 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
return InlinedContext; return InlinedContext;
} }
Expected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName, Expected<DIGlobal>
uint64_t ModuleOffset) { LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
object::SectionedAddress ModuleOffset) {
SymbolizableModule *Info; SymbolizableModule *Info;
if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
Info = InfoOrErr.get(); Info = InfoOrErr.get();
@ -123,7 +126,7 @@ Expected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
// the object to the offset before we do the query. It's what DIContext // the object to the offset before we do the query. It's what DIContext
// expects. // expects.
if (Opts.RelativeAddresses) if (Opts.RelativeAddresses)
ModuleOffset += Info->getModulePreferredBase(); ModuleOffset.Address += Info->getModulePreferredBase();
DIGlobal Global = Info->symbolizeData(ModuleOffset); DIGlobal Global = Info->symbolizeData(ModuleOffset);
if (Opts.Demangle) if (Opts.Demangle)

View File

@ -0,0 +1,221 @@
# The code below is the reduced version of the output
# from the following invocation and source:
#
# // test.cpp:
#void f1() {}
#void f2() {}
#
# clang -gdwarf-5 -ffunction-sections test.cpp -o test.s -S
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -dwarf-version=5 %s -o %t.o
# RUN: llvm-objdump -disassemble -line-numbers -r -s -section-headers -t %t.o | FileCheck %s
# CHECK: 0000000000000000 _Z2f1v
# CHECK-NOT: test.cpp:2
# CHECK: test.cpp:1
# CHECK-NOT: test.cpp:2
# CHECK: 0000000000000000 _Z2f2v
# CHECK-NOT: test.cpp:1
# CHECK: test.cpp:2
# CHECK-NOT: test.cpp:1
.text
.file "test.cpp"
.section .text._Z2f1v,"ax",@progbits
.globl _Z2f1v # -- Begin function _Z2f1v
.p2align 4, 0x90
.type _Z2f1v,@function
_Z2f1v: # @_Z2f1v
.Lfunc_begin0:
.file 0 "/home/avl" "test.cpp" md5 0xefae234cc05b45384d782316d3a5d338
.file 1 "test.cpp" md5 0xefae234cc05b45384d782316d3a5d338
.loc 1 1 0 # test.cpp:1:0
.cfi_startproc
# %bb.0: # %entry
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
.Ltmp0:
.loc 1 1 12 prologue_end # test.cpp:1:12
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.Ltmp1:
.Lfunc_end0:
.size _Z2f1v, .Lfunc_end0-_Z2f1v
.cfi_endproc
# -- End function
.section .text._Z2f2v,"ax",@progbits
.globl _Z2f2v # -- Begin function _Z2f2v
.p2align 4, 0x90
.type _Z2f2v,@function
_Z2f2v: # @_Z2f2v
.Lfunc_begin1:
.loc 1 2 0 # test.cpp:2:0
.cfi_startproc
# %bb.0: # %entry
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
.Ltmp2:
.loc 1 2 12 prologue_end # test.cpp:2:12
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.Ltmp3:
.Lfunc_end1:
.size _Z2f2v, .Lfunc_end1-_Z2f2v
.cfi_endproc
# -- End function
.section .debug_str_offsets,"",@progbits
.long 32
.short 5
.short 0
.Lstr_offsets_base0:
.section .debug_str,"MS",@progbits,1
.Linfo_string0:
.asciz "clang version 9.0.0 (https://github.com/llvm/llvm-project.git ebfc1e5af7a65381d858612517e6414ef58df482)" # string offset=0
.Linfo_string1:
.asciz "test.cpp" # string offset=104
.Linfo_string2:
.asciz "/home/avl" # string offset=113
.Linfo_string3:
.asciz "_Z2f1v" # string offset=123
.Linfo_string4:
.asciz "f1" # string offset=130
.Linfo_string5:
.asciz "_Z2f2v" # string offset=133
.Linfo_string6:
.asciz "f2" # string offset=140
.section .debug_str_offsets,"",@progbits
.long .Linfo_string0
.long .Linfo_string1
.long .Linfo_string2
.long .Linfo_string3
.long .Linfo_string4
.long .Linfo_string5
.long .Linfo_string6
.section .debug_abbrev,"",@progbits
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 1 # DW_CHILDREN_yes
.byte 37 # DW_AT_producer
.byte 37 # DW_FORM_strx1
.byte 19 # DW_AT_language
.byte 5 # DW_FORM_data2
.byte 3 # DW_AT_name
.byte 37 # DW_FORM_strx1
.byte 114 # DW_AT_str_offsets_base
.byte 23 # DW_FORM_sec_offset
.byte 16 # DW_AT_stmt_list
.byte 23 # DW_FORM_sec_offset
.byte 27 # DW_AT_comp_dir
.byte 37 # DW_FORM_strx1
.byte 115 # DW_AT_addr_base
.byte 23 # DW_FORM_sec_offset
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 85 # DW_AT_ranges
.byte 35 # DW_FORM_rnglistx
.byte 116 # DW_AT_rnglists_base
.byte 23 # DW_FORM_sec_offset
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 2 # Abbreviation Code
.byte 46 # DW_TAG_subprogram
.byte 0 # DW_CHILDREN_no
.byte 17 # DW_AT_low_pc
.byte 27 # DW_FORM_addrx
.byte 18 # DW_AT_high_pc
.byte 6 # DW_FORM_data4
.byte 64 # DW_AT_frame_base
.byte 24 # DW_FORM_exprloc
.byte 110 # DW_AT_linkage_name
.byte 37 # DW_FORM_strx1
.byte 3 # DW_AT_name
.byte 37 # DW_FORM_strx1
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 63 # DW_AT_external
.byte 25 # DW_FORM_flag_present
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 0 # EOM(3)
.section .debug_info,"",@progbits
.Lcu_begin0:
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
.Ldebug_info_start0:
.short 5 # DWARF version number
.byte 1 # DWARF Unit Type
.byte 8 # Address Size (in bytes)
.long .debug_abbrev # Offset Into Abbrev. Section
.byte 1 # Abbrev [1] 0xc:0x38 DW_TAG_compile_unit
.byte 0 # DW_AT_producer
.short 4 # DW_AT_language
.byte 1 # DW_AT_name
.long .Lstr_offsets_base0 # DW_AT_str_offsets_base
.long .Lline_table_start0 # DW_AT_stmt_list
.byte 2 # DW_AT_comp_dir
.long .Laddr_table_base0 # DW_AT_addr_base
.quad 0 # DW_AT_low_pc
.byte 0 # DW_AT_ranges
.long .Lrnglists_table_base0 # DW_AT_rnglists_base
.byte 2 # Abbrev [2] 0x2b:0xc DW_TAG_subprogram
.byte 0 # DW_AT_low_pc
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 86
.byte 3 # DW_AT_linkage_name
.byte 4 # DW_AT_name
.byte 1 # DW_AT_decl_file
.byte 1 # DW_AT_decl_line
# DW_AT_external
.byte 2 # Abbrev [2] 0x37:0xc DW_TAG_subprogram
.byte 1 # DW_AT_low_pc
.long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 86
.byte 5 # DW_AT_linkage_name
.byte 6 # DW_AT_name
.byte 1 # DW_AT_decl_file
.byte 2 # DW_AT_decl_line
# DW_AT_external
.byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_rnglists,"",@progbits
.long .Ldebug_rnglist_table_end0-.Ldebug_rnglist_table_start0 # Length
.Ldebug_rnglist_table_start0:
.short 5 # Version
.byte 8 # Address size
.byte 0 # Segment selector size
.long 1 # Offset entry count
.Lrnglists_table_base0:
.long .Ldebug_ranges0-.Lrnglists_table_base0
.Ldebug_ranges0:
.byte 3 # DW_RLE_startx_length
.byte 0 # start index
.uleb128 .Lfunc_end0-.Lfunc_begin0 # length
.byte 3 # DW_RLE_startx_length
.byte 1 # start index
.uleb128 .Lfunc_end1-.Lfunc_begin1 # length
.byte 0 # DW_RLE_end_of_list
.Ldebug_rnglist_table_end0:
.Ldebug_addr_start0:
.short 5 # DWARF version number
.byte 8 # Address size
.byte 0 # Segment selector size
.Laddr_table_base0:
.quad .Lfunc_begin0
.quad .Lfunc_begin1
.Ldebug_addr_end0:
.section .debug_line,"",@progbits
.Lline_table_start0:

View File

@ -1734,17 +1734,17 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
// it is marked as end_sequence in the input (because in that // it is marked as end_sequence in the input (because in that
// case, the relocation offset is accurate and that entry won't // case, the relocation offset is accurate and that entry won't
// serve as the start of another function). // serve as the start of another function).
if (CurrRange == InvalidRange || Row.Address < CurrRange.start() || if (CurrRange == InvalidRange || Row.Address.Address < CurrRange.start() ||
Row.Address > CurrRange.stop() || Row.Address.Address > CurrRange.stop() ||
(Row.Address == CurrRange.stop() && !Row.EndSequence)) { (Row.Address.Address == CurrRange.stop() && !Row.EndSequence)) {
// We just stepped out of a known range. Insert a end_sequence // We just stepped out of a known range. Insert a end_sequence
// corresponding to the end of the range. // corresponding to the end of the range.
uint64_t StopAddress = CurrRange != InvalidRange uint64_t StopAddress = CurrRange != InvalidRange
? CurrRange.stop() + CurrRange.value() ? CurrRange.stop() + CurrRange.value()
: -1ULL; : -1ULL;
CurrRange = FunctionRanges.find(Row.Address); CurrRange = FunctionRanges.find(Row.Address.Address);
bool CurrRangeValid = bool CurrRangeValid =
CurrRange != InvalidRange && CurrRange.start() <= Row.Address; CurrRange != InvalidRange && CurrRange.start() <= Row.Address.Address;
if (!CurrRangeValid) { if (!CurrRangeValid) {
CurrRange = InvalidRange; CurrRange = InvalidRange;
if (StopAddress != -1ULL) { if (StopAddress != -1ULL) {
@ -1754,13 +1754,13 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
// for now do as dsymutil. // for now do as dsymutil.
// FIXME: Understand exactly what cases this addresses and // FIXME: Understand exactly what cases this addresses and
// potentially remove it along with the Ranges map. // potentially remove it along with the Ranges map.
auto Range = Ranges.lower_bound(Row.Address); auto Range = Ranges.lower_bound(Row.Address.Address);
if (Range != Ranges.begin() && Range != Ranges.end()) if (Range != Ranges.begin() && Range != Ranges.end())
--Range; --Range;
if (Range != Ranges.end() && Range->first <= Row.Address && if (Range != Ranges.end() && Range->first <= Row.Address.Address &&
Range->second.HighPC >= Row.Address) { Range->second.HighPC >= Row.Address.Address) {
StopAddress = Row.Address + Range->second.Offset; StopAddress = Row.Address.Address + Range->second.Offset;
} }
} }
} }
@ -1768,7 +1768,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
// Insert end sequence row with the computed end address, but // Insert end sequence row with the computed end address, but
// the same line as the previous one. // the same line as the previous one.
auto NextLine = Seq.back(); auto NextLine = Seq.back();
NextLine.Address = StopAddress; NextLine.Address.Address = StopAddress;
NextLine.EndSequence = 1; NextLine.EndSequence = 1;
NextLine.PrologueEnd = 0; NextLine.PrologueEnd = 0;
NextLine.BasicBlock = 0; NextLine.BasicBlock = 0;
@ -1786,7 +1786,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
continue; continue;
// Relocate row address and add it to the current sequence. // Relocate row address and add it to the current sequence.
Row.Address += CurrRange.value(); Row.Address.Address += CurrRange.value();
Seq.emplace_back(Row); Seq.emplace_back(Row);
if (Row.EndSequence) if (Row.EndSequence)

View File

@ -480,11 +480,11 @@ void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
MS->EmitULEB128IntValue(PointerSize + 1); MS->EmitULEB128IntValue(PointerSize + 1);
MS->EmitIntValue(dwarf::DW_LNE_set_address, 1); MS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
MS->EmitIntValue(Row.Address, PointerSize); MS->EmitIntValue(Row.Address.Address, PointerSize);
LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1); LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1);
AddressDelta = 0; AddressDelta = 0;
} else { } else {
AddressDelta = (Row.Address - Address) / MinInstLength; AddressDelta = (Row.Address.Address - Address) / MinInstLength;
} }
// FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable. // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
@ -540,7 +540,7 @@ void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
MS->EmitBytes(EncodingOS.str()); MS->EmitBytes(EncodingOS.str());
LineSectionSize += EncodingBuffer.size(); LineSectionSize += EncodingBuffer.size();
EncodingBuffer.resize(0); EncodingBuffer.resize(0);
Address = Row.Address; Address = Row.Address.Address;
LastLine = Row.Line; LastLine = Row.Line;
RowsSinceLastSequence++; RowsSinceLastSequence++;
} else { } else {

View File

@ -254,7 +254,8 @@ FileAnalysis::getDirectControlFlowXRefs(const Instr &InstrMeta) const {
return CFCrossReferences; return CFCrossReferences;
} }
const std::set<uint64_t> &FileAnalysis::getIndirectInstructions() const { const std::set<object::SectionedAddress> &
FileAnalysis::getIndirectInstructions() const {
return IndirectInstructions; return IndirectInstructions;
} }
@ -268,8 +269,10 @@ const MCInstrAnalysis *FileAnalysis::getMCInstrAnalysis() const {
return MIA.get(); return MIA.get();
} }
Expected<DIInliningInfo> FileAnalysis::symbolizeInlinedCode(uint64_t Address) { Expected<DIInliningInfo>
FileAnalysis::symbolizeInlinedCode(object::SectionedAddress Address) {
assert(Symbolizer != nullptr && "Symbolizer is invalid."); assert(Symbolizer != nullptr && "Symbolizer is invalid.");
return Symbolizer->symbolizeInlinedCode(Object->getFileName(), Address); return Symbolizer->symbolizeInlinedCode(Object->getFileName(), Address);
} }
@ -457,13 +460,14 @@ Error FileAnalysis::parseCodeSections() {
ArrayRef<uint8_t> SectionBytes((const uint8_t *)SectionContents.data(), ArrayRef<uint8_t> SectionBytes((const uint8_t *)SectionContents.data(),
Section.getSize()); Section.getSize());
parseSectionContents(SectionBytes, Section.getAddress()); parseSectionContents(SectionBytes,
{Section.getAddress(), Section.getIndex()});
} }
return Error::success(); return Error::success();
} }
void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes, void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
uint64_t SectionAddress) { object::SectionedAddress Address) {
assert(Symbolizer && "Symbolizer is uninitialised."); assert(Symbolizer && "Symbolizer is uninitialised.");
MCInst Instruction; MCInst Instruction;
Instr InstrMeta; Instr InstrMeta;
@ -477,7 +481,7 @@ void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
Byte += InstructionSize; Byte += InstructionSize;
uint64_t VMAddress = SectionAddress + Byte - InstructionSize; uint64_t VMAddress = Address.Address + Byte - InstructionSize;
InstrMeta.Instruction = Instruction; InstrMeta.Instruction = Instruction;
InstrMeta.VMAddress = VMAddress; InstrMeta.VMAddress = VMAddress;
InstrMeta.InstructionSize = InstructionSize; InstrMeta.InstructionSize = InstructionSize;
@ -509,8 +513,8 @@ void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
// Check if this instruction exists in the range of the DWARF metadata. // Check if this instruction exists in the range of the DWARF metadata.
if (!IgnoreDWARFFlag) { if (!IgnoreDWARFFlag) {
auto LineInfo = auto LineInfo = Symbolizer->symbolizeCode(
Symbolizer->symbolizeCode(Object->getFileName(), VMAddress); Object->getFileName(), {VMAddress, Address.SectionIndex});
if (!LineInfo) { if (!LineInfo) {
handleAllErrors(LineInfo.takeError(), [](const ErrorInfoBase &E) { handleAllErrors(LineInfo.takeError(), [](const ErrorInfoBase &E) {
errs() << "Symbolizer failed to get line: " << E.message() << "\n"; errs() << "Symbolizer failed to get line: " << E.message() << "\n";
@ -522,7 +526,7 @@ void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
continue; continue;
} }
IndirectInstructions.insert(VMAddress); IndirectInstructions.insert({VMAddress, Address.SectionIndex});
} }
} }

View File

@ -139,14 +139,15 @@ public:
bool usesRegisterOperand(const Instr &InstrMeta) const; bool usesRegisterOperand(const Instr &InstrMeta) const;
// Returns the list of indirect instructions. // Returns the list of indirect instructions.
const std::set<uint64_t> &getIndirectInstructions() const; const std::set<object::SectionedAddress> &getIndirectInstructions() const;
const MCRegisterInfo *getRegisterInfo() const; const MCRegisterInfo *getRegisterInfo() const;
const MCInstrInfo *getMCInstrInfo() const; const MCInstrInfo *getMCInstrInfo() const;
const MCInstrAnalysis *getMCInstrAnalysis() const; const MCInstrAnalysis *getMCInstrAnalysis() const;
// Returns the inlining information for the provided address. // Returns the inlining information for the provided address.
Expected<DIInliningInfo> symbolizeInlinedCode(uint64_t Address); Expected<DIInliningInfo>
symbolizeInlinedCode(object::SectionedAddress Address);
// Returns whether the provided Graph represents a protected indirect control // Returns whether the provided Graph represents a protected indirect control
// flow instruction in this file. // flow instruction in this file.
@ -178,7 +179,7 @@ protected:
// Disassemble and parse the provided bytes into this object. Instruction // Disassemble and parse the provided bytes into this object. Instruction
// address calculation is done relative to the provided SectionAddress. // address calculation is done relative to the provided SectionAddress.
void parseSectionContents(ArrayRef<uint8_t> SectionBytes, void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
uint64_t SectionAddress); object::SectionedAddress Address);
// Constructs and initialises members required for disassembly. // Constructs and initialises members required for disassembly.
Error initialiseDisassemblyMembers(); Error initialiseDisassemblyMembers();
@ -225,7 +226,7 @@ private:
DenseMap<uint64_t, std::vector<uint64_t>> StaticBranchTargetings; DenseMap<uint64_t, std::vector<uint64_t>> StaticBranchTargetings;
// A list of addresses of indirect control flow instructions. // A list of addresses of indirect control flow instructions.
std::set<uint64_t> IndirectInstructions; std::set<object::SectionedAddress> IndirectInstructions;
// The addresses of functions that will trap on CFI violations. // The addresses of functions that will trap on CFI violations.
SmallSet<uint64_t, 4> TrapOnFailFunctionAddresses; SmallSet<uint64_t, 4> TrapOnFailFunctionAddresses;

View File

@ -93,17 +93,19 @@ void GraphResult::printToDOT(const FileAnalysis &Analysis,
} }
GraphResult GraphBuilder::buildFlowGraph(const FileAnalysis &Analysis, GraphResult GraphBuilder::buildFlowGraph(const FileAnalysis &Analysis,
uint64_t Address) { object::SectionedAddress Address) {
GraphResult Result; GraphResult Result;
Result.BaseAddress = Address; Result.BaseAddress = Address.Address;
DenseSet<uint64_t> OpenedNodes; DenseSet<uint64_t> OpenedNodes;
const auto &IndirectInstructions = Analysis.getIndirectInstructions(); const auto &IndirectInstructions = Analysis.getIndirectInstructions();
if (IndirectInstructions.find(Address) == IndirectInstructions.end()) // check that IndirectInstructions contains specified Address
if (IndirectInstructions.find(Address) == IndirectInstructions.end()) {
return Result; return Result;
}
buildFlowGraphImpl(Analysis, OpenedNodes, Result, Address, 0); buildFlowGraphImpl(Analysis, OpenedNodes, Result, Address.Address, 0);
return Result; return Result;
} }

View File

@ -102,7 +102,7 @@ public:
// (i.e. the upwards traversal did not make it to a branch node) flows to the // (i.e. the upwards traversal did not make it to a branch node) flows to the
// provided node in GraphResult::OrphanedNodes. // provided node in GraphResult::OrphanedNodes.
static GraphResult buildFlowGraph(const FileAnalysis &Analysis, static GraphResult buildFlowGraph(const FileAnalysis &Analysis,
uint64_t Address); object::SectionedAddress Address);
private: private:
// Implementation function that actually builds the flow graph. Retrieves a // Implementation function that actually builds the flow graph. Retrieves a

View File

@ -130,8 +130,8 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
std::map<unsigned, uint64_t> BlameCounter; std::map<unsigned, uint64_t> BlameCounter;
for (uint64_t Address : Analysis.getIndirectInstructions()) { for (object::SectionedAddress Address : Analysis.getIndirectInstructions()) {
const auto &InstrMeta = Analysis.getInstructionOrDie(Address); const auto &InstrMeta = Analysis.getInstructionOrDie(Address.Address);
GraphResult Graph = GraphBuilder::buildFlowGraph(Analysis, Address); GraphResult Graph = GraphBuilder::buildFlowGraph(Analysis, Address);
CFIProtectionStatus ProtectionStatus = CFIProtectionStatus ProtectionStatus =
@ -153,7 +153,7 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
auto InliningInfo = Analysis.symbolizeInlinedCode(Address); auto InliningInfo = Analysis.symbolizeInlinedCode(Address);
if (!InliningInfo || InliningInfo->getNumberOfFrames() == 0) { if (!InliningInfo || InliningInfo->getNumberOfFrames() == 0) {
errs() << "Failed to symbolise " << format_hex(Address, 2) errs() << "Failed to symbolise " << format_hex(Address.Address, 2)
<< " with line tables from " << InputFilename << "\n"; << " with line tables from " << InputFilename << "\n";
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -164,9 +164,9 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
if (!Summarize) { if (!Summarize) {
for (uint32_t i = 0; i < InliningInfo->getNumberOfFrames(); ++i) { for (uint32_t i = 0; i < InliningInfo->getNumberOfFrames(); ++i) {
const auto &Line = InliningInfo->getFrame(i); const auto &Line = InliningInfo->getFrame(i);
outs() << " " << format_hex(Address, 2) << " = " << Line.FileName outs() << " " << format_hex(Address.Address, 2) << " = "
<< ":" << Line.Line << ":" << Line.Column << " (" << Line.FileName << ":" << Line.Line << ":" << Line.Column
<< Line.FunctionName << ")\n"; << " (" << Line.FunctionName << ")\n";
} }
} }

View File

@ -379,7 +379,12 @@ static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx,
/// Handle the --lookup option and dump the DIEs and line info for the given /// Handle the --lookup option and dump the DIEs and line info for the given
/// address. /// address.
static bool lookup(DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) { /// TODO: specified Address for --lookup option could relate for several
/// different sections(in case not-linked object file). llvm-dwarfdump
/// need to do something with this: extend lookup option with section
/// information or probably display all matched entries, or something else...
static bool lookup(ObjectFile &Obj, DWARFContext &DICtx, uint64_t Address,
raw_ostream &OS) {
auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup); auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup);
if (!DIEsForAddr) if (!DIEsForAddr)
@ -394,7 +399,10 @@ static bool lookup(DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) {
DIEsForAddr.BlockDIE.dump(OS, 4, DumpOpts); DIEsForAddr.BlockDIE.dump(OS, 4, DumpOpts);
} }
if (DILineInfo LineInfo = DICtx.getLineInfoForAddress(Lookup)) // TODO: it is neccessary to set proper SectionIndex here.
// object::SectionedAddress::UndefSection works for only absolute addresses.
if (DILineInfo LineInfo = DICtx.getLineInfoForAddress(
{Lookup, object::SectionedAddress::UndefSection}))
LineInfo.dump(OS); LineInfo.dump(OS);
return true; return true;
@ -413,7 +421,7 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename,
// Handle the --lookup option. // Handle the --lookup option.
if (Lookup) if (Lookup)
return lookup(DICtx, Lookup, OS); return lookup(Obj, DICtx, Lookup, OS);
// Handle the --name option. // Handle the --name option.
if (!Name.empty()) { if (!Name.empty()) {

View File

@ -7500,7 +7500,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
// Print debug info. // Print debug info.
if (diContext) { if (diContext) {
DILineInfo dli = diContext->getLineInfoForAddress(PC); DILineInfo dli = diContext->getLineInfoForAddress({PC, SectIdx});
// Print valid line info if it changed. // Print valid line info if it changed.
if (dli != lastLine && dli.Line != 0) if (dli != lastLine && dli.Line != 0)
outs() << "\t## " << dli.FileName << ':' << dli.Line << ':' outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'

View File

@ -508,7 +508,8 @@ public:
Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts));
} }
virtual ~SourcePrinter() = default; virtual ~SourcePrinter() = default;
virtual void printSourceLine(raw_ostream &OS, uint64_t Address, virtual void printSourceLine(raw_ostream &OS,
object::SectionedAddress Address,
StringRef Delimiter = "; "); StringRef Delimiter = "; ");
}; };
@ -538,7 +539,8 @@ bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
return true; return true;
} }
void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address, void SourcePrinter::printSourceLine(raw_ostream &OS,
object::SectionedAddress Address,
StringRef Delimiter) { StringRef Delimiter) {
if (!Symbolizer) if (!Symbolizer)
return; return;
@ -599,14 +601,15 @@ class PrettyPrinter {
public: public:
virtual ~PrettyPrinter() = default; virtual ~PrettyPrinter() = default;
virtual void printInst(MCInstPrinter &IP, const MCInst *MI, virtual void printInst(MCInstPrinter &IP, const MCInst *MI,
ArrayRef<uint8_t> Bytes, uint64_t Address, ArrayRef<uint8_t> Bytes,
raw_ostream &OS, StringRef Annot, object::SectionedAddress Address, raw_ostream &OS,
MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef Annot, MCSubtargetInfo const &STI,
SourcePrinter *SP,
std::vector<RelocationRef> *Rels = nullptr) { std::vector<RelocationRef> *Rels = nullptr) {
if (SP && (PrintSource || PrintLines)) if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address); SP->printSourceLine(OS, Address);
if (!NoLeadingAddr) if (!NoLeadingAddr)
OS << format("%8" PRIx64 ":", Address); OS << format("%8" PRIx64 ":", Address.Address);
if (!NoShowRawInsn) { if (!NoShowRawInsn) {
OS << "\t"; OS << "\t";
dumpBytes(Bytes, OS); dumpBytes(Bytes, OS);
@ -633,13 +636,13 @@ public:
} }
} }
void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes, void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
uint64_t Address, raw_ostream &OS, StringRef Annot, object::SectionedAddress Address, raw_ostream &OS,
MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
std::vector<RelocationRef> *Rels) override { std::vector<RelocationRef> *Rels) override {
if (SP && (PrintSource || PrintLines)) if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address, ""); SP->printSourceLine(OS, Address, "");
if (!MI) { if (!MI) {
printLead(Bytes, Address, OS); printLead(Bytes, Address.Address, OS);
OS << " <unknown>"; OS << " <unknown>";
return; return;
} }
@ -661,9 +664,9 @@ public:
std::vector<RelocationRef>::const_iterator RelCur = Rels->begin(); std::vector<RelocationRef>::const_iterator RelCur = Rels->begin();
std::vector<RelocationRef>::const_iterator RelEnd = Rels->end(); std::vector<RelocationRef>::const_iterator RelEnd = Rels->end();
auto PrintReloc = [&]() -> void { auto PrintReloc = [&]() -> void {
while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address)) { while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address.Address)) {
if (RelCur->getOffset() == Address) { if (RelCur->getOffset() == Address.Address) {
printRelocation(*RelCur, Address, 4); printRelocation(*RelCur, Address.Address, 4);
return; return;
} }
++RelCur; ++RelCur;
@ -675,7 +678,7 @@ public:
Separator = "\n"; Separator = "\n";
if (SP && (PrintSource || PrintLines)) if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address, ""); SP->printSourceLine(OS, Address, "");
printLead(Bytes, Address, OS); printLead(Bytes, Address.Address, OS);
OS << Preamble; OS << Preamble;
Preamble = " "; Preamble = " ";
StringRef Inst; StringRef Inst;
@ -693,7 +696,7 @@ public:
OS << " } " << PacketBundle.second; OS << " } " << PacketBundle.second;
PrintReloc(); PrintReloc();
Bytes = Bytes.slice(4); Bytes = Bytes.slice(4);
Address += 4; Address.Address += 4;
} }
} }
}; };
@ -702,8 +705,8 @@ HexagonPrettyPrinter HexagonPrettyPrinterInst;
class AMDGCNPrettyPrinter : public PrettyPrinter { class AMDGCNPrettyPrinter : public PrettyPrinter {
public: public:
void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes, void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
uint64_t Address, raw_ostream &OS, StringRef Annot, object::SectionedAddress Address, raw_ostream &OS,
MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
std::vector<RelocationRef> *Rels) override { std::vector<RelocationRef> *Rels) override {
if (SP && (PrintSource || PrintLines)) if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address); SP->printSourceLine(OS, Address);
@ -733,7 +736,7 @@ public:
} }
} }
OS << format("// %012" PRIX64 ": ", Address); OS << format("// %012" PRIX64 ": ", Address.Address);
if (Bytes.size() >=4) { if (Bytes.size() >=4) {
for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()), for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()),
Bytes.size() / sizeof(U32))) Bytes.size() / sizeof(U32)))
@ -754,13 +757,13 @@ AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst;
class BPFPrettyPrinter : public PrettyPrinter { class BPFPrettyPrinter : public PrettyPrinter {
public: public:
void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes, void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
uint64_t Address, raw_ostream &OS, StringRef Annot, object::SectionedAddress Address, raw_ostream &OS,
MCSubtargetInfo const &STI, SourcePrinter *SP, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
std::vector<RelocationRef> *Rels) override { std::vector<RelocationRef> *Rels) override {
if (SP && (PrintSource || PrintLines)) if (SP && (PrintSource || PrintLines))
SP->printSourceLine(OS, Address); SP->printSourceLine(OS, Address);
if (!NoLeadingAddr) if (!NoLeadingAddr)
OS << format("%8" PRId64 ":", Address / 8); OS << format("%8" PRId64 ":", Address.Address / 8);
if (!NoShowRawInsn) { if (!NoShowRawInsn) {
OS << "\t"; OS << "\t";
dumpBytes(Bytes, OS); dumpBytes(Bytes, OS);
@ -1323,9 +1326,10 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
if (Size == 0) if (Size == 0)
Size = 1; Size = 1;
PIP.printInst( PIP.printInst(*IP, Disassembled ? &Inst : nullptr,
*IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size), Bytes.slice(Index, Size),
SectionAddr + Index + VMAAdjustment, outs(), "", *STI, &SP, &Rels); {SectionAddr + Index + VMAAdjustment, Section.getIndex()},
outs(), "", *STI, &SP, &Rels);
outs() << CommentStream.str(); outs() << CommentStream.str();
Comments.clear(); Comments.clear();

View File

@ -367,6 +367,8 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
} }
uint64_t Addr = *AddrOrErr; uint64_t Addr = *AddrOrErr;
object::SectionedAddress Address;
uint64_t Size = P.second; uint64_t Size = P.second;
// If we're not using the debug object, compute the address of the // If we're not using the debug object, compute the address of the
// symbol in memory (rather than that in the unrelocated object file) // symbol in memory (rather than that in the unrelocated object file)
@ -381,16 +383,20 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
object::section_iterator Sec = *SecOrErr; object::section_iterator Sec = *SecOrErr;
StringRef SecName; StringRef SecName;
Sec->getName(SecName); Sec->getName(SecName);
Address.SectionIndex = Sec->getIndex();
uint64_t SectionLoadAddress = uint64_t SectionLoadAddress =
LoadedObjInfo->getSectionLoadAddress(*Sec); LoadedObjInfo->getSectionLoadAddress(*Sec);
if (SectionLoadAddress != 0) if (SectionLoadAddress != 0)
Addr += SectionLoadAddress - Sec->getAddress(); Addr += SectionLoadAddress - Sec->getAddress();
} } else if (auto SecOrErr = Sym.getSection())
Address.SectionIndex = SecOrErr.get()->getIndex();
outs() << "Function: " << *Name << ", Size = " << Size outs() << "Function: " << *Name << ", Size = " << Size
<< ", Addr = " << Addr << "\n"; << ", Addr = " << Addr << "\n";
DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); Address.Address = Addr;
DILineInfoTable Lines =
Context->getLineInfoForAddressRange(Address, Size);
for (auto &D : Lines) { for (auto &D : Lines) {
outs() << " Line info @ " << D.first - Addr << ": " outs() << " Line info @ " << D.first - Addr << ": "
<< D.second.FileName << ", line:" << D.second.Line << "\n"; << D.second.FileName << ", line:" << D.second.Line << "\n";

View File

@ -194,23 +194,54 @@ static bool parseCommand(StringRef InputString, bool &IsData,
return !StringRef(pos, offset_length).getAsInteger(0, ModuleOffset); return !StringRef(pos, offset_length).getAsInteger(0, ModuleOffset);
} }
// This routine returns section index for an address.
// Assumption: would work ambiguously for object files which have sections not
// assigned to an address(since the same address could belong to various
// sections).
static uint64_t getModuleSectionIndexForAddress(const std::string &ModuleName,
uint64_t Address) {
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(ModuleName);
if (error(BinaryOrErr))
return object::SectionedAddress::UndefSection;
Binary &Binary = *BinaryOrErr->getBinary();
if (ObjectFile *O = dyn_cast<ObjectFile>(&Binary)) {
for (SectionRef Sec : O->sections()) {
if (!Sec.isText() || Sec.isVirtual())
continue;
if (Address >= Sec.getAddress() &&
Address <= Sec.getAddress() + Sec.getSize()) {
return Sec.getIndex();
}
}
}
return object::SectionedAddress::UndefSection;
}
static void symbolizeInput(StringRef InputString, LLVMSymbolizer &Symbolizer, static void symbolizeInput(StringRef InputString, LLVMSymbolizer &Symbolizer,
DIPrinter &Printer) { DIPrinter &Printer) {
bool IsData = false; bool IsData = false;
std::string ModuleName; std::string ModuleName;
uint64_t ModuleOffset = 0; uint64_t Offset = 0;
if (!parseCommand(StringRef(InputString), IsData, ModuleName, ModuleOffset)) { if (!parseCommand(StringRef(InputString), IsData, ModuleName, Offset)) {
outs() << InputString; outs() << InputString;
return; return;
} }
if (ClPrintAddress) { if (ClPrintAddress) {
outs() << "0x"; outs() << "0x";
outs().write_hex(ModuleOffset); outs().write_hex(Offset);
StringRef Delimiter = ClPrettyPrint ? ": " : "\n"; StringRef Delimiter = ClPrettyPrint ? ": " : "\n";
outs() << Delimiter; outs() << Delimiter;
} }
ModuleOffset -= ClAdjustVMA; Offset -= ClAdjustVMA;
object::SectionedAddress ModuleOffset = {
Offset, getModuleSectionIndexForAddress(ModuleName, Offset)};
if (IsData) { if (IsData) {
auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset); auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset);
Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get()); Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get());

View File

@ -29,7 +29,12 @@ std::string FuncIdConversionHelper::SymbolOrNumber(int32_t FuncId) const {
return F.str(); return F.str();
} }
if (auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second)) { object::SectionedAddress ModuleAddress;
ModuleAddress.Address = It->second;
// TODO: set proper section index here.
// object::SectionedAddress::UndefSection works for only absolute addresses.
ModuleAddress.SectionIndex = object::SectionedAddress::UndefSection;
if (auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, ModuleAddress)) {
auto &DI = *ResOrErr; auto &DI = *ResOrErr;
if (DI.FunctionName == "<invalid>") if (DI.FunctionName == "<invalid>")
F << "@(" << std::hex << It->second << ")"; F << "@(" << std::hex << It->second << ")";
@ -51,7 +56,12 @@ std::string FuncIdConversionHelper::FileLineAndColumn(int32_t FuncId) const {
return "(unknown)"; return "(unknown)";
std::ostringstream F; std::ostringstream F;
auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second); object::SectionedAddress ModuleAddress;
ModuleAddress.Address = It->second;
// TODO: set proper section index here.
// object::SectionedAddress::UndefSection works for only absolute addresses.
ModuleAddress.SectionIndex = object::SectionedAddress::UndefSection;
auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, ModuleAddress);
if (!ResOrErr) { if (!ResOrErr) {
consumeError(ResOrErr.takeError()); consumeError(ResOrErr.takeError());
return "(unknown)"; return "(unknown)";

View File

@ -621,10 +621,17 @@ getCoveragePoints(const std::string &ObjectFile,
std::set<std::string> CoveredFiles; std::set<std::string> CoveredFiles;
if (ClSkipDeadFiles) { if (ClSkipDeadFiles) {
for (auto Addr : CoveredAddrs) { for (auto Addr : CoveredAddrs) {
auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); // TODO: it would be neccessary to set proper section index here.
// object::SectionedAddress::UndefSection works for only absolute
// addresses.
object::SectionedAddress ModuleAddress = {
Addr, object::SectionedAddress::UndefSection};
auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, ModuleAddress);
failIfError(LineInfo); failIfError(LineInfo);
CoveredFiles.insert(LineInfo->FileName); CoveredFiles.insert(LineInfo->FileName);
auto InliningInfo = Symbolizer->symbolizeInlinedCode(ObjectFile, Addr); auto InliningInfo =
Symbolizer->symbolizeInlinedCode(ObjectFile, ModuleAddress);
failIfError(InliningInfo); failIfError(InliningInfo);
for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) { for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) {
auto FrameInfo = InliningInfo->getFrame(I); auto FrameInfo = InliningInfo->getFrame(I);
@ -636,7 +643,12 @@ getCoveragePoints(const std::string &ObjectFile,
for (auto Addr : Addrs) { for (auto Addr : Addrs) {
std::set<DILineInfo> Infos; // deduplicate debug info. std::set<DILineInfo> Infos; // deduplicate debug info.
auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); // TODO: it would be neccessary to set proper section index here.
// object::SectionedAddress::UndefSection works for only absolute addresses.
object::SectionedAddress ModuleAddress = {
Addr, object::SectionedAddress::UndefSection};
auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, ModuleAddress);
failIfError(LineInfo); failIfError(LineInfo);
if (ClSkipDeadFiles && if (ClSkipDeadFiles &&
CoveredFiles.find(LineInfo->FileName) == CoveredFiles.end()) CoveredFiles.find(LineInfo->FileName) == CoveredFiles.end())
@ -650,7 +662,8 @@ getCoveragePoints(const std::string &ObjectFile,
Infos.insert(*LineInfo); Infos.insert(*LineInfo);
Point.Locs.push_back(*LineInfo); Point.Locs.push_back(*LineInfo);
auto InliningInfo = Symbolizer->symbolizeInlinedCode(ObjectFile, Addr); auto InliningInfo =
Symbolizer->symbolizeInlinedCode(ObjectFile, ModuleAddress);
failIfError(InliningInfo); failIfError(InliningInfo);
for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) { for (uint32_t I = 0; I < InliningInfo->getNumberOfFrames(); ++I) {
auto FrameInfo = InliningInfo->getFrame(I); auto FrameInfo = InliningInfo->getFrame(I);
@ -957,7 +970,10 @@ symbolize(const RawCoverage &Data, const std::string ObjectFile) {
auto Symbolizer(createSymbolizer()); auto Symbolizer(createSymbolizer());
for (uint64_t Addr : *Data.Addrs) { for (uint64_t Addr : *Data.Addrs) {
auto LineInfo = Symbolizer->symbolizeCode(ObjectFile, Addr); // TODO: it would be neccessary to set proper section index here.
// object::SectionedAddress::UndefSection works for only absolute addresses.
auto LineInfo = Symbolizer->symbolizeCode(
ObjectFile, {Addr, object::SectionedAddress::UndefSection});
failIfError(LineInfo); failIfError(LineInfo);
if (B.isBlacklisted(*LineInfo)) if (B.isBlacklisted(*LineInfo))
continue; continue;

View File

@ -84,8 +84,10 @@ const char *ReadModule(char SizeofPtr, const char *Begin, const char *End) {
// As the instrumentation tracks the return address and not // As the instrumentation tracks the return address and not
// the address of the call to `__sanitizer_stat_report` we // the address of the call to `__sanitizer_stat_report` we
// remove one from the address to get the correct DI. // remove one from the address to get the correct DI.
if (Expected<DILineInfo> LineInfo = // TODO: it would be neccessary to set proper section index here.
Symbolizer.symbolizeCode(Filename, Addr - 1)) { // object::SectionedAddress::UndefSection works for only absolute addresses.
if (Expected<DILineInfo> LineInfo = Symbolizer.symbolizeCode(
Filename, {Addr - 1, object::SectionedAddress::UndefSection})) {
llvm::outs() << format_hex(Addr - 1, 18) << ' ' << LineInfo->FileName llvm::outs() << format_hex(Addr - 1, 18) << ' ' << LineInfo->FileName
<< ':' << LineInfo->Line << ' ' << LineInfo->FunctionName << ':' << LineInfo->Line << ' ' << LineInfo->FunctionName
<< ' '; << ' ';

View File

@ -51,8 +51,8 @@ public:
// Expose this method publicly for testing. // Expose this method publicly for testing.
void parseSectionContents(ArrayRef<uint8_t> SectionBytes, void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
uint64_t SectionAddress) { object::SectionedAddress Address) {
FileAnalysis::parseSectionContents(SectionBytes, SectionAddress); FileAnalysis::parseSectionContents(SectionBytes, Address);
} }
Error initialiseDisassemblyMembers() { Error initialiseDisassemblyMembers() {
@ -106,7 +106,7 @@ TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) {
0x41, 0x0e, // 21: rex.B (bad) 0x41, 0x0e, // 21: rex.B (bad)
0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
EXPECT_EQ(nullptr, Analysis.getInstruction(0x0)); EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000)); EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
@ -210,7 +210,7 @@ TEST_F(BasicX86FileAnalysisTest, PrevAndNextFromBadInst) {
0x2f, // 1: (bad) 0x2f, // 1: (bad)
0x90 // 2: nop 0x90 // 2: nop
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1); const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);
const auto *GoodInstrMeta = const auto *GoodInstrMeta =
Analysis.getPrevInstructionSequential(BadInstrMeta); Analysis.getPrevInstructionSequential(BadInstrMeta);
@ -240,7 +240,7 @@ TEST_F(BasicX86FileAnalysisTest, CFITrapTest) {
0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
0x0f, 0x0b // 28: ud2 0x0f, 0x0b // 28: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF))); EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
EXPECT_FALSE( EXPECT_FALSE(
@ -275,7 +275,7 @@ TEST_F(BasicX86FileAnalysisTest, FallThroughTest) {
0x75, 0x00, // 17: jne +0 0x75, 0x00, // 17: jne +0
0xc3, // 19: retq 0xc3, // 19: retq
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
EXPECT_TRUE( EXPECT_TRUE(
Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF))); Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
@ -322,7 +322,7 @@ TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) {
0xeb, 0xdd, // 36: jmp 3 [-35] 0xeb, 0xdd, // 36: jmp 3 [-35]
0xeb, 0xdc, // 38: jmp 4 [-36] 0xeb, 0xdc, // 38: jmp 4 [-36]
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
const auto *Current = Analysis.getInstruction(0xDEADBEEF); const auto *Current = Analysis.getInstruction(0xDEADBEEF);
const auto *Next = Analysis.getDefiniteNextInstruction(*Current); const auto *Next = Analysis.getDefiniteNextInstruction(*Current);
@ -412,7 +412,7 @@ TEST_F(BasicX86FileAnalysisTest, ControlFlowXRefsTest) {
0xeb, 0xdd, // 36: jmp 3 [-35] 0xeb, 0xdd, // 36: jmp 3 [-35]
0xeb, 0xdc, // 38: jmp 4 [-36] 0xeb, 0xdc, // 38: jmp 4 [-36]
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF); const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);
std::set<const Instr *> XRefs = std::set<const Instr *> XRefs =
Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
@ -503,17 +503,18 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionInvalidTargets) {
0x0f, 0x0b, // 1: ud2 0x0f, 0x0b, // 1: ud2
0x75, 0x00, // 3: jne 5 [+0] 0x75, 0x00, // 3: jne 5 [+0]
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 1); Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
Result = GraphBuilder::buildFlowGraph(Analysis, 0x12345678); Result = GraphBuilder::buildFlowGraph(Analysis, {0x12345678, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION, EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -527,8 +528,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicFallthroughToUd2) {
0x0f, 0x0b, // 2: ud2 0x0f, 0x0b, // 2: ud2
0xff, 0x10, // 4: callq *(%rax) 0xff, 0x10, // 4: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -542,8 +544,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) {
0xff, 0x10, // 2: callq *(%rax) 0xff, 0x10, // 2: callq *(%rax)
0x0f, 0x0b, // 4: ud2 0x0f, 0x0b, // 4: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -560,8 +563,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) {
0x75, 0xf9, // 7: jne 2 [-7] 0x75, 0xf9, // 7: jne 2 [-7]
0x0f, 0x0b, // 9: ud2 0x0f, 0x0b, // 9: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -577,8 +581,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) {
0x75, 0xfb, // 5: jne 2 [-5] 0x75, 0xfb, // 5: jne 2 [-5]
0x0f, 0x0b, // 7: ud2 0x0f, 0x0b, // 7: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -596,12 +601,13 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) {
0xff, 0x10, // 6: callq *(%rax) 0xff, 0x10, // 6: callq *(%rax)
0x0f, 0x0b, // 8: ud2 0x0f, 0x0b, // 8: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
uint64_t PrevSearchLengthForConditionalBranch = uint64_t PrevSearchLengthForConditionalBranch =
SearchLengthForConditionalBranch; SearchLengthForConditionalBranch;
SearchLengthForConditionalBranch = 2; SearchLengthForConditionalBranch = 2;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 6); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
@ -621,11 +627,12 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitDownwards) {
0x90, // 7: nop 0x90, // 7: nop
0x0f, 0x0b, // 8: ud2 0x0f, 0x0b, // 8: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
SearchLengthForUndef = 2; SearchLengthForUndef = 2;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH, EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
@ -642,8 +649,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionGoodAndBadPaths) {
0xff, 0x10, // 4: callq *(%rax) 0xff, 0x10, // 4: callq *(%rax)
0x0f, 0x0b, // 6: ud2 0x0f, 0x0b, // 6: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -658,8 +666,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough
0xff, 0x10, // 4: callq *(%rax) 0xff, 0x10, // 4: callq *(%rax)
0x0f, 0x0b, // 6: ud2 0x0f, 0x0b, // 6: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -685,10 +694,11 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) {
0x90, // 21: nop 0x90, // 21: nop
0x0f, 0x0b, // 22: ud2 0x0f, 0x0b, // 22: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
SearchLengthForUndef = 5; SearchLengthForUndef = 5;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 9); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
SearchLengthForUndef = PrevSearchLengthForUndef; SearchLengthForUndef = PrevSearchLengthForUndef;
@ -704,10 +714,10 @@ TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) {
0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130
0x0f, 0x0b, // 0x688127: ud2 0x0f, 0x0b, // 0x688127: ud2
}, },
0x688118); {0x688118, 0x0});
uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
SearchLengthForUndef = 1; SearchLengthForUndef = 1;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x68811d); GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
SearchLengthForUndef = PrevSearchLengthForUndef; SearchLengthForUndef = PrevSearchLengthForUndef;
@ -719,7 +729,7 @@ TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {
0x74, 0x73, // 0x7759eb: je 0x775a60 0x74, 0x73, // 0x7759eb: je 0x775a60
0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e
}, },
0x7759eb); {0x7759eb, 0x0});
Analysis.parseSectionContents( Analysis.parseSectionContents(
{ {
@ -729,24 +739,24 @@ TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) {
0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi
0xff, 0xd1, // 0x775a68: callq *%rcx 0xff, 0xd1, // 0x775a68: callq *%rcx
}, },
0x775a56); {0x775a56, 0x0});
Analysis.parseSectionContents( Analysis.parseSectionContents(
{ {
0x0f, 0x0b, // 0x775e0e: ud2 0x0f, 0x0b, // 0x775e0e: ud2
}, },
0x775e0e); {0x775e0e, 0x0});
uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
SearchLengthForUndef = 1; SearchLengthForUndef = 1;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH, EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
SearchLengthForUndef = 2; SearchLengthForUndef = 2;
Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
SearchLengthForUndef = 3; SearchLengthForUndef = 3;
Result = GraphBuilder::buildFlowGraph(Analysis, 0x775a68); Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
SearchLengthForUndef = PrevSearchLengthForUndef; SearchLengthForUndef = PrevSearchLengthForUndef;
@ -762,8 +772,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) {
0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax
0xff, 0x10, // 10: callq *(%rax) 0xff, 0x10, // 10: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 10); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -778,8 +789,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) {
0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax
0xff, 0x10, // 8: callq *(%rax) 0xff, 0x10, // 8: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 8); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -794,8 +806,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) {
0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax
0xff, 0x10, // 9: callq *(%rax) 0xff, 0x10, // 9: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 9); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -812,8 +825,9 @@ TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) {
0x75, 0xf9, // 8: jne 2 [-7] 0x75, 0xf9, // 8: jne 2 [-7]
0x0f, 0x0b, // 10: ud2 0x0f, 0x0b, // 10: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -825,8 +839,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) {
{ {
0x00, 0x01, 0x3f, 0xd6, // 0: blr x8 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -840,8 +855,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) {
0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1
0x00, 0x01, 0x3f, 0xd6, // 8: blr x8 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 8); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -856,8 +872,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) {
0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1
0x00, 0x01, 0x3f, 0xd6, // 12: blr x8 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -872,8 +889,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) {
0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16] 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16]
0x20, 0x00, 0x1f, 0xd6, // 12: br x1 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -889,8 +907,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) {
0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
0x20, 0x00, 0x1f, 0xd6, // 16: br x1 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -906,8 +925,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) {
0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1
0x20, 0x00, 0x1f, 0xd6, // 16: br x1 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -923,8 +943,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) {
0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
0x20, 0x00, 0x1f, 0xd6, // 16: br x1 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -940,8 +961,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) {
0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16] 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16]
0x20, 0x00, 0x1f, 0xd6, // 16: br x1 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -957,8 +979,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) {
0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16]
0x20, 0x00, 0x1f, 0xd6, // 16: br x1 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -974,8 +997,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) {
0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16] 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16]
0x20, 0x00, 0x1f, 0xd6, // 16: br x1 0x20, 0x00, 0x1f, 0xd6, // 16: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 16); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -990,8 +1014,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) {
0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1
0x20, 0x00, 0x1f, 0xd6, // 12: br x1 0x20, 0x00, 0x1f, 0xd6, // 12: br x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 12); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -1009,8 +1034,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) {
0x20, 0x00, 0x1f, 0xd6, // 20: br x1 0x20, 0x00, 0x1f, 0xd6, // 20: br x1
0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 20); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0});
EXPECT_EQ(CFIProtectionStatus::PROTECTED, EXPECT_EQ(CFIProtectionStatus::PROTECTED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -1029,8 +1055,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) {
0x20, 0x00, 0x1f, 0xd6, // 24: br x1 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }
@ -1049,8 +1076,9 @@ TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) {
0x20, 0x00, 0x1f, 0xd6, // 24: br x1 0x20, 0x00, 0x1f, 0xd6, // 24: br x1
0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 24); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0});
EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED,
Analysis.validateCFIProtection(Result)); Analysis.validateCFIProtection(Result));
} }

View File

@ -113,8 +113,8 @@ public:
// Expose this method publicly for testing. // Expose this method publicly for testing.
void parseSectionContents(ArrayRef<uint8_t> SectionBytes, void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
uint64_t SectionAddress) { object::SectionedAddress Address) {
FileAnalysis::parseSectionContents(SectionBytes, SectionAddress); FileAnalysis::parseSectionContents(SectionBytes, Address);
} }
Error initialiseDisassemblyMembers() { Error initialiseDisassemblyMembers() {
@ -156,8 +156,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestSinglePathFallthroughUd2) {
0x0f, 0x0b, // 2: ud2 0x0f, 0x0b, // 2: ud2
0xff, 0x10, // 4: callq *(%rax) 0xff, 0x10, // 4: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); const auto Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
@ -182,8 +183,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestSinglePathJumpUd2) {
0xff, 0x10, // 2: callq *(%rax) 0xff, 0x10, // 2: callq *(%rax)
0x0f, 0x0b, // 4: ud2 0x0f, 0x0b, // 4: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); const auto Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
@ -211,8 +213,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestDualPathDualUd2) {
0x75, 0xf9, // 7: jne 2 [-7] 0x75, 0xf9, // 7: jne 2 [-7]
0x0f, 0x0b, // 9: ud2 0x0f, 0x0b, // 9: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
const auto Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); const auto Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2));
@ -249,8 +252,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestDualPathSingleUd2) {
0x75, 0xfb, // 5: jne 2 [-5] 0x75, 0xfb, // 5: jne 2 [-5]
0x0f, 0x0b, // 7: ud2 0x0f, 0x0b, // 7: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2));
@ -284,16 +288,17 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphFailures) {
0x90, // 0: nop 0x90, // 0: nop
0x75, 0xfe, // 1: jne 1 [-2] 0x75, 0xfe, // 1: jne 1 [-2]
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 1); Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADC0DE); Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADC0DE, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
} }
@ -306,8 +311,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphNoXrefs) {
0xeb, 0xfe, // 0: jmp 0 [-2] 0xeb, 0xfe, // 0: jmp 0 [-2]
0xff, 0x10, // 2: callq *(%rax) 0xff, 0x10, // 2: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 2)); EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 2));
EXPECT_THAT(Result.IntermediateNodes, IsEmpty()); EXPECT_THAT(Result.IntermediateNodes, IsEmpty());
@ -321,8 +327,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphConditionalInfiniteLoop) {
0x75, 0xfe, // 0: jne 0 [-2] 0x75, 0xfe, // 0: jne 0 [-2]
0xff, 0x10, // 2: callq *(%rax) 0xff, 0x10, // 2: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
EXPECT_THAT( EXPECT_THAT(
@ -344,8 +351,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphUnconditionalInfiniteLoop) {
0xeb, 0xfc, // 2: jmp 0 [-4] 0xeb, 0xfc, // 2: jmp 0 [-4]
0xff, 0x10, // 4: callq *(%rax) 0xff, 0x10, // 4: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
EXPECT_THAT( EXPECT_THAT(
@ -368,8 +376,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphNoFlowsToIndirection) {
0xeb, 0xfc, // 2: jmp 0 [-4] 0xeb, 0xfc, // 2: jmp 0 [-4]
0xff, 0x10, // 4: callq *(%rax) 0xff, 0x10, // 4: callq *(%rax)
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 4); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 4)); EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 4));
EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty()); EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
} }
@ -387,12 +396,13 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphLengthExceededUpwards) {
0xff, 0x10, // 6: callq *(%rax) 0xff, 0x10, // 6: callq *(%rax)
0x0f, 0x0b, // 8: ud2 0x0f, 0x0b, // 8: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
uint64_t PrevSearchLengthForConditionalBranch = uint64_t PrevSearchLengthForConditionalBranch =
SearchLengthForConditionalBranch; SearchLengthForConditionalBranch;
SearchLengthForConditionalBranch = 2; SearchLengthForConditionalBranch = 2;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 6); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0});
EXPECT_THAT(Result.OrphanedNodes, SizeIs(1)); EXPECT_THAT(Result.OrphanedNodes, SizeIs(1));
EXPECT_THAT(Result.OrphanedNodes, EXPECT_THAT(Result.OrphanedNodes,
Each(HasPath(Result, ElementsAre(0xDEADBEEF + 4, 0xDEADBEEF + 5, Each(HasPath(Result, ElementsAre(0xDEADBEEF + 4, 0xDEADBEEF + 5,
@ -416,11 +426,12 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphLengthExceededDownwards) {
0x90, // 7: nop 0x90, // 7: nop
0x0f, 0x0b, // 8: ud2 0x0f, 0x0b, // 8: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
SearchLengthForUndef = 2; SearchLengthForUndef = 2;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 2); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT( EXPECT_THAT(
Result.ConditionalBranchNodes, Result.ConditionalBranchNodes,
@ -450,8 +461,9 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphWithRepeatedWork) {
0x75, 0xfb, // 5: jne 2 [-5] 0x75, 0xfb, // 5: jne 2 [-5]
0x0f, 0x0b, // 7: ud2 0x0f, 0x0b, // 7: ud2
}, },
0xDEADBEEF); {0xDEADBEEF, 0x0});
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0xDEADBEEF + 3); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
EXPECT_THAT(Result.OrphanedNodes, IsEmpty()); EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2));
EXPECT_THAT( EXPECT_THAT(
@ -529,11 +541,12 @@ TEST_F(BasicGraphBuilderTest, BuildFlowGraphComplexExample) {
0x90, // 21: nop 0x90, // 21: nop
0x0f, 0x0b, // 22: ud2 0x0f, 0x0b, // 22: ud2
}, },
0x1000); {0x1000, 0x0});
uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
SearchLengthForUndef = 5; SearchLengthForUndef = 5;
GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, 0x1000 + 9); GraphResult Result =
GraphBuilder::buildFlowGraph(Analysis, {0x1000 + 9, 0x0});
EXPECT_THAT(Result.OrphanedNodes, SizeIs(1)); EXPECT_THAT(Result.OrphanedNodes, SizeIs(1));
EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(3)); EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(3));