mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 14:47:00 +00:00
Revert "[DWARF] reposting r342048, which was reverted in r342056 due to buildbot errors. Adjusted 2 test cases for ARM and darwin and fixed a bug with the original change in dsymutil."
This reverts commit r342218. Due to a number of failures under TSAN. An isolated test case is being worked on. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@342399 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bd60c64f32
commit
d2dad5476b
@ -231,9 +231,7 @@ public:
|
||||
/// Get a DIE given an exact offset.
|
||||
DWARFDie getDIEForOffset(uint32_t Offset);
|
||||
|
||||
unsigned getMaxVersion(uint16_t DefaultVersion = 0) const {
|
||||
return MaxVersion ? MaxVersion : DefaultVersion;
|
||||
}
|
||||
unsigned getMaxVersion() const { return MaxVersion; }
|
||||
|
||||
void setMaxVersionIfGreater(unsigned Version) {
|
||||
if (Version > MaxVersion)
|
||||
|
86
include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
Normal file
86
include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
Normal file
@ -0,0 +1,86 @@
|
||||
//===- DWARFDebugRangeList.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
|
||||
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct BaseAddress;
|
||||
class raw_ostream;
|
||||
|
||||
class DWARFDebugRangeList {
|
||||
public:
|
||||
struct RangeListEntry {
|
||||
/// A beginning address offset. This address offset has the size of an
|
||||
/// address and is relative to the applicable base address of the
|
||||
/// compilation unit referencing this range list. It marks the beginning
|
||||
/// of an address range.
|
||||
uint64_t StartAddress;
|
||||
/// An ending address offset. This address offset again has the size of
|
||||
/// an address and is relative to the applicable base address of the
|
||||
/// compilation unit referencing this range list. It marks the first
|
||||
/// address past the end of the address range. The ending address must
|
||||
/// be greater than or equal to the beginning address.
|
||||
uint64_t EndAddress;
|
||||
/// A section index this range belongs to.
|
||||
uint64_t SectionIndex;
|
||||
|
||||
/// The end of any given range list is marked by an end of list entry,
|
||||
/// which consists of a 0 for the beginning address offset
|
||||
/// and a 0 for the ending address offset.
|
||||
bool isEndOfListEntry() const {
|
||||
return (StartAddress == 0) && (EndAddress == 0);
|
||||
}
|
||||
|
||||
/// A base address selection entry consists of:
|
||||
/// 1. The value of the largest representable address offset
|
||||
/// (for example, 0xffffffff when the size of an address is 32 bits).
|
||||
/// 2. An address, which defines the appropriate base address for
|
||||
/// use in interpreting the beginning and ending address offsets of
|
||||
/// subsequent entries of the location list.
|
||||
bool isBaseAddressSelectionEntry(uint8_t AddressSize) const {
|
||||
assert(AddressSize == 4 || AddressSize == 8);
|
||||
if (AddressSize == 4)
|
||||
return StartAddress == -1U;
|
||||
else
|
||||
return StartAddress == -1ULL;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/// Offset in .debug_ranges section.
|
||||
uint32_t Offset;
|
||||
uint8_t AddressSize;
|
||||
std::vector<RangeListEntry> Entries;
|
||||
|
||||
public:
|
||||
DWARFDebugRangeList() { clear(); }
|
||||
|
||||
void clear();
|
||||
void dump(raw_ostream &OS) const;
|
||||
Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
|
||||
const std::vector<RangeListEntry> &getEntries() { return Entries; }
|
||||
|
||||
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
|
||||
/// list. Has to be passed base address of the compile unit referencing this
|
||||
/// range list.
|
||||
DWARFAddressRangesVector
|
||||
getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
|
@ -12,8 +12,8 @@
|
||||
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
@ -21,8 +21,6 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct BaseAddress;
|
||||
class DWARFContext;
|
||||
class Error;
|
||||
class raw_ostream;
|
||||
|
||||
@ -35,29 +33,10 @@ struct RangeListEntry : public DWARFListEntryBase {
|
||||
uint64_t Value0;
|
||||
uint64_t Value1;
|
||||
|
||||
Error extract(DWARFDataExtractor Data, uint32_t End, uint16_t Version,
|
||||
StringRef SectionName, uint32_t *OffsetPtr, bool isDWO = false);
|
||||
bool isEndOfList() const { return EntryKind == dwarf::DW_RLE_end_of_list; }
|
||||
bool isBaseAddressSelectionEntry() const {
|
||||
return EntryKind == dwarf::DW_RLE_base_address;
|
||||
}
|
||||
uint64_t getStartAddress() const {
|
||||
assert((EntryKind == dwarf::DW_RLE_start_end ||
|
||||
EntryKind == dwarf::DW_RLE_offset_pair ||
|
||||
EntryKind == dwarf::DW_RLE_startx_length) &&
|
||||
"Unexpected range list entry kind");
|
||||
return Value0;
|
||||
}
|
||||
uint64_t getEndAddress() const {
|
||||
assert((EntryKind == dwarf::DW_RLE_start_end ||
|
||||
EntryKind == dwarf::DW_RLE_offset_pair) &&
|
||||
"Unexpected range list entry kind");
|
||||
return Value1;
|
||||
}
|
||||
void dump(raw_ostream &OS, DWARFContext *C, uint8_t AddrSize,
|
||||
uint64_t &CurrentBase, unsigned Indent, uint16_t Version,
|
||||
uint8_t MaxEncodingStringLength = 0,
|
||||
DIDumpOptions DumpOpts = {}) const;
|
||||
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) const;
|
||||
bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; }
|
||||
};
|
||||
|
||||
/// A class representing a single rangelist.
|
||||
@ -70,12 +49,10 @@ public:
|
||||
|
||||
class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> {
|
||||
public:
|
||||
DWARFDebugRnglistTable(DWARFContext *C, StringRef SectionName,
|
||||
bool isDWO = false)
|
||||
: DWARFListTableBase(C, SectionName, isDWO,
|
||||
DWARFDebugRnglistTable()
|
||||
: DWARFListTableBase(/* SectionName = */ ".debug_rnglists",
|
||||
/* HeaderString = */ "ranges:",
|
||||
/* ListTypeString = */ "range",
|
||||
dwarf::RangeListEncodingString) {}
|
||||
/* ListTypeString = */ "range") {}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DWARFContext;
|
||||
|
||||
/// A base class for DWARF list entries, such as range or location list
|
||||
/// entries.
|
||||
struct DWARFListEntryBase {
|
||||
@ -39,7 +37,6 @@ struct DWARFListEntryBase {
|
||||
/// A base class for lists of entries that are extracted from a particular
|
||||
/// section, such as range lists or location lists.
|
||||
template <typename ListEntryType> class DWARFListType {
|
||||
public:
|
||||
using EntryType = ListEntryType;
|
||||
using ListEntries = std::vector<EntryType>;
|
||||
|
||||
@ -48,26 +45,11 @@ protected:
|
||||
|
||||
public:
|
||||
const ListEntries &getEntries() const { return Entries; }
|
||||
bool empty() const {
|
||||
return Entries.empty() || Entries.begin()->isEndOfList();
|
||||
}
|
||||
bool empty() const { return Entries.empty(); }
|
||||
void clear() { Entries.clear(); }
|
||||
uint32_t getOffset() const {
|
||||
if (Entries.empty())
|
||||
return 0;
|
||||
return Entries.begin()->Offset;
|
||||
}
|
||||
|
||||
/// Extract a list. The caller must pass the correct DWARF version.
|
||||
/// The end-of-list entry is retained as the last element of the vector of
|
||||
/// entries.
|
||||
Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
|
||||
uint16_t Version, uint32_t *OffsetPtr, StringRef SectionName,
|
||||
StringRef ListStringName, bool isDWO = false);
|
||||
void dump(raw_ostream &OS, DWARFContext *C, uint8_t AddressSize,
|
||||
uint64_t BaseAddress, unsigned Indent, uint16_t Version,
|
||||
size_t MaxEncodingStringLength = 0,
|
||||
DIDumpOptions DumpOpts = {}) const;
|
||||
uint32_t *OffsetPtr, StringRef SectionName,
|
||||
StringRef ListStringName);
|
||||
};
|
||||
|
||||
/// A class representing the header of a list table such as the range list
|
||||
@ -85,9 +67,9 @@ class DWARFListTableHeader {
|
||||
uint8_t AddrSize;
|
||||
/// The size in bytes of a segment selector on the target architecture.
|
||||
/// If the target system uses a flat address space, this value is 0.
|
||||
uint8_t SegSize = 0;
|
||||
uint8_t SegSize;
|
||||
/// The number of offsets that follow the header before the range lists.
|
||||
uint32_t OffsetEntryCount = 0;
|
||||
uint32_t OffsetEntryCount;
|
||||
};
|
||||
|
||||
Header HeaderData;
|
||||
@ -96,10 +78,10 @@ class DWARFListTableHeader {
|
||||
/// FIXME: Generate the table and use the appropriate forms.
|
||||
std::vector<uint32_t> Offsets;
|
||||
/// The table's format, either DWARF32 or DWARF64.
|
||||
dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32;
|
||||
dwarf::DwarfFormat Format;
|
||||
/// The offset at which the header (and hence the table) is located within
|
||||
/// its section.
|
||||
uint32_t HeaderOffset = 0;
|
||||
uint32_t HeaderOffset;
|
||||
/// The name of the section the list is located in.
|
||||
StringRef SectionName;
|
||||
/// A characterization of the list for dumping purposes, e.g. "range" or
|
||||
@ -115,19 +97,8 @@ public:
|
||||
Offsets.clear();
|
||||
}
|
||||
uint32_t getHeaderOffset() const { return HeaderOffset; }
|
||||
|
||||
uint8_t getAddrSize() const { return HeaderData.AddrSize; }
|
||||
void setAddrSize(uint8_t AddrSize) { HeaderData.AddrSize = AddrSize; }
|
||||
|
||||
uint32_t getLength() const { return HeaderData.Length; }
|
||||
void setLength(uint32_t Length) { HeaderData.Length = Length; }
|
||||
|
||||
uint16_t getVersion() const { return HeaderData.Version; }
|
||||
void setVersion(uint16_t Version) { HeaderData.Version = Version; }
|
||||
|
||||
uint8_t getSegSize() const { return HeaderData.SegSize; }
|
||||
uint32_t getOffsetEntryCount() const { return HeaderData.OffsetEntryCount; }
|
||||
|
||||
StringRef getSectionName() const { return SectionName; }
|
||||
StringRef getListTypeString() const { return ListTypeString; }
|
||||
dwarf::DwarfFormat getFormat() const { return Format; }
|
||||
@ -144,10 +115,8 @@ public:
|
||||
|
||||
/// Returns the length of the table, including the length field, or 0 if the
|
||||
/// length has not been determined (e.g. because the table has not yet been
|
||||
/// parsed, or there was a problem in parsing). In fake tables, such as for
|
||||
/// DWARF v4 and earlier, there is no header, so the length simply reflects
|
||||
/// the size of the section.
|
||||
uint32_t getTableLength() const;
|
||||
/// parsed, or there was a problem in parsing).
|
||||
uint32_t length() const;
|
||||
};
|
||||
|
||||
/// A class representing a table of lists as specified in the DWARF v5
|
||||
@ -160,22 +129,14 @@ template <typename DWARFListType> class DWARFListTableBase {
|
||||
/// A mapping between file offsets and lists. It is used to find a particular
|
||||
/// list based on an offset (obtained from DW_AT_ranges, for example).
|
||||
std::map<uint32_t, DWARFListType> ListMap;
|
||||
DWARFContext *C;
|
||||
/// True if this list is located in a split-DWARF (dwo or dwp) file.
|
||||
bool isDWO;
|
||||
/// This string is displayed as a heading before the list is dumped
|
||||
/// (e.g. "ranges:").
|
||||
StringRef HeaderString;
|
||||
/// A function returning the encoding string for a given list entry encoding,
|
||||
/// e.g. "DW_RLE_start_end".
|
||||
std::function<StringRef(unsigned)> EncodingString;
|
||||
|
||||
protected:
|
||||
DWARFListTableBase(DWARFContext *C, StringRef SectionName, bool isDWO,
|
||||
StringRef HeaderString, StringRef ListTypeString,
|
||||
std::function<StringRef(unsigned)> EncodingString)
|
||||
: Header(SectionName, ListTypeString), C(C), isDWO(isDWO),
|
||||
HeaderString(HeaderString), EncodingString(EncodingString) {}
|
||||
DWARFListTableBase(StringRef SectionName, StringRef HeaderString,
|
||||
StringRef ListTypeString)
|
||||
: Header(SectionName, ListTypeString), HeaderString(HeaderString) {}
|
||||
|
||||
public:
|
||||
void clear() {
|
||||
@ -186,28 +147,14 @@ public:
|
||||
Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) {
|
||||
return Header.extract(Data, OffsetPtr);
|
||||
}
|
||||
|
||||
/// Initialize the table header to explicit values. This is used for DWARF v4
|
||||
/// and earlier since there is no header that can be extracted from a section.
|
||||
void setHeaderData(uint32_t Length, uint16_t Version, uint8_t AddrSize) {
|
||||
assert(Header.getSegSize() == 0 &&
|
||||
"Unexpected segsize in list table header.");
|
||||
assert(Header.getOffsetEntryCount() == 0 &&
|
||||
"Unexpected offset entry count in list table header.");
|
||||
Header.setLength(Length);
|
||||
Header.setVersion(Version);
|
||||
Header.setAddrSize(AddrSize);
|
||||
}
|
||||
|
||||
/// Extract an entire table, including all list entries.
|
||||
Error extract(DWARFDataExtractor Data, uint16_t Version, uint32_t *OffsetPtr);
|
||||
Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
|
||||
/// Look up a list based on a given offset. Extract it and enter it into the
|
||||
/// list map if necessary.
|
||||
Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset);
|
||||
|
||||
uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); }
|
||||
uint8_t getAddrSize() const { return Header.getAddrSize(); }
|
||||
StringRef getListTypeString() const { return Header.getListTypeString(); }
|
||||
|
||||
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
|
||||
|
||||
@ -228,35 +175,25 @@ public:
|
||||
llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
|
||||
}
|
||||
|
||||
uint16_t getVersion() const { return Header.getVersion(); }
|
||||
uint32_t getLength() const { return Header.getTableLength(); }
|
||||
uint32_t length() { return Header.length(); }
|
||||
};
|
||||
|
||||
template <typename DWARFListType>
|
||||
Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
|
||||
uint16_t Version,
|
||||
uint32_t *OffsetPtr) {
|
||||
assert(Version > 0 && "DWARF version required and not given.");
|
||||
clear();
|
||||
// For DWARF v4 and earlier, we cannot extract a table header, so we
|
||||
// initialize it explicitly.
|
||||
if (Version < 5)
|
||||
setHeaderData(Data.size(), Version, Data.getAddressSize());
|
||||
else if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
|
||||
if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
|
||||
return E;
|
||||
|
||||
Data.setAddressSize(Header.getAddrSize());
|
||||
uint32_t End = getHeaderOffset() + getLength();
|
||||
// Extract all lists.
|
||||
uint32_t End = getHeaderOffset() + Header.length();
|
||||
while (*OffsetPtr < End) {
|
||||
DWARFListType CurrentList;
|
||||
uint32_t Off = *OffsetPtr;
|
||||
if (Error E = CurrentList.extract(
|
||||
Data, getHeaderOffset(), End, Header.getVersion(), OffsetPtr,
|
||||
Header.getSectionName(), Header.getListTypeString(), isDWO)) {
|
||||
*OffsetPtr = End;
|
||||
if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
|
||||
Header.getSectionName(),
|
||||
Header.getListTypeString()))
|
||||
return E;
|
||||
}
|
||||
ListMap[Off] = CurrentList;
|
||||
}
|
||||
|
||||
@ -267,10 +204,11 @@ Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
|
||||
}
|
||||
|
||||
template <typename ListEntryType>
|
||||
Error DWARFListType<ListEntryType>::extract(
|
||||
DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
|
||||
uint16_t Version, uint32_t *OffsetPtr, StringRef SectionName,
|
||||
StringRef ListTypeString, bool isDWO) {
|
||||
Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
|
||||
uint32_t HeaderOffset, uint32_t End,
|
||||
uint32_t *OffsetPtr,
|
||||
StringRef SectionName,
|
||||
StringRef ListTypeString) {
|
||||
if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
|
||||
return createStringError(errc::invalid_argument,
|
||||
"invalid %s list offset 0x%" PRIx32,
|
||||
@ -278,11 +216,10 @@ Error DWARFListType<ListEntryType>::extract(
|
||||
Entries.clear();
|
||||
while (*OffsetPtr < End) {
|
||||
ListEntryType Entry;
|
||||
if (Error E =
|
||||
Entry.extract(Data, End, Version, SectionName, OffsetPtr, isDWO))
|
||||
if (Error E = Entry.extract(Data, End, OffsetPtr))
|
||||
return E;
|
||||
Entries.push_back(Entry);
|
||||
if (Entry.isEndOfList())
|
||||
if (Entry.isSentinel())
|
||||
return Error::success();
|
||||
}
|
||||
return createStringError(errc::illegal_byte_sequence,
|
||||
@ -291,41 +228,28 @@ Error DWARFListType<ListEntryType>::extract(
|
||||
SectionName.data(), HeaderOffset);
|
||||
}
|
||||
|
||||
template <typename ListEntryType>
|
||||
void DWARFListType<ListEntryType>::dump(raw_ostream &OS, DWARFContext *C,
|
||||
uint8_t AddressSize,
|
||||
uint64_t BaseAddress, unsigned Indent,
|
||||
uint16_t Version,
|
||||
size_t MaxEncodingStringLength,
|
||||
DIDumpOptions DumpOpts) const {
|
||||
uint64_t CurrentBase = BaseAddress;
|
||||
for (const auto &Entry : Entries)
|
||||
Entry.dump(OS, C, AddressSize, CurrentBase, Indent, Version,
|
||||
MaxEncodingStringLength, DumpOpts);
|
||||
}
|
||||
|
||||
template <typename DWARFListType>
|
||||
void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS,
|
||||
DIDumpOptions DumpOpts) const {
|
||||
Header.dump(OS, DumpOpts);
|
||||
OS << HeaderString << "\n";
|
||||
|
||||
// Determine the length of the longest encoding string we have in the table,
|
||||
// so we can align the output properly. We only need this in verbose mode.
|
||||
size_t MaxEncodingStringLength = 0;
|
||||
// Don't dump the fake table header we create for DWARF v4 and earlier.
|
||||
if (Header.getVersion() > 4) {
|
||||
Header.dump(OS, DumpOpts);
|
||||
OS << HeaderString << '\n';
|
||||
// Determine the length of the longest encoding string we have in the table,
|
||||
// so we can align the output properly. We only need this in verbose mode.
|
||||
if (DumpOpts.Verbose)
|
||||
for (const auto &List : ListMap)
|
||||
for (const auto &Entry : List.second.getEntries())
|
||||
MaxEncodingStringLength = std::max(
|
||||
MaxEncodingStringLength, EncodingString(Entry.EntryKind).size());
|
||||
if (DumpOpts.Verbose) {
|
||||
for (const auto &List : ListMap)
|
||||
for (const auto &Entry : List.second.getEntries())
|
||||
MaxEncodingStringLength =
|
||||
std::max(MaxEncodingStringLength,
|
||||
dwarf::RangeListEncodingString(Entry.EntryKind).size());
|
||||
}
|
||||
|
||||
uint64_t CurrentBase = 0;
|
||||
for (const auto &List : ListMap) {
|
||||
List.second.dump(OS, C, getAddrSize(), CurrentBase, 0, Header.getVersion(),
|
||||
MaxEncodingStringLength, DumpOpts);
|
||||
}
|
||||
for (const auto &List : ListMap)
|
||||
for (const auto &Entry : List.second.getEntries())
|
||||
Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase,
|
||||
DumpOpts);
|
||||
}
|
||||
|
||||
template <typename DWARFListType>
|
||||
@ -338,11 +262,11 @@ DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
|
||||
|
||||
// Extract the list from the section and enter it into the list map.
|
||||
DWARFListType List;
|
||||
uint32_t End = getHeaderOffset() + getLength();
|
||||
uint32_t End = getHeaderOffset() + Header.length();
|
||||
uint32_t StartingOffset = Offset;
|
||||
if (Error E = List.extract(Data, getHeaderOffset(), End, Header.getVersion(),
|
||||
&Offset, Header.getSectionName(),
|
||||
Header.getListTypeString(), isDWO))
|
||||
if (Error E =
|
||||
List.extract(Data, getHeaderOffset(), End, &Offset,
|
||||
Header.getSectionName(), Header.getListTypeString()))
|
||||
return std::move(E);
|
||||
ListMap[StartingOffset] = List;
|
||||
return List;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
@ -305,6 +306,12 @@ public:
|
||||
return DataExtractor(StringSection, false, 0);
|
||||
}
|
||||
|
||||
/// Extract the range list referenced by this compile unit from the
|
||||
/// .debug_ranges section. If the extraction is unsuccessful, an error
|
||||
/// is returned. Successful extraction requires that the compile unit
|
||||
/// has already been extracted.
|
||||
Error extractRangeList(uint32_t RangeListOffset,
|
||||
DWARFDebugRangeList &RangeList) const;
|
||||
void clear();
|
||||
|
||||
const Optional<StrOffsetsContributionDescriptor> &
|
||||
|
@ -15,6 +15,7 @@ add_llvm_library(LLVMDebugInfoDWARF
|
||||
DWARFDebugLoc.cpp
|
||||
DWARFDebugMacro.cpp
|
||||
DWARFDebugPubTable.cpp
|
||||
DWARFDebugRangeList.cpp
|
||||
DWARFDebugRnglists.cpp
|
||||
DWARFDie.cpp
|
||||
DWARFExpression.cpp
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
@ -266,29 +267,24 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
|
||||
}
|
||||
}
|
||||
|
||||
// Dump a section that contains a sequence of tables of lists, such as range
|
||||
// or location list tables. In DWARF v5 we expect to find properly formatted
|
||||
// tables with headers. In DWARF v4 and earlier we simply expect a sequence of
|
||||
// lists, which we treat, mutatis mutandis, like DWARF v5 tables.
|
||||
template <typename ListTable>
|
||||
static void dumpListSection(raw_ostream &OS, DWARFContext *C,
|
||||
StringRef SectionName, uint16_t MaxVersion,
|
||||
DWARFDataExtractor &ListData,
|
||||
DIDumpOptions DumpOpts, bool isDWO = false) {
|
||||
// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
|
||||
static void dumpRnglistsSection(raw_ostream &OS,
|
||||
DWARFDataExtractor &rnglistData,
|
||||
DIDumpOptions DumpOpts) {
|
||||
uint32_t Offset = 0;
|
||||
while (ListData.isValidOffset(Offset)) {
|
||||
ListTable Table(C, SectionName, isDWO);
|
||||
if (Error Err = Table.extract(ListData, MaxVersion, &Offset)) {
|
||||
while (rnglistData.isValidOffset(Offset)) {
|
||||
llvm::DWARFDebugRnglistTable Rnglists;
|
||||
uint32_t TableOffset = Offset;
|
||||
if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
|
||||
WithColor::error() << toString(std::move(Err)) << '\n';
|
||||
// If table extraction set Offset to 0, it indicates that we cannot
|
||||
// continue to read the section.
|
||||
if (Offset == 0)
|
||||
uint64_t Length = Rnglists.length();
|
||||
// Keep going after an error, if we can, assuming that the length field
|
||||
// could be read. If it couldn't, stop reading the section.
|
||||
if (Length == 0)
|
||||
break;
|
||||
// In DWARF v4 and earlier, dump as much of the lists as we can.
|
||||
if (MaxVersion < 5)
|
||||
Table.dump(OS, DumpOpts);
|
||||
Offset = TableOffset + Length;
|
||||
} else {
|
||||
Table.dump(OS, DumpOpts);
|
||||
Rnglists.dump(OS, DumpOpts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -488,25 +484,29 @@ void DWARFContext::dump(
|
||||
uint8_t savedAddressByteSize = getCUAddrSize();
|
||||
DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(),
|
||||
isLittleEndian(), savedAddressByteSize);
|
||||
dumpListSection<DWARFDebugRnglistTable>(
|
||||
OS, this, ".debug_ranges", /* MaxVersion = */ 4, rangesData, DumpOpts);
|
||||
uint32_t offset = 0;
|
||||
DWARFDebugRangeList rangeList;
|
||||
while (rangesData.isValidOffset(offset)) {
|
||||
if (Error E = rangeList.extract(rangesData, &offset)) {
|
||||
WithColor::error() << toString(std::move(E)) << '\n';
|
||||
break;
|
||||
}
|
||||
rangeList.dump(OS);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
|
||||
DObj->getRnglistsSection().Data)) {
|
||||
DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
|
||||
isLittleEndian(), getCUAddrSize());
|
||||
dumpListSection<DWARFDebugRnglistTable>(
|
||||
OS, this, ".debug_rnglists", getMaxVersion(5), RnglistData, DumpOpts);
|
||||
isLittleEndian(), 0);
|
||||
dumpRnglistsSection(OS, RnglistData, DumpOpts);
|
||||
}
|
||||
|
||||
if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
|
||||
DObj->getRnglistsDWOSection().Data)) {
|
||||
DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
|
||||
isLittleEndian(), getCUAddrSize());
|
||||
dumpListSection<DWARFDebugRnglistTable>(OS, this, ".debug_rnglists.dwo",
|
||||
getMaxVersion(5), RnglistData,
|
||||
DumpOpts);
|
||||
isLittleEndian(), 0);
|
||||
dumpRnglistsSection(OS, RnglistData, DumpOpts);
|
||||
}
|
||||
|
||||
if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
|
||||
|
96
lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
Normal file
96
lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
//===- DWARFDebugRangesList.cpp -------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void DWARFDebugRangeList::clear() {
|
||||
Offset = -1U;
|
||||
AddressSize = 0;
|
||||
Entries.clear();
|
||||
}
|
||||
|
||||
Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
|
||||
uint32_t *offset_ptr) {
|
||||
clear();
|
||||
if (!data.isValidOffset(*offset_ptr))
|
||||
return createStringError(errc::invalid_argument,
|
||||
"invalid range list offset 0x%" PRIx32, *offset_ptr);
|
||||
|
||||
AddressSize = data.getAddressSize();
|
||||
if (AddressSize != 4 && AddressSize != 8)
|
||||
return createStringError(errc::invalid_argument,
|
||||
"invalid address size: %" PRIu8, AddressSize);
|
||||
Offset = *offset_ptr;
|
||||
while (true) {
|
||||
RangeListEntry Entry;
|
||||
Entry.SectionIndex = -1ULL;
|
||||
|
||||
uint32_t prev_offset = *offset_ptr;
|
||||
Entry.StartAddress = data.getRelocatedAddress(offset_ptr);
|
||||
Entry.EndAddress =
|
||||
data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex);
|
||||
|
||||
// Check that both values were extracted correctly.
|
||||
if (*offset_ptr != prev_offset + 2 * AddressSize) {
|
||||
clear();
|
||||
return createStringError(errc::invalid_argument,
|
||||
"invalid range list entry at offset 0x%" PRIx32,
|
||||
prev_offset);
|
||||
}
|
||||
if (Entry.isEndOfListEntry())
|
||||
break;
|
||||
Entries.push_back(Entry);
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void DWARFDebugRangeList::dump(raw_ostream &OS) const {
|
||||
for (const RangeListEntry &RLE : Entries) {
|
||||
const char *format_str = (AddressSize == 4
|
||||
? "%08x %08" PRIx64 " %08" PRIx64 "\n"
|
||||
: "%08x %016" PRIx64 " %016" PRIx64 "\n");
|
||||
OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress);
|
||||
}
|
||||
OS << format("%08x <End of list>\n", Offset);
|
||||
}
|
||||
|
||||
DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
|
||||
llvm::Optional<BaseAddress> BaseAddr) const {
|
||||
DWARFAddressRangesVector Res;
|
||||
for (const RangeListEntry &RLE : Entries) {
|
||||
if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
|
||||
BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
|
||||
continue;
|
||||
}
|
||||
|
||||
DWARFAddressRange E;
|
||||
E.LowPC = RLE.StartAddress;
|
||||
E.HighPC = RLE.EndAddress;
|
||||
E.SectionIndex = RLE.SectionIndex;
|
||||
// Base address of a range list entry is determined by the closest preceding
|
||||
// base address selection entry in the same range list. It defaults to the
|
||||
// base address of the compilation unit if there is no such entry.
|
||||
if (BaseAddr) {
|
||||
E.LowPC += BaseAddr->Address;
|
||||
E.HighPC += BaseAddr->Address;
|
||||
if (E.SectionIndex == -1ULL)
|
||||
E.SectionIndex = BaseAddr->SectionIndex;
|
||||
}
|
||||
Res.push_back(E);
|
||||
}
|
||||
return Res;
|
||||
}
|
@ -13,30 +13,19 @@
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
|
||||
uint16_t Version, StringRef /* SectionName */,
|
||||
uint32_t *OffsetPtr, bool /* isDWO */) {
|
||||
uint32_t *OffsetPtr) {
|
||||
Offset = *OffsetPtr;
|
||||
SectionIndex = -1ULL;
|
||||
|
||||
assert((Data.getAddressSize() == 4 || Data.getAddressSize() == 8) &&
|
||||
"Unsupported address size");
|
||||
|
||||
// We model a DWARF v4 range list entry like DWARF v5 DW_RLE_offset_pair,
|
||||
// since it is subject to base adjustment.
|
||||
uint8_t Encoding = dwarf::DW_RLE_offset_pair;
|
||||
if (Version > 4) {
|
||||
// The caller should guarantee that we have at least 1 byte available, so
|
||||
// we just assert instead of revalidate.
|
||||
assert(*OffsetPtr < End &&
|
||||
"not enough space to extract a rangelist encoding");
|
||||
Encoding = Data.getU8(OffsetPtr);
|
||||
}
|
||||
// The caller should guarantee that we have at least 1 byte available, so
|
||||
// we just assert instead of revalidate.
|
||||
assert(*OffsetPtr < End &&
|
||||
"not enough space to extract a rangelist encoding");
|
||||
uint8_t Encoding = Data.getU8(OffsetPtr);
|
||||
|
||||
switch (Encoding) {
|
||||
case dwarf::DW_RLE_end_of_list:
|
||||
@ -59,23 +48,6 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
|
||||
"at offset 0x%" PRIx32,
|
||||
*OffsetPtr - 1);
|
||||
case dwarf::DW_RLE_offset_pair: {
|
||||
if (Version < 5) {
|
||||
if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
|
||||
return createStringError(
|
||||
errc::illegal_byte_sequence,
|
||||
"invalid range list entry at offset 0x%" PRIx32, *OffsetPtr);
|
||||
Value0 = Data.getRelocatedAddress(OffsetPtr);
|
||||
Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
|
||||
// Adjust the EntryKind for end-of-list and base_address based on the
|
||||
// contents.
|
||||
if (Value0 == maxUIntN(Data.getAddressSize() * 8)) {
|
||||
Encoding = dwarf::DW_RLE_base_address;
|
||||
Value0 = Value1;
|
||||
Value1 = 0;
|
||||
} else if (Value0 == 0 && Value1 == 0)
|
||||
Encoding = dwarf::DW_RLE_end_of_list;
|
||||
break;
|
||||
}
|
||||
uint32_t PreviousOffset = *OffsetPtr - 1;
|
||||
Value0 = Data.getULEB128(OffsetPtr);
|
||||
Value1 = Data.getULEB128(OffsetPtr);
|
||||
@ -86,7 +58,7 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
|
||||
PreviousOffset);
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_RLE_base_address:
|
||||
case dwarf::DW_RLE_base_address: {
|
||||
if ((End - *OffsetPtr) < Data.getAddressSize())
|
||||
return createStringError(errc::invalid_argument,
|
||||
"insufficient space remaining in table for "
|
||||
@ -94,16 +66,18 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
|
||||
*OffsetPtr - 1);
|
||||
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
|
||||
break;
|
||||
case dwarf::DW_RLE_start_end:
|
||||
}
|
||||
case dwarf::DW_RLE_start_end: {
|
||||
if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
|
||||
return createStringError(errc::invalid_argument,
|
||||
"insufficient space remaining in table for "
|
||||
"DW_RLE_start_end encoding "
|
||||
"at offset 0x%" PRIx32,
|
||||
*OffsetPtr - 1);
|
||||
Value0 = Data.getRelocatedAddress(OffsetPtr);
|
||||
Value1 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
|
||||
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
|
||||
Value1 = Data.getRelocatedAddress(OffsetPtr);
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_RLE_start_length: {
|
||||
uint32_t PreviousOffset = *OffsetPtr - 1;
|
||||
Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
|
||||
@ -169,10 +143,9 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
|
||||
return Res;
|
||||
}
|
||||
|
||||
void RangeListEntry::dump(raw_ostream &OS, DWARFContext *, uint8_t AddrSize,
|
||||
uint64_t &CurrentBase, unsigned Indent,
|
||||
uint16_t Version, uint8_t MaxEncodingStringLength,
|
||||
DIDumpOptions DumpOpts) const {
|
||||
void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize,
|
||||
uint8_t MaxEncodingStringLength,
|
||||
uint64_t &CurrentBase, DIDumpOptions DumpOpts) const {
|
||||
auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
|
||||
uint8_t AddrSize, DIDumpOptions DumpOpts) {
|
||||
if (DumpOpts.Verbose) {
|
||||
@ -183,49 +156,27 @@ void RangeListEntry::dump(raw_ostream &OS, DWARFContext *, uint8_t AddrSize,
|
||||
}
|
||||
};
|
||||
|
||||
// Output indentations before we print the actual entry. We only print
|
||||
// anything for DW_RLE_base_address when we are in verbose mode.
|
||||
if (DumpOpts.Verbose || !isBaseAddressSelectionEntry())
|
||||
OS.indent(Indent);
|
||||
|
||||
if (DumpOpts.Verbose) {
|
||||
// Print the section offset in verbose mode.
|
||||
OS << format("0x%8.8" PRIx32 ":", Offset);
|
||||
if (Version > 4) {
|
||||
auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
|
||||
// Unsupported encodings should have been reported during parsing.
|
||||
assert(!EncodingString.empty() && "Unknown range entry encoding");
|
||||
OS << format(" [%s%*c", EncodingString.data(),
|
||||
MaxEncodingStringLength - EncodingString.size() + 1, ']');
|
||||
if (!isEndOfList())
|
||||
OS << ": ";
|
||||
}
|
||||
auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
|
||||
// Unsupported encodings should have been reported during parsing.
|
||||
assert(!EncodingString.empty() && "Unknown range entry encoding");
|
||||
OS << format(" [%s%*c", EncodingString.data(),
|
||||
MaxEncodingStringLength - EncodingString.size() + 1, ']');
|
||||
if (EntryKind != dwarf::DW_RLE_end_of_list)
|
||||
OS << ": ";
|
||||
}
|
||||
|
||||
switch (EntryKind) {
|
||||
case dwarf::DW_RLE_end_of_list:
|
||||
if (DumpOpts.Verbose) {
|
||||
// For DWARF v4 and earlier, we print the raw entry, i.e. 2 zeros.
|
||||
if (Version < 5) {
|
||||
OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
|
||||
OS << format(", 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
OS << "<End of list>";
|
||||
OS << (DumpOpts.Verbose ? "" : "<End of list>");
|
||||
break;
|
||||
case dwarf::DW_RLE_base_address:
|
||||
// In non-verbose mode, we do not print anything for this entry.
|
||||
// In non-verbose mode we do not print anything for this entry.
|
||||
CurrentBase = Value0;
|
||||
if (!DumpOpts.Verbose)
|
||||
return;
|
||||
if (Version < 5) {
|
||||
// Dump the entry in pre-DWARF v5 format, i.e. with a -1 as Value0.
|
||||
uint64_t allOnes = maxUIntN(AddrSize * 8);
|
||||
OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, allOnes);
|
||||
OS << format(", 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
|
||||
break;
|
||||
}
|
||||
OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
|
||||
break;
|
||||
case dwarf::DW_RLE_start_length:
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
|
||||
|
@ -20,43 +20,30 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
|
||||
uint32_t *OffsetPtr) {
|
||||
HeaderOffset = *OffsetPtr;
|
||||
// Read and verify the length field.
|
||||
if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) {
|
||||
// By setting *OffsetPtr to 0, we indicate to the caller that
|
||||
// we could not detemine the length of the table.
|
||||
*OffsetPtr = 0;
|
||||
if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
|
||||
return createStringError(errc::invalid_argument,
|
||||
"section is not large enough to contain a "
|
||||
"%s table length at offset 0x%" PRIx32,
|
||||
SectionName.data(), HeaderOffset);
|
||||
}
|
||||
SectionName.data(), *OffsetPtr);
|
||||
// TODO: Add support for DWARF64.
|
||||
HeaderData.Length = Data.getU32(OffsetPtr);
|
||||
if (HeaderData.Length == 0xffffffffu) {
|
||||
*OffsetPtr = 0;
|
||||
if (HeaderData.Length == 0xffffffffu)
|
||||
return createStringError(errc::not_supported,
|
||||
"DWARF64 is not supported in %s at offset 0x%" PRIx32,
|
||||
SectionName.data(), HeaderOffset);
|
||||
}
|
||||
|
||||
uint32_t TableLength = HeaderData.Length + sizeof(uint32_t);
|
||||
uint32_t End = HeaderOffset + TableLength;
|
||||
Format = dwarf::DwarfFormat::DWARF32;
|
||||
if (TableLength < sizeof(Header)) {
|
||||
*OffsetPtr = End;
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"%s table at offset 0x%" PRIx32 " has too small length (0x%" PRIx32
|
||||
") to contain a complete header",
|
||||
SectionName.data(), HeaderOffset, TableLength);
|
||||
}
|
||||
if (!Data.isValidOffsetForDataOfSize(HeaderOffset, TableLength)) {
|
||||
*OffsetPtr = 0; // No recovery if the length exceeds the section size.
|
||||
return createStringError(
|
||||
errc::invalid_argument,
|
||||
"section is not large enough to contain a %s table "
|
||||
"of length 0x%" PRIx32 " at offset 0x%" PRIx32,
|
||||
SectionName.data(), TableLength, HeaderOffset);
|
||||
}
|
||||
if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header))
|
||||
return createStringError(errc::invalid_argument,
|
||||
"%s table at offset 0x%" PRIx32
|
||||
" has too small length (0x%" PRIx32
|
||||
") to contain a complete header",
|
||||
SectionName.data(), HeaderOffset, length());
|
||||
uint32_t End = HeaderOffset + length();
|
||||
if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset))
|
||||
return createStringError(errc::invalid_argument,
|
||||
"section is not large enough to contain a %s table "
|
||||
"of length 0x%" PRIx32 " at offset 0x%" PRIx32,
|
||||
SectionName.data(), length(), HeaderOffset);
|
||||
|
||||
HeaderData.Version = Data.getU16(OffsetPtr);
|
||||
HeaderData.AddrSize = Data.getU8(OffsetPtr);
|
||||
@ -64,36 +51,27 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
|
||||
HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr);
|
||||
|
||||
// Perform basic validation of the remaining header fields.
|
||||
if (HeaderData.Version != 5) {
|
||||
*OffsetPtr = End;
|
||||
if (HeaderData.Version != 5)
|
||||
return createStringError(errc::invalid_argument,
|
||||
"unrecognised %s table version %" PRIu16
|
||||
" in table at offset 0x%" PRIx32,
|
||||
SectionName.data(), HeaderData.Version,
|
||||
HeaderOffset);
|
||||
}
|
||||
if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) {
|
||||
*OffsetPtr = End;
|
||||
"unrecognised %s table version %" PRIu16
|
||||
" in table at offset 0x%" PRIx32,
|
||||
SectionName.data(), HeaderData.Version, HeaderOffset);
|
||||
if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
|
||||
return createStringError(errc::not_supported,
|
||||
"%s table at offset 0x%" PRIx32
|
||||
" has unsupported address size %" PRIu8,
|
||||
SectionName.data(), HeaderOffset, HeaderData.AddrSize);
|
||||
}
|
||||
if (HeaderData.SegSize != 0) {
|
||||
*OffsetPtr = End;
|
||||
if (HeaderData.SegSize != 0)
|
||||
return createStringError(errc::not_supported,
|
||||
"%s table at offset 0x%" PRIx32
|
||||
" has unsupported segment selector size %" PRIu8,
|
||||
SectionName.data(), HeaderOffset, HeaderData.SegSize);
|
||||
}
|
||||
if (End < HeaderOffset + sizeof(HeaderData) +
|
||||
HeaderData.OffsetEntryCount * sizeof(uint32_t)) {
|
||||
*OffsetPtr = End;
|
||||
HeaderData.OffsetEntryCount * sizeof(uint32_t))
|
||||
return createStringError(errc::invalid_argument,
|
||||
"%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32
|
||||
") than there is space for",
|
||||
SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount);
|
||||
}
|
||||
Data.setAddressSize(HeaderData.AddrSize);
|
||||
for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
|
||||
Offsets.push_back(Data.getU32(OffsetPtr));
|
||||
@ -123,11 +101,9 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DWARFListTableHeader::getTableLength() const {
|
||||
uint32_t DWARFListTableHeader::length() const {
|
||||
if (HeaderData.Length == 0)
|
||||
return 0;
|
||||
assert(HeaderData.Version > 0 &&
|
||||
"No DWARF version in header when using getTableLength()");
|
||||
// TODO: DWARF64 support.
|
||||
return HeaderData.Length + (HeaderData.Version > 4) * sizeof(uint32_t);
|
||||
return HeaderData.Length + sizeof(uint32_t);
|
||||
}
|
||||
|
@ -264,16 +264,13 @@ bool DWARFUnitHeader::extract(DWARFContext &Context,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse a list table header, including the optional array of offsets
|
||||
// Parse the rangelist table header, including the optional array of offsets
|
||||
// following it (DWARF v5 and later).
|
||||
template <typename DWARFListTable>
|
||||
static Expected<DWARFListTable>
|
||||
parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C,
|
||||
StringRef SectionName, uint32_t Offset, bool isDWO) {
|
||||
static Expected<DWARFDebugRnglistTable>
|
||||
parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
|
||||
// TODO: Support DWARF64
|
||||
// We are expected to be called with Offset 0 or pointing just past the table
|
||||
// header, which is 12 bytes long for DWARF32.
|
||||
DWARFListTable Table(C, SectionName, isDWO);
|
||||
if (Offset > 0) {
|
||||
if (Offset < 12U)
|
||||
return createStringError(errc::invalid_argument, "Did not detect a valid"
|
||||
@ -281,46 +278,20 @@ parseListTableHeader(DWARFDataExtractor DA, DWARFContext *C,
|
||||
Offset);
|
||||
Offset -= 12U;
|
||||
}
|
||||
llvm::DWARFDebugRnglistTable Table;
|
||||
if (Error E = Table.extractHeaderAndOffsets(DA, &Offset))
|
||||
return std::move(E);
|
||||
return Table;
|
||||
}
|
||||
|
||||
// Parse a DWARF v5 list table (e.g. either a rangelist table or a location
|
||||
// list table). For DWARF units with version 4 or earlier, we instead create
|
||||
// the table artifically by giving it a size that equals the section size.
|
||||
template <typename DWARFListTable>
|
||||
static Optional<DWARFListTable>
|
||||
setupListTable(DWARFUnit *U, const DWARFSection *Section, StringRef SectionName,
|
||||
uint32_t &Base, bool isDWO, bool isLittleEndian) {
|
||||
if (!Section->Data.size())
|
||||
return None;
|
||||
DWARFContext &Ctx = U->getContext();
|
||||
DWARFListTable Table(&Ctx, SectionName, isDWO);
|
||||
// Parse the list table header. Individual lists are extracted lazily.
|
||||
DWARFDataExtractor DA(Ctx.getDWARFObj(), *Section, isLittleEndian,
|
||||
U->getAddressByteSize());
|
||||
if (U->getVersion() < 5) {
|
||||
Base = 0;
|
||||
Table.setHeaderData(Section->Data.size(), U->getVersion(),
|
||||
DA.getAddressSize());
|
||||
return Table;
|
||||
}
|
||||
if (auto TableOrError = parseListTableHeader<DWARFListTable>(
|
||||
DA, &Ctx, SectionName, Base, isDWO))
|
||||
Table = TableOrError.get();
|
||||
else {
|
||||
WithColor::error() << "parsing a " << Table.getListTypeString().data()
|
||||
<< " list table: " << toString(TableOrError.takeError())
|
||||
<< '\n';
|
||||
return None;
|
||||
}
|
||||
// In a split dwarf unit, there are no attributes like DW_AT_rnglists_base or
|
||||
// DW_AT_loclists_base that describe the table base. Adjust Base to point past
|
||||
// the table header which is expected to start at offset 0.
|
||||
if (isDWO)
|
||||
Base = Table.getHeaderSize();
|
||||
return Table;
|
||||
Error DWARFUnit::extractRangeList(uint32_t RangeListOffset,
|
||||
DWARFDebugRangeList &RangeList) const {
|
||||
// Require that compile unit is extracted.
|
||||
assert(!DieArray.empty());
|
||||
DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
|
||||
isLittleEndian, getAddressByteSize());
|
||||
uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
|
||||
return RangeList.extract(RangesData, &ActualRangeListOffset);
|
||||
}
|
||||
|
||||
void DWARFUnit::clear() {
|
||||
@ -440,20 +411,31 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
|
||||
|
||||
// DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
|
||||
// describe address ranges.
|
||||
StringRef RangeSectionName = ".debug_ranges";
|
||||
if (getVersion() >= 5) {
|
||||
if (isDWO) {
|
||||
RangeSectionName = ".debug_rnglists.dwo";
|
||||
if (isDWO)
|
||||
setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
|
||||
} else {
|
||||
RangeSectionName = ".debug_rnglists";
|
||||
else
|
||||
setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
|
||||
toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0));
|
||||
if (RangeSection->Data.size()) {
|
||||
// Parse the range list table header. Individual range lists are
|
||||
// extracted lazily.
|
||||
DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
|
||||
isLittleEndian, 0);
|
||||
if (auto TableOrError =
|
||||
parseRngListTableHeader(RangesDA, RangeSectionBase))
|
||||
RngListTable = TableOrError.get();
|
||||
else
|
||||
WithColor::error() << "parsing a range list table: "
|
||||
<< toString(TableOrError.takeError())
|
||||
<< '\n';
|
||||
|
||||
// In a split dwarf unit, there is no DW_AT_rnglists_base attribute.
|
||||
// Adjust RangeSectionBase to point past the table header.
|
||||
if (isDWO && RngListTable)
|
||||
RangeSectionBase = RngListTable->getHeaderSize();
|
||||
}
|
||||
}
|
||||
RngListTable = setupListTable<DWARFDebugRnglistTable>(
|
||||
this, RangeSection, RangeSectionName, RangeSectionBase, isDWO,
|
||||
isLittleEndian);
|
||||
|
||||
// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
|
||||
// skeleton CU DIE, so that DWARF users not aware of it are not broken.
|
||||
@ -495,9 +477,16 @@ bool DWARFUnit::parseDWO() {
|
||||
DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
|
||||
if (getVersion() >= 5) {
|
||||
DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
|
||||
DWO->RngListTable = setupListTable<DWARFDebugRnglistTable>(
|
||||
DWOCU, DWO->RangeSection, ".debug_rnglists.dwo", DWO->RangeSectionBase,
|
||||
/* isDWO =*/true, isLittleEndian);
|
||||
DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
|
||||
isLittleEndian, 0);
|
||||
if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase))
|
||||
DWO->RngListTable = TableOrError.get();
|
||||
else
|
||||
WithColor::error() << "parsing a range list table: "
|
||||
<< toString(TableOrError.takeError())
|
||||
<< '\n';
|
||||
if (DWO->RngListTable)
|
||||
DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize();
|
||||
} else {
|
||||
auto DWORangesBase = UnitDie.getRangesBaseAttribute();
|
||||
DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
|
||||
@ -515,6 +504,12 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
|
||||
|
||||
Expected<DWARFAddressRangesVector>
|
||||
DWARFUnit::findRnglistFromOffset(uint32_t Offset) {
|
||||
if (getVersion() <= 4) {
|
||||
DWARFDebugRangeList RangeList;
|
||||
if (Error E = extractRangeList(Offset, RangeList))
|
||||
return std::move(E);
|
||||
return RangeList.getAbsoluteRanges(getBaseAddress());
|
||||
}
|
||||
if (RngListTable) {
|
||||
DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
|
||||
isLittleEndian, RngListTable->getAddrSize());
|
||||
|
@ -4,18 +4,18 @@
|
||||
|
||||
; Check that we emit ranges for this which has a non-traditional section and a normal section.
|
||||
|
||||
; CHECK: .debug_info contents:
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK-NOT: DW_TAG
|
||||
; CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x
|
||||
; CHECK-NEXT: [0x{{[0-9A-Fa-f]+}}, 0x{{[0-9A-Fa-f]+}})
|
||||
; CHECK-NEXT: [0x{{[0-9A-Fa-f]+}}, 0x{{[0-9A-Fa-f]+}}){{.*}})
|
||||
; CHECK: DW_TAG_subprogram
|
||||
; CHECK: DW_AT_low_pc
|
||||
; CHECK: DW_AT_high_pc
|
||||
; CHECK: DW_TAG_subprogram
|
||||
; CHECK: DW_AT_low_pc
|
||||
; CHECK: DW_AT_high_pc
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK: DW_AT_ranges
|
||||
; CHECK: DW_TAG_subprogram
|
||||
; CHECK: DW_AT_low_pc
|
||||
; CHECK: DW_AT_high_pc
|
||||
; CHECK: DW_TAG_subprogram
|
||||
; CHECK: DW_AT_low_pc
|
||||
; CHECK: DW_AT_high_pc
|
||||
|
||||
; CHECK: .debug_ranges contents:
|
||||
; FIXME: When we get better dumping facilities we'll want to elaborate here.
|
||||
; CHECK: 00000000 <End of list>
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define i32 @foo(i32 %a) #0 section "__TEXT,__foo" !dbg !4 {
|
||||
|
@ -83,7 +83,7 @@
|
||||
; written in relocation places (dumper needs to be fixed to read the
|
||||
; relocations rather than interpret that as the end of a range list))
|
||||
|
||||
; CHECK: 0x{{[0-9A-Fa-f]+}}: 0x{{0+}}, 0x{{0+}}
|
||||
; CHECK: 00000000 <End of list>
|
||||
|
||||
|
||||
; Check that we don't emit any pubnames or pubtypes under -gmlt
|
||||
|
@ -1,6 +1,5 @@
|
||||
# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
|
||||
# RUN: llvm-dwarfdump -v %t 2>%t.err | FileCheck %s
|
||||
# RUN: llvm-dwarfdump --debug-ranges %t | FileCheck --check-prefix=TERSE %s
|
||||
# RUN: FileCheck %s <%t.err -check-prefix=ERR
|
||||
|
||||
# CHECK: .debug_info contents:
|
||||
@ -11,24 +10,6 @@
|
||||
# CHECK-NEXT: [0x0000000000000003, 0x0000000000000006) ".text"
|
||||
# CHECK-NEXT: [0x0000000000000001, 0x0000000000000002) ".text.foo1")
|
||||
|
||||
# CHECK: .debug_ranges contents:
|
||||
# CHECK-NEXT: 0x00000000: 0x0000000000000000, 0x0000000000000001 =>
|
||||
# CHECK-SAME: [0x0000000000000000, 0x0000000000000001)
|
||||
# CHECK-NEXT: 0x00000010: 0x0000000000000003, 0x0000000000000006 =>
|
||||
# CHECK-SAME: [0x0000000000000003, 0x0000000000000006)
|
||||
# CHECK-NEXT: 0x00000020: 0xffffffffffffffff, 0x0000000000000000
|
||||
# CHECK-NEXT: 0x00000030: 0x0000000000000001, 0x0000000000000002 =>
|
||||
# CHECK-SAME: [0x0000000000000001, 0x0000000000000002)
|
||||
# CHECK-NEXT: 0x00000040: 0x0000000000000000, 0x0000000000000000
|
||||
|
||||
# TERSE: .debug_ranges contents:
|
||||
# TERSE-NEXT: [0x0000000000000000, 0x0000000000000001)
|
||||
# TERSE-NEXT: [0x0000000000000003, 0x0000000000000006)
|
||||
# TERSE-NEXT: [0x0000000000000001, 0x0000000000000002)
|
||||
# TERSE-NEXT: <End of list>
|
||||
|
||||
|
||||
|
||||
.text
|
||||
.globl foo
|
||||
.type foo,@function
|
||||
|
@ -9,13 +9,10 @@
|
||||
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000003) ".text.foo2" [5])
|
||||
|
||||
# CHECK: .debug_ranges contents:
|
||||
# CHECK-NEXT: 0x00000000: 0x0000000000000000, 0x0000000000000001 =>
|
||||
# CHECK-SAME: [0x0000000000000000, 0x0000000000000001)
|
||||
# CHECK-NEXT: 0x00000010: 0x0000000000000000, 0x0000000000000002 =>
|
||||
# CHECK-SAME: [0x0000000000000000, 0x0000000000000002)
|
||||
# CHECK-NEXT: 0x00000020: 0x0000000000000000, 0x0000000000000003 =>
|
||||
# CHECK-SAME: [0x0000000000000000, 0x0000000000000003)
|
||||
# CHCKK-NEXT: 0x00000030: 0x0000000000000000, 0x0000000000000000
|
||||
# CHECK: 00000000 0000000000000000 0000000000000001
|
||||
# CHECK: 00000000 0000000000000000 0000000000000002
|
||||
# CHECK: 00000000 0000000000000000 0000000000000003
|
||||
# CHECK: 00000000 <End of list>
|
||||
|
||||
# RUN: llvm-dwarfdump %t | FileCheck %s --check-prefix=BRIEF
|
||||
# BRIEF: DW_TAG_compile_unit
|
||||
|
@ -1,5 +1,4 @@
|
||||
RUN: llvm-dwarfdump -v %p/Inputs/dwarfdump-test4.elf-x86-64 | FileCheck %s
|
||||
RUN: llvm-dwarfdump --debug-ranges %p/Inputs/dwarfdump-test4.elf-x86-64 | FileCheck -check-prefix=TERSE %s
|
||||
|
||||
CHECK: .debug_info contents:
|
||||
CHECK: DW_TAG_compile_unit
|
||||
@ -16,21 +15,10 @@ CHECK-NEXT: [0x0000000000000637, 0x000000000000063d))
|
||||
|
||||
|
||||
CHECK: .debug_ranges contents:
|
||||
CHECK-NEXT: 0x00000000: 0x000000000000062c, 0x0000000000000637 =>
|
||||
CHECK-SAME: [0x000000000000062c, 0x0000000000000637)
|
||||
CHECK-NEXT: 0x00000010: 0x0000000000000637, 0x000000000000063d =>
|
||||
CHECK-SAME: [0x0000000000000637, 0x000000000000063d)
|
||||
CHECK-NEXT: 0x00000020: 0x0000000000000000, 0x0000000000000000
|
||||
CHECK-NEXT: 0x00000030: 0x0000000000000640, 0x000000000000064b =>
|
||||
CHECK-SAME: [0x0000000000000640, 0x000000000000064b)
|
||||
CHECK-NEXT: 0x00000040: 0x0000000000000637, 0x000000000000063d =>
|
||||
CHECK-SAME: [0x0000000000000637, 0x000000000000063d)
|
||||
CHECK-NEXT: 0x00000050: 0x0000000000000000, 0x0000000000000000
|
||||
CHECK-NEXT: 00000000 000000000000062c 0000000000000637
|
||||
CHECK-NEXT: 00000000 0000000000000637 000000000000063d
|
||||
CHECK-NEXT: 00000000 <End of list>
|
||||
CHECK-NEXT: 00000030 0000000000000640 000000000000064b
|
||||
CHECK-NEXT: 00000030 0000000000000637 000000000000063d
|
||||
CHECK-NEXT: 00000030 <End of list>
|
||||
|
||||
TERSE: .debug_ranges contents:
|
||||
TERSE-NEXT: [0x000000000000062c, 0x0000000000000637)
|
||||
TERSE-NEXT: [0x0000000000000637, 0x000000000000063d)
|
||||
TERSE-NEXT: <End of list>
|
||||
TERSE-NEXT: [0x0000000000000640, 0x000000000000064b)
|
||||
TERSE-NEXT: [0x0000000000000637, 0x000000000000063d)
|
||||
TERSE-NEXT: <End of list>
|
||||
|
@ -64,11 +64,12 @@ b:
|
||||
|
||||
|
||||
// DWARF: .debug_ranges contents:
|
||||
// DWARF-NEXT: 0x00000000: 0xffffffff, 0x00000000
|
||||
// DWARF-NEXT: 0x00000008: 0x00000000, 0x00000004 => [0x00000000, 0x00000004)
|
||||
// DWARF-NEXT: 0x00000010: 0xffffffff, 0x00000000
|
||||
// DWARF-NEXT: 0x00000018: 0x00000000, 0x00000004 => [0x00000000, 0x00000004)
|
||||
// DWARF-NEXT: 0x00000020: 0x00000000, 0x00000000
|
||||
// DWARF: 00000000 ffffffff 00000000
|
||||
// DWARF: 00000000 00000000 00000004
|
||||
// DWARF: 00000000 ffffffff 00000000
|
||||
// DWARF: 00000000 00000000 00000004
|
||||
// DWARF: 00000000 <End of list>
|
||||
|
||||
|
||||
|
||||
// Offsets are different in DWARF v5 due to different header layout.
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
|
||||
@ -1575,7 +1576,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
|
||||
void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
|
||||
DWARFContext &OrigDwarf,
|
||||
const DebugMapObject &DMO) const {
|
||||
DWARFDebugRnglist RangeList;
|
||||
DWARFDebugRangeList RangeList;
|
||||
const auto &FunctionRanges = Unit.getFunctionRanges();
|
||||
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
|
||||
DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
|
||||
@ -1595,30 +1596,28 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
|
||||
for (const auto &RangeAttribute : Unit.getRangesAttributes()) {
|
||||
uint32_t Offset = RangeAttribute.get();
|
||||
RangeAttribute.set(Streamer->getRangesSectionSize());
|
||||
if (Error E = RangeList.extract(RangeExtractor, /* HeaderOffset = */0,
|
||||
RangeExtractor.size(),
|
||||
Unit.getOrigUnit().getVersion(), &Offset,
|
||||
".debug_ranges", "range")) {
|
||||
if (Error E = RangeList.extract(RangeExtractor, &Offset)) {
|
||||
llvm::consumeError(std::move(E));
|
||||
reportWarning("invalid range list ignored.", DMO);
|
||||
RangeList.clear();
|
||||
}
|
||||
const auto &Entries = RangeList.getEntries();
|
||||
if (!RangeList.empty()) {
|
||||
const auto &First = Entries.front();
|
||||
if (!Entries.empty()) {
|
||||
const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
|
||||
|
||||
if (CurrRange == InvalidRange ||
|
||||
First.getStartAddress() + OrigLowPc < CurrRange.start() ||
|
||||
First.getStartAddress() + OrigLowPc >= CurrRange.stop()) {
|
||||
CurrRange = FunctionRanges.find(First.getStartAddress() + OrigLowPc);
|
||||
First.StartAddress + OrigLowPc < CurrRange.start() ||
|
||||
First.StartAddress + OrigLowPc >= CurrRange.stop()) {
|
||||
CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc);
|
||||
if (CurrRange == InvalidRange ||
|
||||
CurrRange.start() > First.getStartAddress() + OrigLowPc) {
|
||||
CurrRange.start() > First.StartAddress + OrigLowPc) {
|
||||
reportWarning("no mapping for range.", DMO);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Streamer->emitRangesEntries(UnitPcOffset, OrigLowPc, CurrRange, RangeList,
|
||||
Streamer->emitRangesEntries(UnitPcOffset, OrigLowPc, CurrRange, Entries,
|
||||
AddressSize);
|
||||
}
|
||||
}
|
||||
|
@ -269,27 +269,28 @@ void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
|
||||
void DwarfStreamer::emitRangesEntries(
|
||||
int64_t UnitPcOffset, uint64_t OrigLowPc,
|
||||
const FunctionIntervals::const_iterator &FuncRange,
|
||||
const DWARFDebugRnglist &RangeList, unsigned AddressSize) {
|
||||
const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
|
||||
unsigned AddressSize) {
|
||||
MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
|
||||
|
||||
// Offset each range by the right amount.
|
||||
int64_t PcOffset = RangeList.empty() ? 0 : FuncRange.value() + UnitPcOffset;
|
||||
for (const auto &Range : RangeList.getEntries()) {
|
||||
if (Range.isBaseAddressSelectionEntry()) {
|
||||
int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset;
|
||||
for (const auto &Range : Entries) {
|
||||
if (Range.isBaseAddressSelectionEntry(AddressSize)) {
|
||||
warn("unsupported base address selection operation",
|
||||
"emitting debug_ranges");
|
||||
break;
|
||||
}
|
||||
// Do not emit empty ranges.
|
||||
if (Range.isEndOfList() || Range.getStartAddress() == Range.getEndAddress())
|
||||
if (Range.StartAddress == Range.EndAddress)
|
||||
continue;
|
||||
|
||||
// All range entries should lie in the function range.
|
||||
if (!(Range.getStartAddress() + OrigLowPc >= FuncRange.start() &&
|
||||
Range.getEndAddress() + OrigLowPc <= FuncRange.stop()))
|
||||
if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() &&
|
||||
Range.EndAddress + OrigLowPc <= FuncRange.stop()))
|
||||
warn("inconsistent range data.", "emitting debug_ranges");
|
||||
MS->EmitIntValue(Range.getStartAddress() + PcOffset, AddressSize);
|
||||
MS->EmitIntValue(Range.getEndAddress() + PcOffset, AddressSize);
|
||||
MS->EmitIntValue(Range.StartAddress + PcOffset, AddressSize);
|
||||
MS->EmitIntValue(Range.EndAddress + PcOffset, AddressSize);
|
||||
RangesSectionSize += 2 * AddressSize;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "llvm/CodeGen/AccelTable.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
@ -83,7 +83,7 @@ public:
|
||||
void emitRangesEntries(
|
||||
int64_t UnitPcOffset, uint64_t OrigLowPc,
|
||||
const FunctionIntervals::const_iterator &FuncRange,
|
||||
const DWARFDebugRnglist &RangeList,
|
||||
const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
|
||||
unsigned AddressSize);
|
||||
|
||||
/// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true,
|
||||
|
Loading…
Reference in New Issue
Block a user