| // 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_ |