in folly/experimental/symbolizer/DwarfLineNumberVM.cpp [180:286]
void DwarfLineNumberVM::init() {
version_ = read<uint16_t>(data_);
FOLLY_SAFE_CHECK(
version_ >= 2 && version_ <= 5,
"invalid version in line number VM: ",
version_);
if (version_ == 5) {
auto addressSize = read<uint8_t>(data_);
FOLLY_SAFE_CHECK(
addressSize == sizeof(uintptr_t),
"Unexpected Line Number Table address_size: ",
addressSize);
auto segment_selector_size = read<uint8_t>(data_);
FOLLY_SAFE_CHECK(segment_selector_size == 0, "Segments not supported");
}
uint64_t headerLength = readOffset(data_, is64Bit_);
FOLLY_SAFE_CHECK(
headerLength <= data_.size(),
"invalid line number VM header length: headerLength: ",
headerLength,
" data_.size(): ",
data_.size());
folly::StringPiece header(data_.data(), headerLength);
data_.assign(header.end(), data_.end());
minLength_ = read<uint8_t>(header);
if (version_ >= 4) { // Version 2 and 3 records don't have this
uint8_t maxOpsPerInstruction = read<uint8_t>(header);
FOLLY_SAFE_CHECK(maxOpsPerInstruction == 1, "VLIW not supported");
}
defaultIsStmt_ = read<uint8_t>(header);
lineBase_ = read<int8_t>(header); // yes, signed
lineRange_ = read<uint8_t>(header);
opcodeBase_ = read<uint8_t>(header);
FOLLY_SAFE_CHECK(opcodeBase_ != 0, "invalid opcode base");
standardOpcodeLengths_ = reinterpret_cast<const uint8_t*>(header.data());
header.advance(opcodeBase_ - 1);
if (version_ <= 4) {
// We don't want to use heap, so we don't keep an unbounded amount of state.
// We'll just skip over include directories and file names here, and
// we'll loop again when we actually need to retrieve one.
folly::StringPiece sp;
const char* tmp = header.data();
v4_.includeDirectoryCount = 0;
while (!(sp = readNullTerminated(header)).empty()) {
++v4_.includeDirectoryCount;
}
v4_.includeDirectories.assign(tmp, header.data());
tmp = header.data();
FileName fn;
v4_.fileNameCount = 0;
while (readFileName(header, fn)) {
++v4_.fileNameCount;
}
v4_.fileNames.assign(tmp, header.data());
} else if (version_ == 5) {
v5_.directoryEntryFormatCount = read<uint8_t>(header);
const char* tmp = header.data();
for (uint8_t i = 0; i < v5_.directoryEntryFormatCount; i++) {
// A sequence of directory entry format descriptions. Each description
// consists of a pair of ULEB128 values:
readULEB(header); // A content type code
readULEB(header); // A form code using the attribute form codes
}
v5_.directoryEntryFormat.assign(tmp, header.data());
v5_.directoriesCount = readULEB(header);
tmp = header.data();
for (uint64_t i = 0; i < v5_.directoriesCount; i++) {
folly::StringPiece format = v5_.directoryEntryFormat;
for (uint8_t f = 0; f < v5_.directoryEntryFormatCount; f++) {
readLineNumberAttribute(
is64Bit_,
format,
header,
debugSections_.debugStr,
debugSections_.debugLineStr);
}
}
v5_.directories.assign(tmp, header.data());
v5_.fileNameEntryFormatCount = read<uint8_t>(header);
tmp = header.data();
for (uint8_t i = 0; i < v5_.fileNameEntryFormatCount; i++) {
// A sequence of file entry format descriptions. Each description
// consists of a pair of ULEB128 values:
readULEB(header); // A content type code
readULEB(header); // A form code using the attribute form codes
}
v5_.fileNameEntryFormat.assign(tmp, header.data());
v5_.fileNamesCount = readULEB(header);
tmp = header.data();
for (uint64_t i = 0; i < v5_.fileNamesCount; i++) {
folly::StringPiece format = v5_.fileNameEntryFormat;
for (uint8_t f = 0; f < v5_.fileNameEntryFormatCount; f++) {
readLineNumberAttribute(
is64Bit_,
format,
header,
debugSections_.debugStr,
debugSections_.debugLineStr);
}
}
v5_.fileNames.assign(tmp, header.data());
}
}