blob: 8f6b6f5d081f34aaa2a78b4b019b50e47fc45d32 [file] [edit]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_DEBUG_INFO_H_
#define RUNTIME_VM_DEBUG_INFO_H_
#include "platform/globals.h"
#if defined(DART_PRECOMPILER)
#include <functional>
#include "platform/utils.h"
#include "vm/allocation.h"
#include "vm/growable_array.h"
#include "vm/object.h"
#include "vm/zone.h"
namespace dart {
template <typename T>
class Trie;
class DebugInfoPosition {
public:
DebugInfoPosition(int32_t line, int32_t column)
: line_(line), column_(column) {
// Should only have no line information if also no column information.
ASSERT(line_ > kNoLine || column_ <= kNoColumn);
}
// CodeSourceMaps start the line and column registers at -1, not at 0, and
// the arguments passed to ChangePosition are retrieved from CodeSourceMaps.
explicit DebugInfoPosition(int32_t line) : DebugInfoPosition(line, -1) {}
constexpr DebugInfoPosition() : line_(-1), column_(-1) {}
// Debug formats use 0 to denote missing line or column information.
static constexpr int32_t kNoLine = 0;
static constexpr int32_t kNoColumn = 0;
int32_t line() const { return line_ > kNoLine ? line_ : kNoLine; }
int32_t column() const { return column_ > kNoColumn ? column_ : kNoColumn; }
// Adjusts the contents given the arguments to a ChangePosition instruction
// from CodeSourceMaps.
void ChangePosition(int32_t line_delta, int32_t new_column) {
line_ = Utils::AddWithWrapAround(line_, line_delta);
column_ = new_column;
}
private:
int32_t line_;
int32_t column_;
};
static constexpr auto kNoDebugInfoPositionInfo = DebugInfoPosition();
class DebugInfoLineNumberProgramWriter : public ValueObject {
public:
explicit DebugInfoLineNumberProgramWriter(Zone* zone)
: function_stack_(zone, 8), token_positions_(zone, 8) {}
virtual ~DebugInfoLineNumberProgramWriter() {}
virtual intptr_t LookupCodeLabel(const Code& code) = 0;
virtual intptr_t LookupScript(const Script& script) = 0;
virtual void EmitRow(intptr_t file,
intptr_t line,
intptr_t column,
intptr_t label,
intptr_t pc_offset) = 0;
protected:
GrowableArray<const Function*> function_stack_;
GrowableArray<DebugInfoPosition> token_positions_;
private:
friend class DebugInfo;
DISALLOW_COPY_AND_ASSIGN(DebugInfoLineNumberProgramWriter);
};
class DebugInfoWriteStream : public ValueObject {
public:
DebugInfoWriteStream() {}
virtual ~DebugInfoWriteStream() {}
virtual void sleb128(intptr_t value) = 0;
virtual void uleb128(uintptr_t value) = 0;
virtual void u1(uint8_t value) = 0;
virtual void u2(uint16_t value) = 0;
virtual void u4(uint32_t value) = 0;
virtual void u8(uint64_t value) = 0;
virtual void string(const char* cstr) = 0; // NOLINT
// Prefixes the content added by body with its length.
//
// symbol_prefix is used when a local symbol is created for the length.
virtual void WritePrefixedLength(const char* symbol_prefix,
std::function<void()> body) = 0;
// Generates a relocated address from the given symbol label and offset.
//
// If no size is provided, the size of the relocated address in the stream
// is the native word size.
virtual void OffsetFromSymbol(intptr_t label,
intptr_t offset,
size_t size = kAddressSize) = 0;
virtual void InitializeAbstractOrigins(intptr_t size) = 0;
virtual void RegisterAbstractOrigin(intptr_t index) = 0;
virtual void AbstractOrigin(intptr_t index) = 0;
protected:
#if defined(TARGET_ARCH_IS_32_BIT)
static constexpr size_t kAddressSize = kInt32Size;
#else
static constexpr size_t kAddressSize = kInt64Size;
#endif
DISALLOW_COPY_AND_ASSIGN(DebugInfoWriteStream);
};
class DebugInfo : public AllStatic {
public:
static const char* ConvertResolvedURI(const char* str);
static const char* ResolveScriptUri(
Zone* zone,
const Script& script,
const Trie<const char>* deobfuscation_trie);
static void WriteLineNumberProgramForCode(
Zone* zone,
const Code& code,
DebugInfoLineNumberProgramWriter* writer);
static void WriteLineNumberProgramFromCodeSourceMaps(
Zone* zone,
const GrowableArray<const Code*>& codes,
DebugInfoLineNumberProgramWriter* writer);
};
} // namespace dart
#endif // DART_PRECOMPILER
#endif // RUNTIME_VM_DEBUG_INFO_H_