in folly/experimental/symbolizer/DwarfImpl.cpp [373:497]
bool DwarfImpl::isAddrInRangeList(
uint64_t address,
folly::Optional<uint64_t> baseAddr,
size_t offset,
uint8_t addrSize) const {
FOLLY_SAFE_CHECK(
addrSize == 4 || addrSize == 8, "wrong address size: ", int(addrSize));
if (cu_.version <= 4 && !cu_.debugSections.debugRanges.empty()) {
const bool is64BitAddr = addrSize == 8;
folly::StringPiece sp = cu_.debugSections.debugRanges;
sp.advance(offset);
const uint64_t maxAddr = is64BitAddr ? std::numeric_limits<uint64_t>::max()
: std::numeric_limits<uint32_t>::max();
while (!sp.empty()) {
uint64_t begin = readOffset(sp, is64BitAddr);
uint64_t end = readOffset(sp, is64BitAddr);
// The range list entry is a base address selection entry.
if (begin == maxAddr) {
baseAddr = end;
continue;
}
// The range list entry is an end of list entry.
if (begin == 0 && end == 0) {
break;
}
// Check if the given address falls in the range list entry.
// 2.17.3 Non-Contiguous Address Ranges
// The applicable base address of a range list entry is determined by the
// closest preceding base address selection entry (see below) in the same
// range list. If there is no such selection entry, then the applicable
// base address defaults to the base address of the compilation unit.
if (baseAddr && address >= begin + *baseAddr &&
address < end + *baseAddr) {
return true;
}
};
}
if (cu_.version == 5 && !cu_.debugSections.debugRnglists.empty() &&
cu_.addrBase.has_value()) {
auto debugRnglists = cu_.debugSections.debugRnglists;
debugRnglists.advance(offset);
while (!debugRnglists.empty()) {
auto kind = read<uint8_t>(debugRnglists);
switch (kind) {
case DW_RLE_end_of_list:
return false;
case DW_RLE_base_addressx: {
auto index = readULEB(debugRnglists);
auto sp = cu_.debugSections.debugAddr.subpiece(
*cu_.addrBase + index * sizeof(uint64_t));
baseAddr = read<uint64_t>(sp);
} break;
case DW_RLE_startx_endx: {
auto indexStart = readULEB(debugRnglists);
auto indexEnd = readULEB(debugRnglists);
auto spStart = cu_.debugSections.debugAddr.subpiece(
*cu_.addrBase + indexStart * sizeof(uint64_t));
auto start = read<uint64_t>(spStart);
auto spEnd = cu_.debugSections.debugAddr.subpiece(
*cu_.addrBase + indexEnd * sizeof(uint64_t));
auto end = read<uint64_t>(spEnd);
if (address >= start && address < end) {
return true;
}
} break;
case DW_RLE_startx_length: {
auto indexStart = readULEB(debugRnglists);
auto length = readULEB(debugRnglists);
auto spStart = cu_.debugSections.debugAddr.subpiece(
*cu_.addrBase + indexStart * sizeof(uint64_t));
auto start = read<uint64_t>(spStart);
auto spEnd = cu_.debugSections.debugAddr.subpiece(
*cu_.addrBase + indexStart * sizeof(uint64_t) + length);
auto end = read<uint64_t>(spEnd);
if (start != end && address >= start && address < end) {
return true;
}
} break;
case DW_RLE_offset_pair: {
auto offsetStart = readULEB(debugRnglists);
auto offsetEnd = readULEB(debugRnglists);
if (baseAddr && address >= (*baseAddr + offsetStart) &&
address < (*baseAddr + offsetEnd)) {
return true;
}
} break;
case DW_RLE_base_address:
baseAddr = read<uint64_t>(debugRnglists);
break;
case DW_RLE_start_end: {
uint64_t start = read<uint64_t>(debugRnglists);
uint64_t end = read<uint64_t>(debugRnglists);
if (address >= start && address < end) {
return true;
}
} break;
case DW_RLE_start_length: {
uint64_t start = read<uint64_t>(debugRnglists);
uint64_t end = start + readULEB(debugRnglists);
if (address >= start && address < end) {
return true;
}
} break;
default:
FOLLY_SAFE_CHECK(
false,
"Unexpected debug_rnglists entry kind: ",
static_cast<int>(kind));
}
}
}
return false;
}