blob: 5096b9f1f98077a9eb3afa50b1fe836355ac2b29 [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_CODEVIEW_H_
#define RUNTIME_VM_CODEVIEW_H_
#include "platform/globals.h"
#if defined(DART_PRECOMPILER)
#include "platform/coff.h"
#include "vm/allocation.h"
#include "vm/growable_array.h"
#include "vm/object.h"
#include "vm/zone.h"
namespace dart {
class CoffWriter;
class DebugInfoStream;
// Translates the Dart debug metadata into Microsoft CodeView records embedded
// in .debug$S (symbols + line numbers) and .debug$T (types). The output is
// designed so that `link.exe /DEBUG` synthesizes a Microsoft .pdb compatible
// with WinDbg / Visual Studio.
//
// Owned by CoffWriter; appends bytes and relocations directly into the
// CoffWriter's .debug$S / .debug$T sections.
class CodeViewBuilder : public ZoneObject {
public:
CodeViewBuilder(Zone* zone,
CoffWriter* writer,
DebugInfoStream* debug_s,
DebugInfoStream* debug_t);
// Populate the .debug$S and .debug$T sections. Caller (CoffWriter::Finalize)
// must have created both sections before calling.
void Build();
private:
// Per-function CodeView metadata.
struct FunctionInfo {
const char* name = nullptr;
intptr_t label = 0; // VM-internal label registered with debug info/Coff
uint32_t func_id_type = 0; // LF_FUNC_ID type index
};
// .debug$T helpers.
void EmitTypeRecords();
// .debug$S helpers.
void EmitObjectAndCompileSymbolsSubsection();
void EmitFunctionSymbolsSubsection(const FunctionInfo& fn, const Code& code);
void EmitLinesSubsection(const FunctionInfo& fn, const Code& code);
void EmitFileChecksumsSubsection();
void EmitStringTableSubsection();
void GatherFunctions();
void ComputeScriptTables();
void EmitOneFunctionSymbol(const FunctionInfo& fn, const Code& code);
// Returns a zone-owned, NUL-terminated path string for `script`, honoring
// --resolve-dwarf-paths and the obfuscation trie.
const char* ResolvedScriptUri(const Script& script);
Zone* const zone_;
// CodeViewBuilder is allocated and used synchronously by
// CoffWriter::EmitCodeView() during CoffWriter::Finalize(). The CoffWriter
// and the debug streams owned by its .debug$S/.debug$T Sections therefore
// remain valid for the builder's lifetime, before the sections are laid out
// and written.
CoffWriter* const writer_;
DebugInfoStream* const debugS_;
DebugInfoStream* const debugT_;
ZoneGrowableArray<FunctionInfo>* functions_;
// Parallel arrays indexed by debug script index. Computed
// by ComputeScriptTables() so EmitLines can stamp checksum-offsets directly
// into CV_LINE_BLOCK headers.
ZoneGrowableArray<uint32_t>* script_string_offsets_;
ZoneGrowableArray<uint32_t>* script_checksum_offsets_;
// The next available LF_* type index (CodeView starts user types at 0x1000).
uint32_t next_type_index_ = 0x1000;
uint32_t arglist_type_ = 0;
uint32_t procedure_type_ = 0;
DISALLOW_COPY_AND_ASSIGN(CodeViewBuilder);
};
} // namespace dart
#endif // DART_PRECOMPILER
#endif // RUNTIME_VM_CODEVIEW_H_