// Writer for the .debug_line opcodes (DWARF-3). // The writer is very light-weight, however it will do the following for you: // * Choose the most compact encoding of a given opcode. // * Keep track of current state and convert absolute values to deltas. // * Divide by header-defined factors as appropriate. template<typename Vector = std::vector<uint8_t>> class DebugLineOpCodeWriter final : private Writer<Vector> {
static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
public: static constexpr int kOpcodeBase = 13; static constexpr bool kDefaultIsStmt = false; static constexpr int kLineBase = -5; static constexpr int kLineRange = 14;
void AddRow() { this->PushUint8(DW_LNS_copy);
}
void AdvancePC(uint64_t absolute_address) {
DCHECK_NE(current_address_, 0u); // Use SetAddress for the first advance.
DCHECK_GE(absolute_address, current_address_); if (absolute_address != current_address_) {
uint64_t delta = FactorCodeOffset(absolute_address - current_address_); if (delta <= INT32_MAX) { this->PushUint8(DW_LNS_advance_pc); this->PushUleb128(static_cast<int>(delta));
current_address_ = absolute_address;
} else {
SetAddress(absolute_address);
}
}
}
// Uncoditionally set address using the long encoding. // This gives the linker opportunity to relocate the address. void SetAddress(uint64_t absolute_address) {
DCHECK_GE(absolute_address, current_address_);
FactorCodeOffset(absolute_address); // Check if it is factorable. this->PushUint8(0); if (use_64bit_address_) { this->PushUleb128(1 + 8); this->PushUint8(DW_LNE_set_address);
patch_locations_.push_back(this->data()->size()); this->PushUint64(absolute_address);
} else { this->PushUleb128(1 + 4); this->PushUint8(DW_LNE_set_address);
patch_locations_.push_back(this->data()->size()); this->PushUint32(absolute_address);
}
current_address_ = absolute_address;
}
void DefineFile(constchar* filename, int directory_index, int modification_time, int file_size) { int size = 1 +
strlen(filename) + 1 +
UnsignedLeb128Size(directory_index) +
UnsignedLeb128Size(modification_time) +
UnsignedLeb128Size(file_size); this->PushUint8(0); this->PushUleb128(size);
size_t start = data()->size(); this->PushUint8(DW_LNE_define_file); this->PushString(filename); this->PushUleb128(directory_index); this->PushUleb128(modification_time); this->PushUleb128(file_size);
DCHECK_EQ(start + size, data()->size());
}
// Compact address and line opcode. void AddRow(uint64_t absolute_address, int absolute_line) {
DCHECK_GE(absolute_address, current_address_);
// If the address is definitely too far, use the long encoding.
uint64_t delta_address = FactorCodeOffset(absolute_address - current_address_); if (delta_address > UINT8_MAX) {
AdvancePC(absolute_address);
delta_address = 0;
}
// If the line is definitely too far, use the long encoding. int delta_line = absolute_line - current_line_; if (!(kLineBase <= delta_line && delta_line < kLineBase + kLineRange)) {
AdvanceLine(absolute_line);
delta_line = 0;
}
// Both address and line should be reasonable now. Use the short encoding. int opcode = kOpcodeBase + (delta_line - kLineBase) +
(static_cast<int>(delta_address) * kLineRange); if (opcode > UINT8_MAX) { // If the address is still too far, try to increment it by const amount. int const_advance = (0xFF - kOpcodeBase) / kLineRange;
opcode -= (kLineRange * const_advance); if (opcode <= UINT8_MAX) { this->PushUint8(DW_LNS_const_add_pc);
} else { // Give up and use long encoding for address.
AdvancePC(absolute_address); // Still use the opcode to do line advance and copy.
opcode = kOpcodeBase + (delta_line - kLineBase);
}
}
DCHECK(kOpcodeBase <= opcode && opcode <= 0xFF); this->PushUint8(opcode); // Special opcode.
current_line_ = absolute_line;
current_address_ = absolute_address;
}
int GetCodeFactorBits() const { return code_factor_bits_;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.