in folly/experimental/symbolizer/DwarfLineNumberVM.cpp [449:559]
DwarfLineNumberVM::StepResult DwarfLineNumberVM::step(
folly::StringPiece& program) {
auto opcode = read<uint8_t>(program);
if (opcode >= opcodeBase_) { // special opcode
uint8_t adjustedOpcode = opcode - opcodeBase_;
uint8_t opAdvance = adjustedOpcode / lineRange_;
address_ += minLength_ * opAdvance;
line_ += lineBase_ + adjustedOpcode % lineRange_;
basicBlock_ = false;
prologueEnd_ = false;
epilogueBegin_ = false;
discriminator_ = 0;
return COMMIT;
}
if (opcode != 0) { // standard opcode
// Only interpret opcodes that are recognized by the version we're parsing;
// the others are vendor extensions and we should ignore them.
switch (opcode) {
case DW_LNS_copy:
basicBlock_ = false;
prologueEnd_ = false;
epilogueBegin_ = false;
discriminator_ = 0;
return COMMIT;
case DW_LNS_advance_pc:
address_ += minLength_ * readULEB(program);
return CONTINUE;
case DW_LNS_advance_line:
line_ += readSLEB(program);
return CONTINUE;
case DW_LNS_set_file:
file_ = readULEB(program);
return CONTINUE;
case DW_LNS_set_column:
column_ = readULEB(program);
return CONTINUE;
case DW_LNS_negate_stmt:
isStmt_ = !isStmt_;
return CONTINUE;
case DW_LNS_set_basic_block:
basicBlock_ = true;
return CONTINUE;
case DW_LNS_const_add_pc:
address_ += minLength_ * ((255 - opcodeBase_) / lineRange_);
return CONTINUE;
case DW_LNS_fixed_advance_pc:
address_ += read<uint16_t>(program);
return CONTINUE;
case DW_LNS_set_prologue_end:
if (version_ == 2) {
break; // not supported in version 2
}
prologueEnd_ = true;
return CONTINUE;
case DW_LNS_set_epilogue_begin:
if (version_ == 2) {
break; // not supported in version 2
}
epilogueBegin_ = true;
return CONTINUE;
case DW_LNS_set_isa:
if (version_ == 2) {
break; // not supported in version 2
}
isa_ = readULEB(program);
return CONTINUE;
}
// Unrecognized standard opcode, slurp the appropriate number of LEB
// arguments.
uint8_t argCount = standardOpcodeLengths_[opcode - 1];
while (argCount--) {
readULEB(program);
}
return CONTINUE;
}
// Extended opcode
auto length = readULEB(program);
// the opcode itself should be included in the length, so length >= 1
FOLLY_SAFE_CHECK(length != 0, "invalid extended opcode length");
auto extendedOpcode = read<uint8_t>(program);
--length;
switch (extendedOpcode) {
case DW_LNE_end_sequence:
return END;
case DW_LNE_set_address:
address_ = read<uintptr_t>(program);
return CONTINUE;
case DW_LNE_define_file:
FOLLY_SAFE_CHECK(version_ < 5, "DW_LNE_define_file deprecated in DWARF5");
// We can't process DW_LNE_define_file here, as it would require us to
// use unbounded amounts of state (ie. use the heap). We'll do a second
// pass (using nextDefineFile()) if necessary.
break;
#if !defined(__FreeBSD__)
case DW_LNE_set_discriminator:
discriminator_ = readULEB(program);
return CONTINUE;
#endif
}
// Unrecognized extended opcode
program.advance(length);
return CONTINUE;
}