Skip to content

Commit

Permalink
[DebugInfo] add SectionedAddress to DebugInfo interfaces.
Browse files Browse the repository at this point in the history
      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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354972 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
avl-llvm committed Feb 27, 2019
1 parent ea85a46 commit a15cff1
Show file tree
Hide file tree
Showing 44 changed files with 783 additions and 327 deletions.
11 changes: 7 additions & 4 deletions include/llvm/DebugInfo/DIContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,14 @@ class DIContext {
return true;
}

virtual DILineInfo getLineInfoForAddress(uint64_t Address,
virtual DILineInfo getLineInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
virtual DILineInfoTable getLineInfoForAddressRange(
object::SectionedAddress Address, uint64_t Size,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
virtual DIInliningInfo getInliningInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;

private:
Expand Down
13 changes: 10 additions & 3 deletions include/llvm/DebugInfo/DWARF/DWARFContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,13 +317,18 @@ class DWARFContext : public DIContext {

/// Get the compilation unit, the function DIE and lexical block DIE for the
/// given address where applicable.
/// TODO: change input parameter from "uint64_t Address"
/// into "SectionedAddress Address"
DIEsForAddress getDIEsForAddress(uint64_t Address);

DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfo getLineInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
DILineInfoTable getLineInfoForAddressRange(
object::SectionedAddress Address, uint64_t Size,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DIInliningInfo getInliningInfoForAddress(
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;

bool isLittleEndian() const { return DObj->isLittleEndian(); }
Expand Down Expand Up @@ -366,6 +371,8 @@ class DWARFContext : public DIContext {
private:
/// Return the compile unit which contains instruction with provided
/// address.
/// TODO: change input parameter from "uint64_t Address"
/// into "SectionedAddress Address"
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
};

Expand Down
36 changes: 27 additions & 9 deletions include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,16 @@ class DWARFDebugLine {
static void dumpTableHeader(raw_ostream &OS);

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
/// generated by the compiler.
uint64_t Address;
/// generated by the compiler and section index pointing to the section
/// 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
/// beginning at 1. The compiler may emit the value 0 in cases where an
/// instruction cannot be attributed to any source line.
Expand Down Expand Up @@ -192,21 +196,29 @@ class DWARFDebugLine {
/// and is described by line table rows [FirstRowIndex, LastRowIndex).
uint64_t LowPC;
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 LastRowIndex;
bool Empty;

void reset();

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 {
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 {
Expand All @@ -223,9 +235,9 @@ class DWARFDebugLine {

/// Returns the index of the row with file/line info for a given address,
/// 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;

bool hasFileAtIndex(uint64_t FileIndex) const;
Expand All @@ -238,7 +250,8 @@ class DWARFDebugLine {

/// Fills the Result argument with the file and line information
/// 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,
DILineInfo &Result) const;

Expand All @@ -263,10 +276,15 @@ class DWARFDebugLine {

private:
uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
uint64_t Address) const;
object::SectionedAddress Address) const;
Optional<StringRef>
getSourceByIndex(uint64_t FileIndex,
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;
Expand Down
2 changes: 1 addition & 1 deletion include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class DWARFDebugRangeList {
/// list. Has to be passed base address of the compile unit referencing this
/// range list.
DWARFAddressRangesVector
getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr) const;
getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr) const;
};

} // end namespace llvm
Expand Down
4 changes: 2 additions & 2 deletions include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct RangeListEntry : public DWARFListEntryBase {
Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr);
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
uint64_t &CurrentBase, DIDumpOptions DumpOpts,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress) const;
bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; }
};
Expand All @@ -47,7 +47,7 @@ class DWARFDebugRnglist : public DWARFListType<RangeListEntry> {
public:
/// Build a DWARFAddressRangesVector from a rangelist.
DWARFAddressRangesVector
getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr,
getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr,
DWARFUnit &U) const;
};

Expand Down
6 changes: 3 additions & 3 deletions include/llvm/DebugInfo/DWARF/DWARFFormValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class DWARFFormValue {
const DWARFUnit *getUnit() const { return U; }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const;
void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts,
SectionedAddress SA) const;
object::SectionedAddress SA) const;
static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,
DIDumpOptions DumpOpts, uint64_t SectionIndex);

Expand Down Expand Up @@ -108,7 +108,7 @@ class DWARFFormValue {
Optional<int64_t> getAsSignedConstant() const;
Optional<const char *> getAsCString() const;
Optional<uint64_t> getAsAddress() const;
Optional<SectionedAddress> getAsSectionedAddress() const;
Optional<object::SectionedAddress> getAsSectionedAddress() const;
Optional<uint64_t> getAsSectionOffset() const;
Optional<ArrayRef<uint8_t>> getAsBlock() const;
Optional<uint64_t> getAsCStringOffset() const;
Expand Down Expand Up @@ -246,7 +246,7 @@ inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue> &V) {
return None;
}

inline Optional<SectionedAddress>
inline Optional<object::SectionedAddress>
toSectionedAddress(const Optional<DWARFFormValue> &V) {
if (V)
return V->getAsSectionedAddress();
Expand Down
4 changes: 2 additions & 2 deletions include/llvm/DebugInfo/DWARF/DWARFListTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ template <typename DWARFListType> class DWARFListTableBase {
uint8_t getAddrSize() const { return Header.getAddrSize(); }

void dump(raw_ostream &OS,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress,
DIDumpOptions DumpOpts = {}) const;

Expand Down Expand Up @@ -234,7 +234,7 @@ Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
template <typename DWARFListType>
void DWARFListTableBase<DWARFListType>::dump(
raw_ostream &OS,
llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress,
DIDumpOptions DumpOpts) const {
Header.dump(OS, DumpOpts);
Expand Down
5 changes: 0 additions & 5 deletions include/llvm/DebugInfo/DWARF/DWARFSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ struct SectionName {
bool IsNameUnique;
};

struct SectionedAddress {
uint64_t Address;
uint64_t SectionIndex;
};

} // end namespace llvm

#endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
7 changes: 4 additions & 3 deletions include/llvm/DebugInfo/DWARF/DWARFUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ class DWARFUnit {
Optional<DWARFDebugRnglistTable> RngListTable;

mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
llvm::Optional<SectionedAddress> BaseAddr;
llvm::Optional<object::SectionedAddress> BaseAddr;
/// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;

Expand Down Expand Up @@ -304,7 +304,8 @@ class DWARFUnit {
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;

DWARFDataExtractor getDebugInfoExtractor() const;
Expand Down Expand Up @@ -375,7 +376,7 @@ class DWARFUnit {
llvm_unreachable("Invalid UnitType.");
}

llvm::Optional<SectionedAddress> getBaseAddress();
llvm::Optional<object::SectionedAddress> getBaseAddress();

DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
extractDIEsIfNeeded(ExtractUnitDIEOnly);
Expand Down
6 changes: 3 additions & 3 deletions include/llvm/DebugInfo/PDB/PDBContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ namespace pdb {
void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override;

DILineInfo getLineInfoForAddress(
uint64_t Address,
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DILineInfoTable getLineInfoForAddressRange(
uint64_t Address, uint64_t Size,
object::SectionedAddress Address, uint64_t Size,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DIInliningInfo getInliningInfoForAddress(
uint64_t Address,
object::SectionedAddress Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;

private:
Expand Down
11 changes: 6 additions & 5 deletions include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ class SymbolizableModule {
public:
virtual ~SymbolizableModule() = default;

virtual DILineInfo symbolizeCode(uint64_t ModuleOffset,
virtual DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset,
FunctionNameKind FNKind,
bool UseSymbolTable) const = 0;
virtual DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset,
FunctionNameKind FNKind,
bool UseSymbolTable) const = 0;
virtual DIGlobal symbolizeData(uint64_t ModuleOffset) const = 0;
virtual DIInliningInfo
symbolizeInlinedCode(object::SectionedAddress ModuleOffset,
FunctionNameKind FNKind, bool UseSymbolTable) const = 0;
virtual DIGlobal
symbolizeData(object::SectionedAddress ModuleOffset) const = 0;

// Return true if this is a 32-bit x86 PE COFF module.
virtual bool isWin32Module() const = 0;
Expand Down
11 changes: 6 additions & 5 deletions include/llvm/DebugInfo/Symbolize/Symbolize.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ class LLVMSymbolizer {
}

Expected<DILineInfo> symbolizeCode(const std::string &ModuleName,
uint64_t ModuleOffset,
object::SectionedAddress ModuleOffset,
StringRef DWPName = "");
Expected<DIInliningInfo> symbolizeInlinedCode(const std::string &ModuleName,
uint64_t ModuleOffset,
StringRef DWPName = "");
Expected<DIInliningInfo>
symbolizeInlinedCode(const std::string &ModuleName,
object::SectionedAddress ModuleOffset,
StringRef DWPName = "");
Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
uint64_t ModuleOffset);
object::SectionedAddress ModuleOffset);
void flush();

static std::string
Expand Down
24 changes: 24 additions & 0 deletions include/llvm/Object/ObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,30 @@ class SectionRef {
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
/// symbols in the object file.
class SymbolRef : public BasicSymbolRef {
Expand Down
Loading

0 comments on commit a15cff1

Please sign in to comment.