From 1003d2a94b756697f426e00d0dc998d79f0676c8 Mon Sep 17 00:00:00 2001 From: Simon Spies Date: Fri, 15 May 2026 17:30:51 +0100 Subject: [PATCH 1/9] DWARF expression support for OxCaml LLDB --- .../Plugins/Language/OxCaml/CMakeLists.txt | 1 + .../Language/OxCaml/OxCamlFormatters.cpp | 897 ++++++++++-------- .../SymbolFile/DWARF/DWARFASTParserOxCaml.cpp | 217 +++-- .../Plugins/TypeSystem/OxCaml/CMakeLists.txt | 2 + .../OxCaml/OxCamlDynamicLayoutValue.cpp | 181 ++++ .../OxCaml/OxCamlDynamicLayoutValue.h | 154 +++ .../Plugins/TypeSystem/OxCaml/OxCamlTypes.h | 68 +- .../TypeSystem/OxCaml/TypeSystemOxCaml.cpp | 11 +- 8 files changed, 1004 insertions(+), 527 deletions(-) create mode 100644 lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.cpp create mode 100644 lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h diff --git a/lldb/source/Plugins/Language/OxCaml/CMakeLists.txt b/lldb/source/Plugins/Language/OxCaml/CMakeLists.txt index 1aa3cbe45afec..a8f92a9eaca13 100644 --- a/lldb/source/Plugins/Language/OxCaml/CMakeLists.txt +++ b/lldb/source/Plugins/Language/OxCaml/CMakeLists.txt @@ -8,6 +8,7 @@ add_lldb_library(lldbPluginOxCamlLanguage PLUGIN LINK_LIBS lldbCore + lldbExpression lldbTarget lldbUtility ) diff --git a/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp b/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp index c01caaa4e01fc..780cc77ab9e60 100644 --- a/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp +++ b/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp @@ -60,6 +60,7 @@ #include "lldb/Utility/Reference.h" #include "lldb/Utility/Status.h" #include "lldb/ValueObject/ValueObject.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" #include @@ -86,49 +87,43 @@ static uint64_t MakeLowBitMask(uint64_t bit_size) { return (1ULL << bit_size) - 1ULL; } - static bool FormatValue(Stream &stream, OxCamlType *type, DataExtractor &data, - lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref); + const OxCamlFormatContext &context, + std::optional object_address); static bool FormatUnboxedBase(Stream &stream, OxCamlUnboxedBaseType *unboxed_type, - DataExtractor &data, lldb::ProcessSP process_sp); + DataExtractor &data); static bool FormatFallback(Stream &stream, OxCamlType *type, - DataExtractor &data, lldb::ProcessSP process_sp); + DataExtractor &data); static bool FormatEnum(Stream &stream, OxCamlEnumType *enum_type, - DataExtractor &data, lldb::ProcessSP process_sp); + DataExtractor &data); static bool FormatPointer(Stream &stream, OxCamlPointerType *ptr_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref); + DataExtractor &data, + const OxCamlFormatContext &context); static bool FormatTypedef(Stream &stream, OxCamlTypedefType *typedef_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref); + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address); static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref); + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address); static bool FormatPlaceholder(Stream &stream, OxCamlPlaceholderType *placeholder_type, - DataExtractor &data, lldb::ProcessSP process_sp); + DataExtractor &data); static bool FormatUnknown(Stream &stream, OxCamlUnknownType *unknown_type, - DataExtractor &data, lldb::ProcessSP process_sp); + DataExtractor &data); static bool FormatArray(Stream &stream, OxCamlArrayType *array_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref); - -// Forward declarations for variant functions called from -// FormatPointer/FormatStructure -static uint64_t -CalculateMinimumSizeForDiscriminators(OxCamlStructureType *struct_type); -static uint64_t EstimatePointerAllocationSize(OxCamlType *type, - DataExtractor &data); -static uint64_t ComputeActualPointerSize(OxCamlType *pointed_to, - lldb::addr_t adjusted_address, - const DataExtractor &data, - lldb::ProcessSP process_sp); + DataExtractor &data, const OxCamlFormatContext &context, + std::optional object_address); +static bool TryFormatRuntimeFloatArray(Stream &stream, lldb::addr_t array_ptr, + lldb::ProcessSP process_sp); + static bool FormatVariantPart(Stream &stream, const OxCamlVariantPart &variant_part, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref, + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address, bool is_ocaml_variant); // ============================================================================ @@ -173,9 +168,14 @@ bool lldb_private::formatters::oxcaml::OxCamlValue_SummaryProvider( "(ptr={0:P})", process_sp.get()); - const ExecutionContextRef &exe_ctx_ref = valobj.GetExecutionContextRef(); + OxCamlFormatContext context{process_sp, valobj.GetExecutionContextRef(), + data.GetByteOrder(), data.GetAddressByteSize()}; - return FormatValue(stream, type, data, process_sp, exe_ctx_ref); + // No object address at entry: [data] holds the OCaml value itself + // (typically a register-resident tagged pointer). FormatPointer sets the + // object address for any pointed-to objects it dereferences. + return FormatValue(stream, type, data, context, + /*object_address=*/std::nullopt); } // ============================================================================ @@ -183,7 +183,7 @@ bool lldb_private::formatters::oxcaml::OxCamlValue_SummaryProvider( // ============================================================================ static bool FormatFallback(Stream &stream, OxCamlType *type, - DataExtractor &data, lldb::ProcessSP process_sp) { + DataExtractor &data) { size_t byte_size = data.GetByteSize(); if (byte_size == 0) { if (type) { @@ -217,7 +217,7 @@ static bool FormatFallback(Stream &stream, OxCamlType *type, static bool FormatPlaceholder(Stream &stream, OxCamlPlaceholderType *placeholder_type, - DataExtractor &data, lldb::ProcessSP process_sp) { + DataExtractor &data) { OXCAML_EMIT_MARKER( stream, "", "Cannot format unresolved placeholder type '{0}' (DIE 0x{1:x16})", @@ -226,7 +226,7 @@ static bool FormatPlaceholder(Stream &stream, } static bool FormatUnknown(Stream &stream, OxCamlUnknownType *unknown_type, - DataExtractor &data, lldb::ProcessSP process_sp) { + DataExtractor &data) { OXCAML_EMIT_MARKER( stream, "", "Unsupported DWARF tag 0x{0:x} for type '{1}' (DIE 0x{2:x16})", @@ -237,7 +237,7 @@ static bool FormatUnknown(Stream &stream, OxCamlUnknownType *unknown_type, static bool FormatUnboxedBase(Stream &stream, OxCamlUnboxedBaseType *unboxed_type, - DataExtractor &data, lldb::ProcessSP process_sp) { + DataExtractor &data) { uint64_t byte_size = unboxed_type->GetByteSize(); ENSURE(byte_size != 0, stream, "<0-byte base type>", "Unboxed base type '{0}' (DIE 0x{1:x}) reports zero byte size", @@ -299,7 +299,7 @@ static bool FormatUnboxedBase(Stream &stream, } static bool FormatEnum(Stream &stream, OxCamlEnumType *enum_type, - DataExtractor &data, lldb::ProcessSP process_sp) { + DataExtractor &data) { uint64_t byte_size = enum_type->GetByteSize(); OX_ASSERT(byte_size > 0 && byte_size <= helpers::constants::WORD_SIZE, "OCaml enum type '{0}' (DIE 0x{1:x}) has size {2} bytes, must be " @@ -325,9 +325,80 @@ static bool FormatEnum(Stream &stream, OxCamlEnumType *enum_type, return true; } +// Resolve the byte size of [type] at format time. For structures, evaluates +// the dynamic DW_AT_byte_size/DW_AT_bit_size against [object_address] (which +// must be the type's own object address). For arrays, compiler-emitted OxCaml +// DWARF wraps the DW_TAG_array_type in a reference type and equips the array +// with DW_AT_count and DW_AT_byte_stride. The count expression reads the OCaml +// block header wosize; generic runtime array discovery belongs to the +// ocaml_value formatter, not this typed-array path. For everything else, +// returns the static byte size. +static llvm::Expected +ResolveTypeByteSize(OxCamlType *type, + std::optional object_address, + const OxCamlFormatContext &context) { + OxCamlType *underlying = type; + while (underlying && underlying->GetKind() == OxCamlType::Typedef) + underlying = + static_cast(underlying)->GetUnderlyingType(); + if (!underlying) + return type->GetByteSize(); + + if (underlying->GetKind() == OxCamlType::Structure) { + auto *struct_type = static_cast(underlying); + auto result = + struct_type->GetDynamicSize().Evaluate(context, object_address); + if (!result) + return result.takeError(); + OX_ASSERT( + result->GetKind() == OxCamlLayoutValueKind::ScalarBytes || + result->GetKind() == OxCamlLayoutValueKind::ScalarBits, + "Dynamic size for structure type '{0}' (DIE 0x{1:x}) evaluated to " + "layout kind {2}; expected ScalarBytes or ScalarBits", + struct_type->GetDisplayName(), struct_type->GetDieId(), + static_cast(result->GetKind())); + if (result->GetKind() == OxCamlLayoutValueKind::ScalarBits) + return (result->GetScalar() + 7) / 8; + return result->GetScalar(); + } + + if (underlying->GetKind() == OxCamlType::Array) { + auto *array_type = static_cast(underlying); + auto stride_result = + array_type->GetStride().Evaluate(context, object_address); + if (!stride_result) + return stride_result.takeError(); + OX_ASSERT(stride_result->GetKind() == OxCamlLayoutValueKind::ScalarBytes, + "DW_AT_byte_stride for array '{0}' (DIE 0x{1:x}) evaluated to " + "layout kind {2}; expected ScalarBytes", + array_type->GetDisplayName(), array_type->GetDieId(), + static_cast(stride_result->GetKind())); + uint64_t stride = stride_result->GetScalar(); + + const auto &count = array_type->GetCount(); + if (!count.has_value()) + return llvm::createStringError( + "Array type '%s' (DIE 0x%" PRIx64 + ") has no DW_AT_count; compiler-emitted OxCaml arrays must include " + "a subrange count expression", + array_type->GetDisplayName().c_str(), array_type->GetDieId()); + auto count_result = count->Evaluate(context, object_address); + if (!count_result) + return count_result.takeError(); + OX_ASSERT(count_result->GetKind() == OxCamlLayoutValueKind::ScalarElements, + "DW_AT_count for array '{0}' (DIE 0x{1:x}) evaluated to layout " + "kind {2}; expected ScalarElements", + array_type->GetDisplayName(), array_type->GetDieId(), + static_cast(count_result->GetKind())); + return count_result->GetScalar() * stride; + } + + return type->GetByteSize(); +} + static bool FormatPointer(Stream &stream, OxCamlPointerType *ptr_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref) { + DataExtractor &data, + const OxCamlFormatContext &context) { uint64_t ptr_size = ptr_type->GetByteSize(); ENSURE(ptr_size == helpers::constants::WORD_SIZE, stream, "", "OCaml pointer type '{0}' (DIE 0x{1:x}) has size {2} bytes, " @@ -354,62 +425,65 @@ static bool FormatPointer(Stream &stream, OxCamlPointerType *ptr_type, "Pointer 0x{0:x} to '{1}' (DIE 0x{2:x}) lacks a resolved target type", ptr_value, ptr_type->GetDisplayName(), ptr_type->GetDieId()); - // Special case: Arrays are variable-sized and need the raw pointer value - // Don't dereference - just pass the data (containing pointer) to FormatArray - if (pointed_to->GetKind() == OxCamlType::Array) { - return FormatArray(stream, static_cast(pointed_to), data, - process_sp, exe_ctx_ref); - } - - uint64_t size = pointed_to->GetByteSize(); - ENSURE(size != 0, stream, "", - "Resolved target type '{0}' (DIE 0x{1:x}) reports byte size 0; " - "cannot dereference pointer 0x{2:x}", - pointed_to->GetDisplayName(), pointed_to->GetDieId(), ptr_value); - - // potentially offset the pointer for OCaml blocks - int64_t base_offset = pointed_to->GetPointerAdjustmentOffset(); - uint64_t adjusted_address = ptr_value + base_offset; - - uint64_t actual_size = - ComputeActualPointerSize(pointed_to, adjusted_address, data, process_sp); - - if (base_offset != 0) { - Log *log = GetLog(OxCamlLog::Formatting); - LLDB_LOG(log, - "FormatPointer: Applying base offset {0} to pointer 0x{1:x}, " - "adjusted address: 0x{2:x}, reading {3} bytes", - base_offset, ptr_value, adjusted_address, actual_size); + lldb::addr_t object_address = ptr_value; + + llvm::Expected actual_size_expected = + ResolveTypeByteSize(pointed_to, object_address, context); + if (!actual_size_expected) { + OXCAML_EMIT_MARKER( + stream, "", + "Failed to evaluate dynamic byte size for pointer 0x{0:x} to " + "'{1}' (DIE 0x{2:x}): {3}", + ptr_value, pointed_to->GetDisplayName(), pointed_to->GetDieId(), + llvm::toString(actual_size_expected.takeError())); + return true; } - + uint64_t actual_size = *actual_size_expected; + OxCamlType *underlying_pointed_to = pointed_to; + while (underlying_pointed_to && + underlying_pointed_to->GetKind() == OxCamlType::Typedef) + underlying_pointed_to = + static_cast(underlying_pointed_to) + ->GetUnderlyingType(); + bool is_array_target = underlying_pointed_to && + underlying_pointed_to->GetKind() == OxCamlType::Array; + + // Empty OCaml arrays are real heap blocks with zero-byte payloads. Keep the + // zero-size guard for other pointer targets, but let arrays flow through to + // FormatArray with an empty DataExtractor and the object address. ENSURE( - actual_size != 0, stream, "", + actual_size != 0 || is_array_target, stream, "", "Resolved target type '{0}' (DIE 0x{1:x}) computed dereference size 0; " "cannot dereference pointer 0x{2:x}", pointed_to->GetDisplayName(), pointed_to->GetDieId(), ptr_value); std::vector buffer(actual_size); - Status error; - size_t bytes_read = process_sp->ReadMemory(adjusted_address, buffer.data(), - actual_size, error); - - ENSURE(bytes_read == actual_size && error.Success(), stream, "", - "Failed to read {0} bytes from address 0x{1:x} for pointer 0x{2:x} " - "to '{3}' (DIE 0x{4:x})", - actual_size, adjusted_address, ptr_value, pointed_to->GetDisplayName(), - pointed_to->GetDieId()); - - DataExtractor pointed_data(buffer.data(), actual_size, data.GetByteOrder(), - data.GetAddressByteSize()); + DataExtractor pointed_data; + pointed_data.SetByteOrder(data.GetByteOrder()); + pointed_data.SetAddressByteSize(data.GetAddressByteSize()); + if (actual_size > 0) { + Status error; + size_t bytes_read = context.process_sp->ReadMemory( + object_address, buffer.data(), actual_size, error); + + ENSURE(bytes_read == actual_size && error.Success(), stream, "", + "Failed to read {0} bytes from address 0x{1:x} for pointer 0x{2:x} " + "to '{3}' (DIE 0x{4:x})", + actual_size, object_address, ptr_value, pointed_to->GetDisplayName(), + pointed_to->GetDieId()); + + pointed_data.SetData(buffer.data(), actual_size, data.GetByteOrder()); + } - return FormatValue(stream, pointed_to, pointed_data, process_sp, exe_ctx_ref); + return FormatValue(stream, pointed_to, pointed_data, context, object_address); } static bool FormatTypedef(Stream &stream, OxCamlTypedefType *typedef_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref) { - return FormatValue(stream, typedef_type->GetUnderlyingType(), data, - process_sp, exe_ctx_ref); + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address) { + return FormatValue(stream, typedef_type->GetUnderlyingType(), data, context, + object_address); } // Format an OCaml exception value @@ -550,8 +624,7 @@ ExtractExceptionInfo(lldb::addr_t exception_addr, lldb::ProcessSP process_sp) { // Format an OCaml exception value static bool FormatException(Stream &stream, DataExtractor &data, - lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref) { + const OxCamlFormatContext &context) { lldb::offset_t offset = 0; uint64_t exception_value = data.GetU64(&offset); @@ -565,7 +638,7 @@ static bool FormatException(Stream &stream, DataExtractor &data, exception_value, (exception_value == 0) ? "null pointer" : "immediate OCaml value"); - auto info_opt = ExtractExceptionInfo(exception_value, process_sp); + auto info_opt = ExtractExceptionInfo(exception_value, context.process_sp); ENSURE(info_opt.has_value(), stream, "", "Failed to extract OCaml exception payload at 0x{0:x}", @@ -583,8 +656,9 @@ static bool FormatException(Stream &stream, DataExtractor &data, } DataExtractor arg_data(&info_opt->arguments[i], constants::WORD_SIZE, - process_sp->GetByteOrder(), constants::WORD_SIZE); - oxcaml::FormatOxCamlValue(stream, arg_data, process_sp, exe_ctx_ref); + context.byte_order, constants::WORD_SIZE); + oxcaml::FormatOxCamlValue(stream, arg_data, context.process_sp, + context.exe_ctx_ref); } if (use_parens) { @@ -595,161 +669,296 @@ static bool FormatException(Stream &stream, DataExtractor &data, return true; } -static bool FormatArray(Stream &stream, OxCamlArrayType *array_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref) { - ENSURE(data.GetByteSize() >= helpers::constants::WORD_SIZE, stream, "", - "Data size {0} < expected word size {1}", data.GetByteSize(), - helpers::constants::WORD_SIZE); - - lldb::offset_t offset = 0; - uint64_t array_ptr = data.GetU64(&offset); - - ENSURE(offset != 0, stream, "", - "Failed to read OCaml array pointer from value data ({0} bytes " - "available)", - data.GetByteSize()); - - // Check for null or immediate values (not actual pointers) - ENSURE(array_ptr != 0 && !helpers::value::IsImmediate(array_ptr), stream, - llvm::formatv("", array_ptr).str(), - "Array pointer 0x{0:x} is a {1}; skipping dereference", array_ptr, - array_ptr == 0 ? "null pointer" : "immediate OCaml value"); - +// Polymorphic array values such as ['a array] may have an ocaml_value element +// type in DWARF but actually carry unboxed doubles at runtime. The OCaml block +// tag (Double_array_tag) is authoritative, so check it here before formatting +// elements from DWARF. Returns true (with output emitted) if the runtime tag +// proves this is a float array; returns false without emitting anything +// otherwise. +static bool TryFormatRuntimeFloatArray(Stream &stream, lldb::addr_t array_ptr, + lldb::ProcessSP process_sp) { auto header_opt = helpers::ReadBlockHeader(array_ptr, process_sp); - ENSURE(header_opt.has_value(), stream, - llvm::formatv("", array_ptr).str(), - "Failed to read OCaml array header for pointer 0x{0:x}", array_ptr); + if (!header_opt.has_value()) + return false; - uint64_t header = *header_opt; uint8_t tag; uint64_t wosize; uint8_t reserved; - helpers::header::ParseHeader(header, tag, wosize, reserved); + helpers::header::ParseHeader(*header_opt, tag, wosize, reserved); + if (tag != helpers::constants::DOUBLE_ARRAY_TAG) + return false; + + return oxcaml::FormatOxCamlDoubleArray(stream, array_ptr, wosize, process_sp); +} - // OCaml float arrays (tag 254) store unboxed 8-byte IEEE 754 doubles - // wosize is the number of doubles (1 word = 1 double on 64-bit platforms) - if (tag == constants::DOUBLE_ARRAY_TAG) { - return oxcaml::FormatOxCamlDoubleArray(stream, array_ptr, wosize, - process_sp); +static bool FormatArray(Stream &stream, OxCamlArrayType *array_type, + DataExtractor &data, const OxCamlFormatContext &context, + std::optional object_address) { + if (object_address.has_value() && + TryFormatRuntimeFloatArray(stream, *object_address, context.process_sp)) + return true; + + llvm::Expected stride_result = + array_type->GetStride().Evaluate(context, object_address); + if (!stride_result) { + OXCAML_EMIT_MARKER( + stream, "", + "Failed to evaluate byte_stride for array '{0}' (DIE 0x{1:x}): {2}", + array_type->GetDisplayName(), array_type->GetDieId(), + llvm::toString(stride_result.takeError())); + return true; } + uint64_t stride = stride_result->GetScalar(); + ENSURE(stride != 0, stream, "", + "Array type '{0}' (DIE 0x{1:x}) has stride 0; cannot format elements", + array_type->GetDisplayName(), array_type->GetDieId()); + + // OxCaml compiler-emitted array DIEs always carry DW_AT_count on their + // subrange. Values without typed-array DWARF are handled by generic + // ocaml_value formatting instead. + ENSURE(array_type->GetCount().has_value(), stream, "", + "Array type '{0}' (DIE 0x{1:x}) has no DW_AT_count; " + "compiler-emitted OxCaml arrays must include a subrange count " + "expression", + array_type->GetDisplayName(), array_type->GetDieId()); + llvm::Expected count_result = + array_type->GetCount()->Evaluate(context, object_address); + if (!count_result) { + OXCAML_EMIT_MARKER( + stream, "", + "Failed to evaluate DW_AT_count for array '{0}' (DIE 0x{1:x}): {2}", + array_type->GetDisplayName(), array_type->GetDieId(), + llvm::toString(count_result.takeError())); + return true; + } + uint64_t num_elements = count_result->GetScalar(); - // Regular arrays: calculate number of elements from wosize and stride - // wosize is number of words, total bytes = wosize * WORD_SIZE - OxCamlType *element_type = array_type->GetElementType(); - uint64_t stride = array_type->GetStride(); - ENSURE(stride != 0, stream, llvm::formatv("", array_ptr).str(), - "Array type '{0}' (DIE 0x{1:x}) has stride 0; cannot format array at " - "0x{2:x}", - array_type->GetDisplayName(), array_type->GetDieId(), array_ptr); - - uint64_t total_bytes = wosize * helpers::constants::WORD_SIZE; - uint64_t num_elements = total_bytes / stride; - Status error; + uint64_t payload_size = num_elements * stride; + ENSURE(data.GetByteSize() >= payload_size, stream, "", + "Array '{0}' (DIE 0x{1:x}) payload buffer holds {2} bytes, needs " + "{3} ({4} elements x {5}-byte stride)", + array_type->GetDisplayName(), array_type->GetDieId(), + data.GetByteSize(), payload_size, num_elements, stride); + OxCamlType *element_type = array_type->GetElementType(); stream.Printf("[| "); - for (uint64_t i = 0; i < num_elements; i++) { if (i > 0) stream.Printf("; "); - uint64_t element_address = array_ptr + (i * stride); + DataExtractor element_data(data, i * stride, stride); + std::optional element_address; + if (object_address.has_value()) + element_address = *object_address + i * stride; + FormatValue(stream, element_type, element_data, context, element_address); + } + stream.Printf(" |]"); + return true; +} - std::vector buffer(stride); - size_t bytes_read = - process_sp->ReadMemory(element_address, buffer.data(), stride, error); +// A member's location resolved against the parent's object address and the +// parent's in-buffer data: either an offset within [data] (for constant +// object-relative locations) or a process load address (for exprloc results). +// The member object address is the OCaml object address of the member itself, +// suitable for evaluating expressions on the member's type. +struct ResolvedMemberLocation { + enum class Source { BufferOffset, LoadAddress }; + Source source; + uint64_t buffer_offset = 0; + lldb::addr_t load_address = LLDB_INVALID_ADDRESS; + std::optional member_object_address; +}; - if (bytes_read != stride || error.Fail()) { - OXCAML_EMIT_MARKER(stream, "", - "Failed to read array element {0} at 0x{1:x}; " - "requested {2} bytes, read {3}", - i, element_address, stride, bytes_read); - error.Clear(); - continue; - } +static std::optional +ResolveMemberLocation(Stream &stream, const OxCamlMember &member, + DataExtractor &data, const OxCamlFormatContext &context, + std::optional parent_object_address) { + (void)data; + llvm::Expected result = + member.location.Evaluate(context, parent_object_address); + if (!result) { + OXCAML_EMIT_MARKER( + stream, "", "Failed to evaluate location for member '{0}': {1}", + member.name.value_or(""), llvm::toString(result.takeError())); + return std::nullopt; + } - DataExtractor element_data(buffer.data(), stride, data.GetByteOrder(), - data.GetAddressByteSize()); - FormatValue(stream, element_type, element_data, process_sp, exe_ctx_ref); + ResolvedMemberLocation resolved; + if (result->GetLocationStorage() == + OxCamlLayoutResult::LocationStorage::ObjectRelativeByteOffset) { + resolved.source = ResolvedMemberLocation::Source::BufferOffset; + resolved.buffer_offset = result->GetObjectRelativeByteOffset(); + if (parent_object_address.has_value()) + resolved.member_object_address = + *parent_object_address + resolved.buffer_offset; + } else { + resolved.source = ResolvedMemberLocation::Source::LoadAddress; + resolved.load_address = result->GetLoadAddress(); + resolved.member_object_address = resolved.load_address; } + return resolved; +} - stream.Printf(" |]"); +// Read [byte_size] bytes for a member or discriminator into [out_buffer] +// according to a resolved location. +static bool +ReadResolvedMemberBytes(Stream &stream, const OxCamlMember &member, + uint64_t byte_size, + const ResolvedMemberLocation &resolved, + DataExtractor &data, const OxCamlFormatContext &context, + llvm::SmallVectorImpl &out_buffer) { + out_buffer.resize(byte_size); + if (resolved.source == ResolvedMemberLocation::Source::BufferOffset) { + uint64_t offset = resolved.buffer_offset; + if (offset + byte_size > data.GetByteSize()) { + OXCAML_EMIT_MARKER( + stream, "", + "Member '{0}' at object-relative offset {1} (+{2} bytes) extends " + "past available data ({3} bytes)", + member.name.value_or(""), offset, byte_size, + data.GetByteSize()); + return false; + } + if (data.CopyData(offset, byte_size, out_buffer.data()) != byte_size) { + OXCAML_EMIT_MARKER( + stream, "", + "Member '{0}': failed to copy {1} bytes from offset {2}", + member.name.value_or(""), byte_size, offset); + return false; + } + return true; + } + + Status error; + size_t bytes_read = context.process_sp->ReadMemory( + resolved.load_address, out_buffer.data(), byte_size, error); + if (bytes_read != byte_size || error.Fail()) { + OXCAML_EMIT_MARKER( + stream, "", + "Member '{0}': failed to read {1} bytes from 0x{2:x}: {3}", + member.name.value_or(""), byte_size, resolved.load_address, + error.AsCString()); + return false; + } return true; } static bool FormatMember(Stream &stream, const OxCamlMember &member, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref) { + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address) { + auto resolved = + ResolveMemberLocation(stream, member, data, context, object_address); + if (!resolved.has_value()) + return true; + if (member.IsBitField()) { - uint64_t bit_offset = member.bit_offset.value(); - uint64_t bit_size = member.bit_size.value(); - lldb::offset_t byte_offset = member.data_member_location; + llvm::Expected bit_offset_result = + member.bit_offset->Evaluate(context, object_address); + if (!bit_offset_result) { + OXCAML_EMIT_MARKER(stream, "", + "Failed to evaluate bit offset for member '{0}': {1}", + member.name.value_or(""), + llvm::toString(bit_offset_result.takeError())); + return true; + } + llvm::Expected bit_size_result = + member.bit_size->Evaluate(context, object_address); + if (!bit_size_result) { + OXCAML_EMIT_MARKER(stream, "", + "Failed to evaluate bit size for member '{0}': {1}", + member.name.value_or(""), + llvm::toString(bit_size_result.takeError())); + return true; + } + uint64_t bit_offset = bit_offset_result->GetScalar(); + uint64_t bit_size = bit_size_result->GetScalar(); - // Check if bit-field spans multiple words (not currently supported) - // Multi-word bit-fields would require reading multiple 64-bit words and - // combining bits across word boundaries ENSURE(bit_offset + bit_size <= 64, stream, "", "Bit-field '{0}' spans multiple words (offset={1}, size={2}); " "multi-word bit-fields not yet supported", member.name.value_or(""), bit_offset, bit_size); - ENSURE(byte_offset + sizeof(uint64_t) <= data.GetByteSize(), stream, - "", - "Not enough data ({0} bytes) to read bit-field '{1}' starting at " - "offset {2}", - data.GetByteSize(), member.name.value_or(""), - static_cast(byte_offset)); + llvm::SmallVector word; + if (!ReadResolvedMemberBytes(stream, member, sizeof(uint64_t), *resolved, + data, context, word)) + return true; - uint64_t full_value = data.GetU64(&byte_offset); + DataExtractor word_data(word.data(), word.size(), data.GetByteOrder(), + data.GetAddressByteSize()); + lldb::offset_t off = 0; + uint64_t full_value = word_data.GetU64(&off); uint64_t bit_mask = MakeLowBitMask(bit_size); uint64_t extracted = (full_value >> bit_offset) & bit_mask; + // The extracted bit-field value is a fresh scalar with no header; nested + // expressions cannot reference an object address through it. DataExtractor bit_data(&extracted, sizeof(extracted), data.GetByteOrder(), data.GetAddressByteSize()); + return FormatValue(stream, member.GetType(), bit_data, context, + /*object_address=*/std::nullopt); + } - return FormatValue(stream, member.GetType(), bit_data, process_sp, - exe_ctx_ref); + // Resolve the member type's dynamic byte size using the member's own + // object address, so nested structures with exprloc-valued sizes read the + // right amount of memory. + llvm::Expected member_byte_size_expected = ResolveTypeByteSize( + member.GetType(), resolved->member_object_address, context); + if (!member_byte_size_expected) { + OXCAML_EMIT_MARKER( + stream, "", + "Failed to evaluate byte size for member '{0}' (type '{1}'): {2}", + member.name.value_or(""), member.GetType()->GetDisplayName(), + llvm::toString(member_byte_size_expected.takeError())); + return true; } + uint64_t member_byte_size = *member_byte_size_expected; - DataExtractor member_data(data, member.data_member_location, - member.GetType()->GetByteSize()); - return FormatValue(stream, member.GetType(), member_data, process_sp, - exe_ctx_ref); + llvm::SmallVector buffer; + if (!ReadResolvedMemberBytes(stream, member, member_byte_size, *resolved, + data, context, buffer)) + return true; + + DataExtractor member_data(buffer.data(), member_byte_size, + data.GetByteOrder(), data.GetAddressByteSize()); + return FormatValue(stream, member.GetType(), member_data, context, + resolved->member_object_address); +} + +// Returns true if both members have constant data_member_location 0. +static bool AreBothMembersAtConstantOffsetZero(const OxCamlMember &a, + const OxCamlMember &b) { + return a.location.IsConstant() && a.location.GetConstant() == 0 && + b.location.IsConstant() && b.location.GetConstant() == 0; } static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref) { + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address) { const auto &members = struct_type->GetMembers(); const auto &variant_parts = struct_type->GetVariantParts(); - // Special case for OCaml variants: Structures with no direct members and - // exactly one variant part are formatted without braces (just the variant - // content directly). This represents the typical OCaml variant structure - // encoding. + // OCaml variant: a structure with no direct members and exactly one + // variant part is rendered as the variant content alone (no braces). if (members.empty() && variant_parts.size() == 1) { - return FormatVariantPart(stream, variant_parts[0], data, process_sp, - exe_ctx_ref, true); + return FormatVariantPart(stream, variant_parts[0], data, context, + object_address, true); } - // Special case for OCaml exceptions: Union-style structure with "exn" and - // "raw" members. Exceptions have both members at the same offset. We format - // only the "raw" member. This hardcodes the current format of the OxCaml - // compiler. + // OCaml exception: a union-style struct with "exn" and "raw" members both + // at offset 0. Format only via FormatException. if (members.size() == 2 && variant_parts.empty() && members[0].name.has_value() && members[1].name.has_value() && - members[0].data_member_location == 0 && - members[1].data_member_location == 0) { + AreBothMembersAtConstantOffsetZero(members[0], members[1])) { const std::string &name0 = members[0].name.value(); const std::string &name1 = members[1].name.value(); if ((name0 == "exn" && name1 == "raw") || (name0 == "raw" && name1 == "exn")) { - return FormatException(stream, data, process_sp, exe_ctx_ref); + return FormatException(stream, data, context); } } - // Regular case: structure with members and/or multiple variant parts - // Determine formatting based on type bool is_tuple = struct_type->IsTuple(); const char *open_delim = is_tuple ? "(" : "{ "; const char *close_delim = is_tuple ? ")" : " }"; @@ -759,7 +968,6 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, bool has_content = false; - // Format regular members first for (size_t i = 0; i < members.size(); ++i) { if (has_content) stream.Printf("%s", separator); @@ -768,16 +976,15 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, stream.Printf("%s = ", members[i].name.value().c_str()); } - FormatMember(stream, members[i], data, process_sp, exe_ctx_ref); + FormatMember(stream, members[i], data, context, object_address); has_content = true; } - // Format variant parts for (size_t i = 0; i < variant_parts.size(); ++i) { if (has_content) stream.Printf("%s", separator); - FormatVariantPart(stream, variant_parts[i], data, process_sp, exe_ctx_ref, + FormatVariantPart(stream, variant_parts[i], data, context, object_address, false); has_content = true; } @@ -788,118 +995,100 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, } static bool FormatValue(Stream &stream, OxCamlType *type, DataExtractor &data, - lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref) { + const OxCamlFormatContext &context, + std::optional object_address) { if (!type) { Log *log = GetLog(OxCamlLog::Formatting); LLDB_LOG( log, "FormatValue: No type information available, using fallback formatter"); - return FormatFallback(stream, type, data, process_sp); + return FormatFallback(stream, type, data); } switch (type->GetKind()) { case OxCamlType::Value: - return oxcaml::FormatOxCamlValue(stream, data, process_sp, exe_ctx_ref); + return oxcaml::FormatOxCamlValue(stream, data, context.process_sp, + context.exe_ctx_ref); case OxCamlType::UnboxedBase: return FormatUnboxedBase(stream, static_cast(type), - data, process_sp); + data); case OxCamlType::Enum: - return FormatEnum(stream, static_cast(type), data, - process_sp); + return FormatEnum(stream, static_cast(type), data); case OxCamlType::Pointer: return FormatPointer(stream, static_cast(type), data, - process_sp, exe_ctx_ref); + context); case OxCamlType::Typedef: return FormatTypedef(stream, static_cast(type), data, - process_sp, exe_ctx_ref); + context, object_address); case OxCamlType::Structure: return FormatStructure(stream, static_cast(type), - data, process_sp, exe_ctx_ref); + data, context, object_address); case OxCamlType::Array: return FormatArray(stream, static_cast(type), data, - process_sp, exe_ctx_ref); + context, object_address); case OxCamlType::Placeholder: return FormatPlaceholder(stream, static_cast(type), - data, process_sp); + data); case OxCamlType::Unknown: - return FormatUnknown(stream, static_cast(type), data, - process_sp); + return FormatUnknown(stream, static_cast(type), data); } return false; } -// ============================================================================ -// Variant Formatting -// ============================================================================ -// -// ## Problem Overview -// -// OCaml variants present a formatting challenge: the actual memory size of a -// variant value depends on which constructor is active at runtime. In the -// current implementation of the OxCaml compiler and the LLDB plugin, the DWARF -// information only provides static size information (the base structure size), -// but each variant constructor may have a different payload size. -// -// ## Current Approach: Approximate Two-Pass Strategy -// -// Since the DWARF doesn't encode dynamic size calculations (which would require -// DWARF expressions), we use an estimation approach: -// -// 1. **First Pass - Read Discriminators**: -// - Calculate the minimum memory needed to read all discriminators -// - Read enough memory to analyze which variant constructors are active -// -// 2. **Second Pass - Estimate Total Size**: -// - Based on active variants, calculate the maximum offset required -// - This includes: base structure members + active variant member payloads -// - Read the estimated total memory needed -// -// ## Key Functions: -// -// - `ReadDiscriminatorValue()` - Extracts discriminator value from data -// - `CalculateMinimumSizeForDiscriminators()` - Computes memory needed for -// discriminator analysis -// - `FindActiveVariantsInStructure()` - Determines which variants are active -// based on discriminator values -// - `EstimatePointerAllocationSize()` - Estimates total allocation size by -// examining all active variant payloads -// - `FormatVariantPart()` - Main dispatcher for variant formatting -// - `FormatVariantPartOxCaml()` - OCaml-style variant formatting -// - `FormatVariantPartGeneric()` - Generic variant formatting -// -// ## Limitations -// -// This approach provides an estimate rather than exact sizes: -// - We calculate the maximum offset across all members in the active variant -// - Member type sizes may themselves be estimates (e.g., nested structures) -// - The actual memory layout might be more compact than our calculation -// suggests -// -// A more precise solution would require the OCaml compiler to emit DWARF -// expressions that dynamically calculate exact sizes based on runtime values. -// -// ============================================================================ - static std::optional -ReadDiscriminatorValue(const OxCamlVariantPart &variant_part, - DataExtractor &data) { +ReadDiscriminatorValue(Stream &stream, const OxCamlVariantPart &variant_part, + DataExtractor &data, const OxCamlFormatContext &context, + std::optional object_address) { const auto &discriminator = variant_part.GetDiscriminator(); - lldb::offset_t discr_offset = discriminator.data_member_location; - uint64_t discriminator_byte_size = discriminator.GetType()->GetByteSize(); + // The discriminator value is later returned as a uint64_t, so wider + // discriminators cannot fit and we refuse to read them here. + if (discriminator_byte_size == 0 || + discriminator_byte_size > sizeof(uint64_t)) + return std::nullopt; + + auto resolved = ResolveMemberLocation(stream, discriminator, data, context, + object_address); + if (!resolved.has_value()) + return std::nullopt; + + llvm::SmallVector buffer; + if (!ReadResolvedMemberBytes(stream, discriminator, discriminator_byte_size, + *resolved, data, context, buffer)) + return std::nullopt; + DataExtractor discr_data(buffer.data(), buffer.size(), data.GetByteOrder(), + data.GetAddressByteSize()); + lldb::offset_t cursor = 0; std::optional apint = - helpers::ExtractAPInt(data, &discr_offset, discriminator_byte_size); - if (!apint.has_value() || apint->getBitWidth() > 64) { + helpers::ExtractAPInt(discr_data, &cursor, discriminator_byte_size); + if (!apint.has_value() || apint->getBitWidth() > 64) return std::nullopt; - } uint64_t value = apint->getZExtValue(); if (discriminator.IsBitField()) { - uint64_t bit_offset = discriminator.bit_offset.value(); - uint64_t bit_size = discriminator.bit_size.value(); + Log *log = GetLog(OxCamlLog::Formatting); + auto bit_offset_result = + discriminator.bit_offset->Evaluate(context, object_address); + if (!bit_offset_result) { + LLDB_LOG_ERROR(log, bit_offset_result.takeError(), + "ReadDiscriminatorValue: bit_offset evaluation failed for " + "discriminator '{1}': {0}", + discriminator.name); + return std::nullopt; + } + auto bit_size_result = + discriminator.bit_size->Evaluate(context, object_address); + if (!bit_size_result) { + LLDB_LOG_ERROR(log, bit_size_result.takeError(), + "ReadDiscriminatorValue: bit_size evaluation failed for " + "discriminator '{1}': {0}", + discriminator.name); + return std::nullopt; + } + uint64_t bit_offset = bit_offset_result->GetScalar(); + uint64_t bit_size = bit_size_result->GetScalar(); if (bit_offset + bit_size > 64) return std::nullopt; uint64_t discr_mask = MakeLowBitMask(bit_size); @@ -909,127 +1098,6 @@ ReadDiscriminatorValue(const OxCamlVariantPart &variant_part, return value; } -static uint64_t -CalculateMinimumSizeForDiscriminators(OxCamlStructureType *struct_type) { - uint64_t max_discriminator_end = 0; - - const auto &variant_parts = struct_type->GetVariantParts(); - for (const auto &variant_part : variant_parts) { - const auto &discr = variant_part.GetDiscriminator(); - uint64_t discr_end = - discr.data_member_location + discr.GetType()->GetByteSize(); - max_discriminator_end = std::max(max_discriminator_end, discr_end); - } - - return max_discriminator_end; -} - -static std::vector -FindActiveVariantsInStructure(OxCamlStructureType *struct_type, - DataExtractor &data) { - std::vector active_variants; - Log *log = GetLog(OxCamlLog::UserVisibleErrors); - - const auto &variant_parts = struct_type->GetVariantParts(); - for (const auto &variant_part : variant_parts) { - auto discr_value_opt = ReadDiscriminatorValue(variant_part, data); - if (!discr_value_opt.has_value()) { - LLDB_LOG(log, - "Failed to read discriminator value for variant part with " - "discriminator '{0}'", - variant_part.GetDiscriminator().name); - continue; // Skip variant part if discriminator cannot be read - } - - auto active_variant = variant_part.GetActiveVariant(*discr_value_opt); - if (active_variant.has_value()) { - active_variants.push_back(*active_variant); - } - } - - return active_variants; -} - -static uint64_t EstimatePointerAllocationSize(OxCamlType *type, - DataExtractor &data) { - OX_ASSERT(type != nullptr, - "EstimatePointerAllocationSize called with null type (ptr={0:P})", - type); - - while (type->GetKind() == OxCamlType::Typedef) { - type = static_cast(type)->GetUnderlyingType(); - } - - // We assume all types except for structures return accurate sizes. Only - // structures can have variant parts. - if (type->GetKind() != OxCamlType::Structure) { - return type->GetByteSize(); - } - - auto *struct_type = static_cast(type); - uint64_t max_end_offset = type->GetByteSize(); - - const auto &members = struct_type->GetMembers(); - for (const auto &member : members) { - // If the size that is returned here is not exact (e.g., as in the case of - // structures, then our estimate here is off). That's why it is not exact. - uint64_t member_end = - member.data_member_location + member.GetType()->GetByteSize(); - max_end_offset = std::max(max_end_offset, member_end); - } - - auto active_variants = FindActiveVariantsInStructure(struct_type, data); - for (const auto *variant : active_variants) { - for (const auto &member : variant->members) { - uint64_t member_end = - member.data_member_location + member.GetType()->GetByteSize(); - max_end_offset = std::max(max_end_offset, member_end); - } - } - - return max_end_offset; -} - -static uint64_t ComputeActualPointerSize(OxCamlType *pointed_to, - lldb::addr_t adjusted_address, - const DataExtractor &data, - lldb::ProcessSP process_sp) { - uint64_t type_size = pointed_to->GetByteSize(); - - if (pointed_to->GetKind() != OxCamlType::Structure) { - return type_size; - } - - auto *struct_type = static_cast(pointed_to); - const auto &variant_parts = struct_type->GetVariantParts(); - - if (variant_parts.empty()) { - return type_size; - } - - uint64_t min_discriminator_size = - CalculateMinimumSizeForDiscriminators(struct_type); - uint64_t temp_read_size = std::max(min_discriminator_size, type_size); - - // Two-pass approach for structures with variant parts: - // 1. Read enough data to analyze all discriminators - // 2. Calculate precise size based on active variants - Status error; - std::vector temp_buffer(temp_read_size); - size_t bytes_read = process_sp->ReadMemory( - adjusted_address, temp_buffer.data(), temp_buffer.size(), error); - - if (bytes_read >= min_discriminator_size) { - DataExtractor heap_data(temp_buffer.data(), bytes_read, data.GetByteOrder(), - data.GetAddressByteSize()); - uint64_t estimated_size = - EstimatePointerAllocationSize(pointed_to, heap_data); - return estimated_size; - } - - return type_size; -} - enum VariantKind { SingleEntryVariant, // 1 member, no name TupleVariant, // >1 members, no names @@ -1038,10 +1106,13 @@ enum VariantKind { // Format variant part with generic square bracket format: // Name[mem1 = val1; ...; memN = valN] -static bool FormatVariantPartGeneric( - Stream &stream, const OxCamlVariantPart &variant_part, DataExtractor &data, - lldb::ProcessSP process_sp, const ExecutionContextRef &exe_ctx_ref, - uint64_t discr_value, const std::vector &members) { +static bool FormatVariantPartGeneric(Stream &stream, + const OxCamlVariantPart &variant_part, + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address, + uint64_t discr_value, + const std::vector &members) { std::string discr_name = "Unknown"; const auto &discriminator = variant_part.GetDiscriminator(); if (discriminator.GetType()->GetKind() == OxCamlType::Enum) { @@ -1062,7 +1133,7 @@ static bool FormatVariantPartGeneric( stream.Printf("; "); if (members[i].name.has_value()) stream.Printf("%s = ", members[i].name.value().c_str()); - FormatMember(stream, members[i], data, process_sp, exe_ctx_ref); + FormatMember(stream, members[i], data, context, object_address); } stream.Printf("]"); } @@ -1070,10 +1141,13 @@ static bool FormatVariantPartGeneric( return true; } -static bool FormatVariantPartOxCaml( - Stream &stream, const OxCamlVariantPart &variant_part, DataExtractor &data, - lldb::ProcessSP process_sp, const ExecutionContextRef &exe_ctx_ref, - uint64_t discr_value, const std::vector &members) { +static bool FormatVariantPartOxCaml(Stream &stream, + const OxCamlVariantPart &variant_part, + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address, + uint64_t discr_value, + const std::vector &members) { const auto &discriminator = variant_part.GetDiscriminator(); ENSURE(discriminator.GetType()->GetKind() == OxCamlType::Enum, stream, @@ -1150,7 +1224,7 @@ static bool FormatVariantPartOxCaml( } } - FormatMember(stream, members[i], data, process_sp, exe_ctx_ref); + FormatMember(stream, members[i], data, context, object_address); } stream.Printf("%s", close_delim); @@ -1158,18 +1232,17 @@ static bool FormatVariantPartOxCaml( return true; } -// Main variant formatting dispatcher -// -// Special handling for artificial discriminators: -// - Artificial discriminators (e.g., Pointer/Immediate) with exactly one member -// in the active variant are displayed transparently (member content only) -// - All other cases dispatch to either OCaml or generic formatting +// An artificial discriminator (e.g. Pointer/Immediate) with exactly one +// member in the active variant is displayed transparently (member content +// only, no discriminator name or brackets). static bool FormatVariantPart(Stream &stream, const OxCamlVariantPart &variant_part, - DataExtractor &data, lldb::ProcessSP process_sp, - const ExecutionContextRef &exe_ctx_ref, - bool is_ocaml_variant = false) { - auto discr_value_opt = ReadDiscriminatorValue(variant_part, data); + DataExtractor &data, + const OxCamlFormatContext &context, + std::optional object_address, + bool is_ocaml_variant) { + auto discr_value_opt = ReadDiscriminatorValue(stream, variant_part, data, + context, object_address); ENSURE(discr_value_opt.has_value(), stream, "", "Discriminator value unreadable (variant={0})", variant_part.GetDiscriminator().name); @@ -1183,18 +1256,16 @@ static bool FormatVariantPart(Stream &stream, const auto &members = (*active_variant)->members; - // Special case: artificial discriminator with exactly one member - // Display the member content directly without discriminator name/brackets if (variant_part.HasArtificialDiscriminator() && members.size() == 1) { - FormatMember(stream, members[0], data, process_sp, exe_ctx_ref); + FormatMember(stream, members[0], data, context, object_address); return true; } if (is_ocaml_variant) { - return FormatVariantPartOxCaml(stream, variant_part, data, process_sp, - exe_ctx_ref, discr_value, members); + return FormatVariantPartOxCaml(stream, variant_part, data, context, + object_address, discr_value, members); } else { - return FormatVariantPartGeneric(stream, variant_part, data, process_sp, - exe_ctx_ref, discr_value, members); + return FormatVariantPartGeneric(stream, variant_part, data, context, + object_address, discr_value, members); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOxCaml.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOxCaml.cpp index 60a63ebc3e2c5..c8bfcce290ced 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOxCaml.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserOxCaml.cpp @@ -8,16 +8,22 @@ #include "DWARFASTParserOxCaml.h" +#include "DWARFAttribute.h" #include "DWARFDIE.h" #include "DWARFDebugInfoEntry.h" #include "DWARFDefines.h" +#include "DWARFFormValue.h" +#include "DWARFUnit.h" #include "SymbolFileDWARF.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Symbol/Type.h" #include "../../Language/OxCaml/LogChannelOxCaml.h" #include "../../Language/OxCaml/OxCamlAssert.h" +#include "Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h" #include "Plugins/TypeSystem/OxCaml/TypeSystemOxCaml.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/CompileUnit.h" @@ -29,18 +35,56 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::plugin::dwarf; -// Custom OCaml DWARF attribute DW_AT_ocaml_offset_record_from_pointer -// This attribute indicates the offset to apply when dereferencing pointers to -// this type -static constexpr uint32_t DW_AT_ocaml_offset_record_from_pointer = 0x3106; -// CR sspies: Technically, this requires an extension of the DWARF -// standard. If we want to upstream this, we should think about whether the -// attribute should be on the structure or on the pointer itself (indicating a -// base offset). For now, we declare it as an ad-hoc attribute here. - // Default size for OCaml values when size attribute is missing static constexpr uint64_t DEFAULT_OCAML_VALUE_SIZE = 8; +namespace { + +// Locate a single attribute on a DIE and return its form value. Returns +// std::nullopt if the attribute is absent or the form value cannot be +// extracted. +std::optional +GetFormValueForAttribute(const DWARFDIE &die, llvm::dwarf::Attribute attr) { + DWARFAttributes attrs = die.GetAttributes(); + for (uint32_t i = 0; i < attrs.Size(); ++i) { + if (attrs.AttributeAtIndex(i) != attr) + continue; + DWARFFormValue form_value; + if (!attrs.ExtractFormValueAtIndex(i, form_value)) + return std::nullopt; + return form_value; + } + return std::nullopt; +} + +// Parse a layout attribute that may be a constant or a DW_FORM_exprloc. +// The (kind, initial_stack) pair is fixed per attribute by the compiler +// contract; callers pass the pair that matches the attribute. +std::optional ParseConstantOrExpression( + const DWARFDIE &die, llvm::dwarf::Attribute attr, + OxCamlLayoutValueKind kind, + OxCamlDynamicLayoutValue::InitialStackLayout initial_stack) { + auto form_value = GetFormValueForAttribute(die, attr); + if (!form_value.has_value()) + return std::nullopt; + + if (form_value->BlockData() == nullptr) + return OxCamlDynamicLayoutValue::MakeConstant(form_value->Unsigned(), kind); + + const DWARFDataExtractor &debug_info_data = die.GetData(); + uint32_t block_length = form_value->Unsigned(); + uint32_t block_offset = + form_value->BlockData() - debug_info_data.GetDataStart(); + DataExtractor expr_data(debug_info_data, block_offset, block_length); + DWARFExpression expr(expr_data); + + DWARFExpressionList list(die.GetModule(), std::move(expr), die.GetCU()); + return OxCamlDynamicLayoutValue::MakeExpression(std::move(list), kind, + initial_stack); +} + +} // namespace + DWARFASTParserOxCaml::DWARFASTParserOxCaml(TypeSystemOxCaml &oxcaml_typesystem) : DWARFASTParser(Kind::DWARFASTParserOxCaml), m_oxcaml_typesystem(oxcaml_typesystem) {} @@ -512,32 +556,38 @@ DWARFASTParserOxCaml::ParseStructureType(const SymbolContext &sc, LLDB_LOG(log, "ParseStructureType: DIE 0x{0:x16}", die_id); - std::optional byte_size_opt = - die.GetAttributeValueAsOptionalUnsigned(llvm::dwarf::DW_AT_byte_size); - if (!byte_size_opt.has_value() || byte_size_opt.value() == 0) { + auto size_opt = ParseConstantOrExpression( + die, llvm::dwarf::DW_AT_byte_size, OxCamlLayoutValueKind::ScalarBytes, + OxCamlDynamicLayoutValue::InitialStackLayout::Empty); + if (!size_opt.has_value()) { + size_opt = ParseConstantOrExpression( + die, llvm::dwarf::DW_AT_bit_size, OxCamlLayoutValueKind::ScalarBits, + OxCamlDynamicLayoutValue::InitialStackLayout::Empty); + } + if (!size_opt.has_value()) { LLDB_LOG(log, - "ParseStructureType: Missing or zero byte_size for DIE 0x{0:x16}", + "ParseStructureType: Missing byte_size and bit_size for DIE " + "0x{0:x16}", die_id); return nullptr; } - uint64_t byte_size = byte_size_opt.value(); + OxCamlDynamicLayoutValue size = std::move(*size_opt); - std::optional name = ExtractTypeName(die); - - auto ocaml_attr = static_cast( - DW_AT_ocaml_offset_record_from_pointer); - std::optional attr_value_opt = - die.GetAttributeValueAsOptionalUnsigned(ocaml_attr); - - int64_t base_offset = 0; - if (attr_value_opt.has_value()) { - base_offset = static_cast(attr_value_opt.value()); - LLDB_LOG( - log, - "ParseStructureType: Found DW_AT_ocaml_offset_record_from_pointer: {0}", - base_offset); + uint64_t static_size_fallback; + if (size.IsConstant()) { + if (size.GetConstant() == 0) { + LLDB_LOG(log, "ParseStructureType: Zero size for DIE 0x{0:x16}", die_id); + return nullptr; + } + static_size_fallback = size.GetKind() == OxCamlLayoutValueKind::ScalarBits + ? (size.GetConstant() + 7) / 8 + : size.GetConstant(); + } else { + static_size_fallback = formatters::oxcaml::helpers::constants::WORD_SIZE; } + std::optional name = ExtractTypeName(die); + std::vector members; std::vector variant_parts; @@ -546,11 +596,14 @@ DWARFASTParserOxCaml::ParseStructureType(const SymbolContext &sc, case llvm::dwarf::DW_TAG_member: { auto member = ParseMember(sc, child_die); if (member.has_value()) { - members.push_back(std::move(*member)); + const char *location_kind = + member->location.IsConstant() ? "constant" : "expression"; LLDB_LOG( - log, "ParseStructureType: Added member {0} at offset {1}, type {2}", - member->name.value_or(""), member->data_member_location, + log, + "ParseStructureType: Added member {0} ({1} location), type {2}", + member->name.value_or(""), location_kind, member->GetType()->GetDisplayName()); + members.push_back(std::move(*member)); } else { LLDB_LOG(log, "ParseStructureType: Failed to parse member, skipping"); } @@ -576,12 +629,12 @@ DWARFASTParserOxCaml::ParseStructureType(const SymbolContext &sc, LLDB_LOG(log, "ParseStructureType: Creating OxCamlStructureType with {0} members, " - "{1} variant parts, size {2}", - members.size(), variant_parts.size(), byte_size); + "{1} variant parts, static-size-fallback {2}", + members.size(), variant_parts.size(), static_size_fallback); return std::make_unique( - die_id, std::move(name), byte_size, std::move(members), - std::move(variant_parts), base_offset); + die_id, std::move(name), std::move(size), static_size_fallback, + std::move(members), std::move(variant_parts)); } std::optional @@ -613,22 +666,24 @@ DWARFASTParserOxCaml::ParseMember(const SymbolContext &sc, member_type_die.GetID()); Reference *member_type_ref = member_type_opt.value(); - std::optional member_offset_opt = - member_die.GetAttributeValueAsOptionalUnsigned( - llvm::dwarf::DW_AT_data_member_location); - if (!member_offset_opt.has_value()) { + auto location_opt = ParseConstantOrExpression( + member_die, llvm::dwarf::DW_AT_data_member_location, + OxCamlLayoutValueKind::Location, + OxCamlDynamicLayoutValue::InitialStackLayout::ObjectAddress); + if (!location_opt.has_value()) { LLDB_LOG(log, "ParseMember: Missing data_member_location for DIE 0x{0:x16}", member_die.GetID()); return std::nullopt; } - uint64_t member_offset = member_offset_opt.value(); - std::optional bit_offset = - member_die.GetAttributeValueAsOptionalUnsigned( - llvm::dwarf::DW_AT_data_bit_offset); - std::optional bit_size = - member_die.GetAttributeValueAsOptionalUnsigned( - llvm::dwarf::DW_AT_bit_size); + auto bit_offset = ParseConstantOrExpression( + member_die, llvm::dwarf::DW_AT_data_bit_offset, + OxCamlLayoutValueKind::ScalarBits, + OxCamlDynamicLayoutValue::InitialStackLayout::Empty); + auto bit_size = ParseConstantOrExpression( + member_die, llvm::dwarf::DW_AT_bit_size, + OxCamlLayoutValueKind::ScalarBits, + OxCamlDynamicLayoutValue::InitialStackLayout::Empty); std::optional artificial_opt = member_die.GetAttributeValueAsOptionalUnsigned( @@ -636,22 +691,20 @@ DWARFASTParserOxCaml::ParseMember(const SymbolContext &sc, bool is_artificial = artificial_opt.has_value() && artificial_opt.value() != 0; - LLDB_LOG(log, "ParseMember: Created member {0} at offset {1}, type {2}{3}", - member_name.value_or(""), member_offset, + LLDB_LOG(log, "ParseMember: Created member {0} ({1}), type {2}{3}", + member_name.value_or(""), + location_opt->IsConstant() ? "constant location" : "expr location", member_type_ref->get()->GetDisplayName(), is_artificial ? " (artificial)" : ""); if (bit_offset.has_value() || bit_size.has_value()) { - LLDB_LOG(log, "ParseMember: Bit field detected - offset: {0}, size: {1}", - bit_offset.value_or(0), bit_size.value_or(0)); + LLDB_LOG(log, "ParseMember: Bit field detected for DIE 0x{0:x16}", + member_die.GetID()); } - return OxCamlMember{std::move(member_name), - member_type_ref, - member_offset, - bit_offset, - bit_size, - is_artificial}; + return OxCamlMember{std::move(member_name), member_type_ref, + std::move(*location_opt), std::move(bit_offset), + std::move(bit_size), is_artificial}; } std::optional @@ -678,8 +731,9 @@ DWARFASTParserOxCaml::ParseVariantPart(const SymbolContext &sc, return std::nullopt; } - LLDB_LOG(log, "ParseVariantPart: Discriminator at offset {0}, type: {1}", - discriminator_member->data_member_location, + LLDB_LOG(log, "ParseVariantPart: Discriminator ({0} location), type: {1}", + discriminator_member->location.IsConstant() ? "constant" + : "expression", discriminator_member->GetType()->GetDisplayName()); std::vector variants; @@ -755,40 +809,37 @@ DWARFASTParserOxCaml::ParseArrayType(const SymbolContext &sc, element_type_die.GetID()); Reference *element_type_ref = element_type_opt.value(); - std::optional byte_stride_opt = - die.GetAttributeValueAsOptionalUnsigned(llvm::dwarf::DW_AT_byte_stride); - uint64_t byte_stride; - if (byte_stride_opt.has_value()) { - byte_stride = byte_stride_opt.value(); - } else { - byte_stride = element_type_ref->get()->GetByteSize(); - LLDB_LOG(log, - "ParseArrayType: No explicit byte_stride, using element size: {0}", - byte_stride); - } + auto byte_stride_opt = ParseConstantOrExpression( + die, llvm::dwarf::DW_AT_byte_stride, OxCamlLayoutValueKind::ScalarBytes, + OxCamlDynamicLayoutValue::InitialStackLayout::Empty); + OxCamlDynamicLayoutValue byte_stride = + byte_stride_opt.has_value() ? std::move(*byte_stride_opt) + : OxCamlDynamicLayoutValue::MakeConstant( + element_type_ref->get()->GetByteSize(), + OxCamlLayoutValueKind::ScalarBytes); - std::optional count; + std::optional count; for (DWARFDIE child_die : die.children()) { if (child_die.Tag() == llvm::dwarf::DW_TAG_subrange_type) { - auto subrange_count_opt = child_die.GetAttributeValueAsOptionalUnsigned( - llvm::dwarf::DW_AT_count); - if (subrange_count_opt.has_value()) { - count = subrange_count_opt.value(); - LLDB_LOG(log, "ParseArrayType: Found subrange count: {0}", - count.value()); - } + count = ParseConstantOrExpression( + child_die, llvm::dwarf::DW_AT_count, + OxCamlLayoutValueKind::ScalarElements, + OxCamlDynamicLayoutValue::InitialStackLayout::Empty); break; } } LLDB_LOG(log, "ParseArrayType: Creating OxCamlArrayType with element type {0}, " - "stride {1}, count {2}", - element_type_ref->get()->GetDisplayName(), byte_stride, - count.has_value() ? std::to_string(count.value()) : "unknown"); - - return std::make_unique( - die_id, std::move(name), element_type_ref, count, byte_stride); + "{1} stride, {2} count", + element_type_ref->get()->GetDisplayName(), + byte_stride.IsConstant() ? "constant" : "expression", + count.has_value() ? (count->IsConstant() ? "constant" : "expression") + : "unknown"); + + return std::make_unique(die_id, std::move(name), + element_type_ref, std::move(count), + std::move(byte_stride)); } std::unique_ptr diff --git a/lldb/source/Plugins/TypeSystem/OxCaml/CMakeLists.txt b/lldb/source/Plugins/TypeSystem/OxCaml/CMakeLists.txt index 627617d133dba..ba27f64c1b5de 100644 --- a/lldb/source/Plugins/TypeSystem/OxCaml/CMakeLists.txt +++ b/lldb/source/Plugins/TypeSystem/OxCaml/CMakeLists.txt @@ -2,10 +2,12 @@ set(LLVM_LINK_COMPONENTS Support) add_lldb_library(lldbPluginTypeSystemOxCaml PLUGIN TypeSystemOxCaml.cpp + OxCamlDynamicLayoutValue.cpp OxCamlTypes.cpp LINK_LIBS lldbCore + lldbExpression lldbSymbol lldbTarget lldbUtility diff --git a/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.cpp b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.cpp new file mode 100644 index 0000000000000..a2cee4771002a --- /dev/null +++ b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.cpp @@ -0,0 +1,181 @@ +//===-- OxCamlDynamicLayoutValue.cpp ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "OxCamlDynamicLayoutValue.h" + +#include "../../Language/OxCaml/LogChannelOxCaml.h" +#include "../../Language/OxCaml/OxCamlAssert.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Scalar.h" +#include "llvm/Support/Error.h" + +using namespace lldb; +using namespace lldb_private; + +// ============================================================================ +// OxCamlDynamicLayoutValue +// ============================================================================ + +OxCamlDynamicLayoutValue +OxCamlDynamicLayoutValue::MakeConstant(uint64_t value, + OxCamlLayoutValueKind kind) { + return OxCamlDynamicLayoutValue(kind, InitialStackLayout::Empty, value, + std::nullopt); +} + +OxCamlDynamicLayoutValue +OxCamlDynamicLayoutValue::MakeExpression(DWARFExpressionList expression, + OxCamlLayoutValueKind kind, + InitialStackLayout initial_stack) { + return OxCamlDynamicLayoutValue(kind, initial_stack, 0, + std::move(expression)); +} + +static Value MakeObjectAddressValue(lldb::addr_t address) { + Value v; + v.GetScalar() = address; + v.SetValueType(Value::ValueType::Scalar); + return v; +} + +// Wrap [error] with an OxCaml-channel log entry and return it. All evaluation +// failures (DWARF errors, missing object address, kind mismatch) flow through +// here so every call site gets consistent logging on the user-visible channel. +// The caller is responsible for emitting a user-visible formatter marker +// (OXCAML_EMIT_MARKER) when the failure surfaces in formatter output. +static llvm::Error LogAndReturnError(llvm::Error error) { + std::string message = llvm::toString(std::move(error)); + if (Log *log = GetLog(OxCamlLog::UserVisibleErrors)) + LLDB_LOG(log, "OxCamlDynamicLayoutValue evaluation failed: {0}", message); + return llvm::createStringError(llvm::inconvertibleErrorCode(), message); +} + +llvm::Expected OxCamlDynamicLayoutValue::Evaluate( + const OxCamlFormatContext &context, + std::optional object_address) const { + if (IsConstant()) { + if (m_kind == OxCamlLayoutValueKind::Location) + return OxCamlLayoutResult::MakeObjectRelativeByteOffset(m_constant); + return OxCamlLayoutResult::MakeScalar(m_kind, m_constant); + } + + ExecutionContext exe_ctx(context.exe_ctx_ref); + + Value initial_value; + const Value *initial_value_ptr = nullptr; + if (m_initial_stack == InitialStackLayout::ObjectAddress) { + if (!object_address.has_value()) + return LogAndReturnError(llvm::createStringError( + "OxCaml dynamic layout expression needs the OCaml object address " + "but none is available")); + initial_value = MakeObjectAddressValue(*object_address); + initial_value_ptr = &initial_value; + } + + Value object_address_value; + const Value *object_address_ptr = nullptr; + if (object_address.has_value()) { + object_address_value = MakeObjectAddressValue(*object_address); + object_address_ptr = &object_address_value; + } + + // Pass the current frame's RegisterContext so DWARF expressions that mention + // registers (DW_OP_breg*, DW_OP_regx, etc.) can be evaluated correctly. + RegisterContext *reg_ctx = nullptr; + if (StackFrame *frame = exe_ctx.GetFramePtr()) + reg_ctx = frame->GetRegisterContext().get(); + + llvm::Expected result = + m_expression->Evaluate(&exe_ctx, reg_ctx, + /*func_load_addr=*/LLDB_INVALID_ADDRESS, + initial_value_ptr, object_address_ptr); + if (!result) + return LogAndReturnError(result.takeError()); + + if (m_kind == OxCamlLayoutValueKind::Location) { + if (result->GetValueType() != Value::ValueType::LoadAddress) + return LogAndReturnError(llvm::createStringError( + "OxCaml location-valued expression did not produce a load address " + "(value-type %d); a trailing DW_OP_stack_value would make a " + "location-valued attribute scalar by mistake", + static_cast(result->GetValueType()))); + return OxCamlLayoutResult::MakeLoadAddress( + result->GetScalar().ULongLong(LLDB_INVALID_ADDRESS)); + } + + if (result->GetValueType() != Value::ValueType::Scalar) + return LogAndReturnError(llvm::createStringError( + "OxCaml scalar-valued expression did not produce an implicit scalar " + "(value-type %d); did the expression omit DW_OP_stack_value?", + static_cast(result->GetValueType()))); + return OxCamlLayoutResult::MakeScalar(m_kind, + result->GetScalar().ULongLong()); +} + +// ============================================================================ +// OxCamlLayoutResult +// ============================================================================ + +OxCamlLayoutResult OxCamlLayoutResult::MakeScalar(OxCamlLayoutValueKind kind, + uint64_t scalar) { + OX_ASSERT(kind != OxCamlLayoutValueKind::Location, + "MakeScalar requires a scalar kind (got {0})", + static_cast(kind)); + return OxCamlLayoutResult(kind, LocationStorage::ObjectRelativeByteOffset, + scalar, LLDB_INVALID_ADDRESS, 0); +} + +OxCamlLayoutResult +OxCamlLayoutResult::MakeLoadAddress(lldb::addr_t load_address) { + return OxCamlLayoutResult(OxCamlLayoutValueKind::Location, + LocationStorage::LoadAddress, 0, load_address, 0); +} + +OxCamlLayoutResult +OxCamlLayoutResult::MakeObjectRelativeByteOffset(uint64_t byte_offset) { + return OxCamlLayoutResult(OxCamlLayoutValueKind::Location, + LocationStorage::ObjectRelativeByteOffset, 0, + LLDB_INVALID_ADDRESS, byte_offset); +} + +uint64_t OxCamlLayoutResult::GetScalar() const { + OX_ASSERT(m_kind != OxCamlLayoutValueKind::Location, + "GetScalar called on a location-valued result (kind={0})", + static_cast(m_kind)); + return m_scalar; +} + +OxCamlLayoutResult::LocationStorage +OxCamlLayoutResult::GetLocationStorage() const { + OX_ASSERT(m_kind == OxCamlLayoutValueKind::Location, + "GetLocationStorage called on a non-location result (kind={0})", + static_cast(m_kind)); + return m_location_storage; +} + +lldb::addr_t OxCamlLayoutResult::GetLoadAddress() const { + OX_ASSERT(m_kind == OxCamlLayoutValueKind::Location && + m_location_storage == LocationStorage::LoadAddress, + "GetLoadAddress called on a non-load-address result (kind={0}, " + "storage={1})", + static_cast(m_kind), static_cast(m_location_storage)); + return m_load_address; +} + +uint64_t OxCamlLayoutResult::GetObjectRelativeByteOffset() const { + OX_ASSERT(m_kind == OxCamlLayoutValueKind::Location && + m_location_storage == LocationStorage::ObjectRelativeByteOffset, + "GetObjectRelativeByteOffset called on a non-object-relative " + "result (kind={0}, storage={1})", + static_cast(m_kind), static_cast(m_location_storage)); + return m_object_relative_byte_offset; +} diff --git a/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h new file mode 100644 index 0000000000000..4998396e20974 --- /dev/null +++ b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h @@ -0,0 +1,154 @@ +//===-- OxCamlDynamicLayoutValue.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_OXCAML_OXCAMLDYNAMICLAYOUTVALUE_H +#define LLDB_SOURCE_PLUGINS_TYPESYSTEM_OXCAML_OXCAMLDYNAMICLAYOUTVALUE_H + +#include "../../Language/OxCaml/OxCamlAssert.h" +#include "lldb/Expression/DWARFExpressionList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/lldb-private.h" +#include "llvm/Support/Error.h" +#include +#include + +namespace lldb_private { + +class OxCamlLayoutResult; + +/// Describes the unit of a dynamic-layout value's result. +/// +/// - ScalarBits/ScalarBytes/ScalarElements: the value is a scalar quantity +/// whose unit is fixed by the attribute it came from (e.g. a byte size, a +/// bit offset, an element count). Scalar exprlocs end with +/// DW_OP_stack_value. +/// - Location: the value identifies a memory location. Constants are +/// object-relative byte offsets; exprlocs evaluate to a load address. +enum class OxCamlLayoutValueKind { + ScalarBits, + ScalarBytes, + ScalarElements, + Location, +}; + +/// Session-invariant context for the formatter: process, frame, byte order, +/// pointer size. Set once at the entry point and threaded by const reference +/// through recursive calls. Per-recursion state (e.g. the OCaml object +/// address inherited from an enclosing FormatPointer) is passed as a +/// separate parameter. +struct OxCamlFormatContext { + lldb::ProcessSP process_sp; + ExecutionContextRef exe_ctx_ref; + lldb::ByteOrder byte_order; + uint32_t address_byte_size; +}; + +/// A layout fact that may be a constant or a DWARF expression. +/// +/// The wrapper is generic over the result's value-kind and the expression's +/// initial-stack convention. Parsing helpers fix the (kind, initial_stack) +/// pair per DWARF attribute, since DWARF carries no signal that varies per +/// occurrence. +class OxCamlDynamicLayoutValue { +public: + /// What the DWARF evaluator should pre-load on the expression stack before + /// running the expression. + enum class InitialStackLayout { Empty, ObjectAddress }; + + /// Build a constant layout value. For Location kind, the constant is an + /// object-relative byte offset. + static OxCamlDynamicLayoutValue MakeConstant(uint64_t value, + OxCamlLayoutValueKind kind); + + static OxCamlDynamicLayoutValue + MakeExpression(DWARFExpressionList expression, OxCamlLayoutValueKind kind, + InitialStackLayout initial_stack); + + bool IsConstant() const { return !m_expression.has_value(); } + OxCamlLayoutValueKind GetKind() const { return m_kind; } + InitialStackLayout GetInitialStack() const { return m_initial_stack; } + + /// Returns the constant value. Asserts when IsConstant() is false, because + /// reading the constant out of an expression-valued layout would indicate a + /// bug in the caller. + uint64_t GetConstant() const { + OX_ASSERT(IsConstant(), + "GetConstant() called on a non-constant OxCamlDynamicLayoutValue " + "(kind={0})", + static_cast(m_kind)); + return m_constant; + } + + /// Evaluate the layout value. Constants wrap the stored constant. + /// Expressions invoke the LLDB DWARF evaluator with [object_address] as + /// the raw OCaml object pointer; evaluation fails cleanly when the + /// expression needs an object address (via the initial-stack convention + /// or DW_OP_push_object_address) but none is supplied. + llvm::Expected + Evaluate(const OxCamlFormatContext &context, + std::optional object_address) const; + +private: + OxCamlDynamicLayoutValue(OxCamlLayoutValueKind kind, + InitialStackLayout initial_stack, uint64_t constant, + std::optional expression) + : m_kind(kind), m_initial_stack(initial_stack), m_constant(constant), + m_expression(std::move(expression)) {} + + OxCamlLayoutValueKind m_kind; + InitialStackLayout m_initial_stack; + uint64_t m_constant = 0; + std::optional m_expression; +}; + +/// Tagged result of evaluating an OxCamlDynamicLayoutValue. +/// +/// The kind drives which accessor is valid: +/// - ScalarBits/ScalarBytes/ScalarElements: GetScalar() returns the value in +/// the indicated unit. +/// - Location: GetLocationStorage() indicates whether the result is an +/// absolute LoadAddress or an ObjectRelativeByteOffset still to be combined +/// with the OCaml object pointer. +/// +/// Misuse is a debug assertion, not a runtime fallback. +class OxCamlLayoutResult { +public: + enum class LocationStorage { LoadAddress, ObjectRelativeByteOffset }; + + static OxCamlLayoutResult MakeScalar(OxCamlLayoutValueKind kind, + uint64_t scalar); + static OxCamlLayoutResult MakeLoadAddress(lldb::addr_t load_address); + static OxCamlLayoutResult MakeObjectRelativeByteOffset(uint64_t byte_offset); + + OxCamlLayoutValueKind GetKind() const { return m_kind; } + + uint64_t GetScalar() const; + + LocationStorage GetLocationStorage() const; + lldb::addr_t GetLoadAddress() const; + uint64_t GetObjectRelativeByteOffset() const; + +private: + OxCamlLayoutResult(OxCamlLayoutValueKind kind, + LocationStorage location_storage, uint64_t scalar, + lldb::addr_t load_address, + uint64_t object_relative_byte_offset) + : m_kind(kind), m_location_storage(location_storage), m_scalar(scalar), + m_load_address(load_address), + m_object_relative_byte_offset(object_relative_byte_offset) {} + + OxCamlLayoutValueKind m_kind; + LocationStorage m_location_storage; + uint64_t m_scalar; + lldb::addr_t m_load_address; + uint64_t m_object_relative_byte_offset; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_OXCAML_OXCAMLDYNAMICLAYOUTVALUE_H diff --git a/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlTypes.h b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlTypes.h index c36ab1d26942e..51e8b3a000b85 100644 --- a/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlTypes.h +++ b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlTypes.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_TYPESYSTEM_OXCAML_OXCAMLTYPES_H #include "../../Language/OxCaml/OxCamlHelpers.h" +#include "OxCamlDynamicLayoutValue.h" #include "lldb/Utility/Reference.h" #include "lldb/lldb-private.h" #include @@ -49,8 +50,6 @@ class OxCamlType { virtual uint64_t GetByteSize() const = 0; - virtual int64_t GetPointerAdjustmentOffset() const { return 0; } - virtual std::string GetDefaultDisplayName() const = 0; protected: @@ -188,20 +187,27 @@ class OxCamlPointerType : public OxCamlType { class OxCamlArrayType : public OxCamlType { Reference *m_element_type_ref; - std::optional m_count; - uint64_t m_stride; + /// DW_AT_count, in elements. The storage is optional because DWARF permits + /// unbounded arrays, but OxCaml compiler-emitted array DIEs must have a + /// subrange count expression that reads the runtime block wosize. + std::optional m_count; + /// DW_AT_byte_stride, in bytes. OxCaml compiler output emits this explicitly. + OxCamlDynamicLayoutValue m_stride; public: OxCamlArrayType(lldb::user_id_t die_id, std::optional name, Reference *element_type_ref, - std::optional count, uint64_t stride) + std::optional count, + OxCamlDynamicLayoutValue stride) : OxCamlType(Array, die_id, std::move(name)), - m_element_type_ref(element_type_ref), m_count(count), m_stride(stride) { - } + m_element_type_ref(element_type_ref), m_count(std::move(count)), + m_stride(std::move(stride)) {} OxCamlType *GetElementType() const; - std::optional GetCount() const { return m_count; } - uint64_t GetStride() const { return m_stride; } + const std::optional &GetCount() const { + return m_count; + } + const OxCamlDynamicLayoutValue &GetStride() const { return m_stride; } uint64_t GetByteSize() const override { return formatters::oxcaml::helpers::constants::WORD_SIZE; } @@ -213,9 +219,14 @@ class OxCamlArrayType : public OxCamlType { struct OxCamlMember { std::optional name; Reference *type_ref; - uint64_t data_member_location; - std::optional bit_offset; - std::optional bit_size; + /// Object-address-relative location of this member. Constants are byte + /// offsets from the raw OCaml object pointer; exprlocs evaluate to a load + /// address using the pre-pushed pointer convention. + OxCamlDynamicLayoutValue location; + /// Optional bit-field offset and size. Both are scalar quantities in bits + /// (constants or empty-stack exprlocs). + std::optional bit_offset; + std::optional bit_size; bool is_artificial = false; bool IsBitField() const { @@ -250,34 +261,33 @@ class OxCamlVariantPart { class OxCamlStructureType : public OxCamlType { private: - uint64_t m_byte_size; + /// Dynamic size (ScalarBytes or ScalarBits, constant or expression). The + /// unit is recorded by [m_size.GetKind()]; callers that need bytes must + /// convert. [m_static_size_fallback] (always in bytes) is used by LLDB + /// APIs that need a static size without an execution context. + OxCamlDynamicLayoutValue m_size; + uint64_t m_static_size_fallback; std::vector m_members; std::vector m_variant_parts; - // Custom base offset from DW_AT_ocaml_offset_record_from_pointer. This is - // specific to the DWARF encoding used by the OxCaml compiler. It supports an - // ad-hoc attribute (see DW_AT_ocaml_offset_record_from_pointer in - // DWARFASTParserOxCaml.cpp) that specifies a byte offset to apply when - // dealing with a pointer to a structure. This allows one to factor in the - // header field of a block when the actual pointer points to the first entry - // in the block. - int64_t m_base_offset; - public: OxCamlStructureType(lldb::user_id_t die_id, std::optional name, - uint64_t byte_size, std::vector members, - std::vector variant_parts = {}, - int64_t base_offset = 0) - : OxCamlType(Structure, die_id, std::move(name)), m_byte_size(byte_size), + OxCamlDynamicLayoutValue size, + uint64_t static_size_fallback, + std::vector members, + std::vector variant_parts = {}) + : OxCamlType(Structure, die_id, std::move(name)), + m_size(std::move(size)), + m_static_size_fallback(static_size_fallback), m_members(std::move(members)), - m_variant_parts(std::move(variant_parts)), m_base_offset(base_offset) {} + m_variant_parts(std::move(variant_parts)) {} - uint64_t GetByteSize() const override { return m_byte_size; } + uint64_t GetByteSize() const override { return m_static_size_fallback; } + const OxCamlDynamicLayoutValue &GetDynamicSize() const { return m_size; } const std::vector &GetMembers() const { return m_members; } const std::vector &GetVariantParts() const { return m_variant_parts; } - int64_t GetPointerAdjustmentOffset() const override { return m_base_offset; } bool IsOCamlVariant() const; bool IsTuple() const; diff --git a/lldb/source/Plugins/TypeSystem/OxCaml/TypeSystemOxCaml.cpp b/lldb/source/Plugins/TypeSystem/OxCaml/TypeSystemOxCaml.cpp index f01a2b98ca644..e07775887b067 100644 --- a/lldb/source/Plugins/TypeSystem/OxCaml/TypeSystemOxCaml.cpp +++ b/lldb/source/Plugins/TypeSystem/OxCaml/TypeSystemOxCaml.cpp @@ -338,8 +338,15 @@ void TypeSystemOxCaml::Dump(llvm::raw_ostream &output, llvm::StringRef filter) { auto *at = static_cast(actual_type); output << " (array of " << at->GetElementType()->GetDisplayName(); if (at->GetCount().has_value()) - output << ", count=" << at->GetCount().value(); - output << ", stride=" << at->GetStride() << " bytes)"; + output << ", count=" + << (at->GetCount()->IsConstant() + ? std::to_string(at->GetCount()->GetConstant()) + : std::string("")); + output << ", stride=" + << (at->GetStride().IsConstant() + ? std::to_string(at->GetStride().GetConstant()) + : std::string("")) + << " bytes)"; } break; case OxCamlType::Placeholder: output << " (placeholder - parsing in progress)"; From 5693788961507d31b33f756e6b46d070f5dc5e1d Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Wed, 10 Jun 2026 17:41:26 +0100 Subject: [PATCH 2/9] DW_OP_call* implementations --- .../include/lldb/Expression/DWARFExpression.h | 31 +++ lldb/source/Expression/DWARFExpression.cpp | 177 +++++++++++++----- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 56 ++++++ .../Plugins/SymbolFile/DWARF/DWARFUnit.h | 8 + .../Expression/DWARFExpressionTest.cpp | 146 +++++++++++++++ 5 files changed, 366 insertions(+), 52 deletions(-) diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 37853c0b5a8fc..1510631350013 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -19,6 +19,7 @@ #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" #include "llvm/Support/Error.h" #include +#include namespace lldb_private { @@ -45,8 +46,38 @@ class DWARFExpression { virtual uint16_t GetVersion() const = 0; virtual dw_addr_t GetBaseAddress() const = 0; virtual uint8_t GetAddressByteSize() const = 0; + + /// Return the size in bytes of an offset in the DWARF format of this + /// unit: 4 bytes for the 32-bit DWARF format, 8 bytes for the 64-bit + /// DWARF format. This is the size of the operand of DW_OP_call_ref. + virtual uint8_t GetDWARFOffsetByteSize() const = 0; + virtual llvm::Expected> GetDIEBitSizeAndSign(uint64_t relative_die_offset) const = 0; + + /// Return the DW_AT_location expression of the DIE referenced by a + /// DW_OP_call2, DW_OP_call4 or DW_OP_call_ref operation, together with + /// the delegate of the unit that contains the expression (which may not + /// be this unit for DW_OP_call_ref). + /// + /// \param[in] die_offset + /// The offset of the referenced DIE. If \a unit_relative is true, + /// the offset is relative to the start of this unit + /// (DW_OP_call2/DW_OP_call4), otherwise it is an offset in the + /// .debug_info section (DW_OP_call_ref). + /// + /// \return + /// The location expression data and the delegate to evaluate it + /// with. An empty (zero length) DataExtractor is returned when the + /// referenced DIE has no DW_AT_location attribute; per the DWARF + /// specification the call operation then has no effect. An error is + /// returned if the DIE cannot be resolved or its DW_AT_location is + /// not an expression block (i.e. it is a location list, which is not + /// currently supported here). + virtual llvm::Expected> + GetDIELocationExpression(uint64_t die_offset, + bool unit_relative) const = 0; + virtual dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const = 0; virtual lldb::offset_t GetVendorDWARFOpcodeSize(const DataExtractor &data, diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 52891fcefd68b..c0f0bbefc0008 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -160,9 +160,17 @@ GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset, break; case DW_OP_addr: - case DW_OP_call_ref: // 0x9a 1 address sized offset of DIE (DWARF3) return data.GetAddressByteSize(); + // DW_OP_call_ref takes a single operand: the offset of a DIE in the + // .debug_info section. Its size is that of an offset in the DWARF format + // of the compile unit: 4 bytes for the 32-bit DWARF format, 8 bytes for + // the 64-bit DWARF format. Fall back to the address size if the compile + // unit is not available. + case DW_OP_call_ref: // 0x9a DWARF offset sized offset of DIE (DWARF3) + return dwarf_cu ? dwarf_cu->GetDWARFOffsetByteSize() + : data.GetAddressByteSize(); + // Opcodes with no arguments case DW_OP_deref: // 0x06 case DW_OP_dup: // 0x12 @@ -940,19 +948,27 @@ static Scalar DerefSizeExtractDataHelper(uint8_t *addr_bytes, return addr_data.GetAddress(&addr_data_offset); } -llvm::Expected DWARFExpression::Evaluate( +/// The maximum number of nested DW_OP_call2, DW_OP_call4 and DW_OP_call_ref +/// operations that may be active at once. This guards against cyclic DIE +/// references in (malformed) DWARF, which would otherwise recurse forever. +static constexpr uint32_t g_max_dwarf_call_depth = 64; + +/// Evaluate the DWARF expression in \a opcodes against \a stack. +/// +/// This implements the opcode interpreter loop of DWARFExpression::Evaluate, +/// which provides and initializes the evaluation state and derives the +/// result. It is split out so that DW_OP_call2, DW_OP_call4 and +/// DW_OP_call_ref can evaluate the DW_AT_location expression of the +/// referenced DIE against the caller's state, as if the called expression's +/// opcodes appeared in place of the call operation. +static llvm::Error EvaluateOpcodes( ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::ModuleSP module_sp, const DataExtractor &opcodes, const DWARFExpression::Delegate *dwarf_cu, - const lldb::RegisterKind reg_kind, const Value *initial_value_ptr, - const Value *object_address_ptr) { - - if (opcodes.GetByteSize() == 0) - return llvm::createStringError( - "no location, value may have been optimized out"); - - Stack stack; - + const lldb::RegisterKind reg_kind, const Value *object_address_ptr, + DWARFExpression::Stack &stack, + LocationDescriptionKind &dwarf4_location_description_kind, Value &pieces, + uint64_t &op_piece_offset, const uint32_t call_depth) { Process *process = nullptr; StackFrame *frame = nullptr; Target *target = nullptr; @@ -965,17 +981,10 @@ llvm::Expected DWARFExpression::Evaluate( if (reg_ctx == nullptr && frame) reg_ctx = frame->GetRegisterContext().get(); - if (initial_value_ptr) - stack.push_back(*initial_value_ptr); - lldb::offset_t offset = 0; Value tmp; uint32_t reg_num; - /// Insertion point for evaluating multi-piece expression. - uint64_t op_piece_offset = 0; - Value pieces; // Used for DW_OP_piece - Log *log = GetLog(LLDBLog::Expressions); // A generic type is "an integral type that has the size of an address and an // unspecified signedness". For now, just use the signedness of the operand. @@ -990,11 +999,6 @@ llvm::Expected DWARFExpression::Evaluate( !is_signed)); }; - // The default kind is a memory location. This is updated by any - // operation that changes this, such as DW_OP_stack_value, and reset - // by composition operations like DW_OP_piece. - LocationDescriptionKind dwarf4_location_description_kind = Memory; - while (opcodes.ValidOffset(offset)) { const lldb::offset_t op_offset = offset; const uint8_t op = opcodes.GetU8(&offset); @@ -2099,37 +2103,21 @@ llvm::Expected DWARFExpression::Evaluate( } break; - // OPCODE: DW_OP_call2 - // OPERANDS: - // uint16_t compile unit relative offset of a DIE - // DESCRIPTION: Performs subroutine calls during evaluation - // of a DWARF expression. The operand is the 2-byte unsigned offset of a - // debugging information entry in the current compilation unit. - // - // Operand interpretation is exactly like that for DW_FORM_ref2. - // - // This operation transfers control of DWARF expression evaluation to the - // DW_AT_location attribute of the referenced DIE. If there is no such - // attribute, then there is no effect. Execution of the DWARF expression of - // a DW_AT_location attribute may add to and/or remove from values on the - // stack. Execution returns to the point following the call when the end of - // the attribute is reached. Values on the stack at the time of the call - // may be used as parameters by the called expression and values left on - // the stack by the called expression may be used as return values by prior - // agreement between the calling and called expressions. - case DW_OP_call2: - return llvm::createStringError("unimplemented opcode DW_OP_call2"); - // OPCODE: DW_OP_call4 + // OPCODE: DW_OP_call2, DW_OP_call4, DW_OP_call_ref // OPERANDS: 1 - // uint32_t compile unit relative offset of a DIE - // DESCRIPTION: Performs a subroutine call during evaluation of a DWARF - // expression. For DW_OP_call4, the operand is a 4-byte unsigned offset of - // a debugging information entry in the current compilation unit. + // DW_OP_call2: uint16_t compile unit relative offset of a DIE + // DW_OP_call4: uint32_t compile unit relative offset of a DIE + // DW_OP_call_ref: offset of a DIE in the .debug_info section; the + // operand is 4 bytes in the 32-bit DWARF format and 8 bytes in + // the 64-bit DWARF format + // DESCRIPTION: Performs a DWARF procedure call during evaluation of a + // DWARF expression. // - // Operand interpretation DW_OP_call4 is exactly like that for - // DW_FORM_ref4. + // Operand interpretation of DW_OP_call2, DW_OP_call4 and DW_OP_call_ref + // is exactly like that for DW_FORM_ref2, DW_FORM_ref4 and + // DW_FORM_ref_addr, respectively. // - // This operation transfers control of DWARF expression evaluation to the + // These operations transfer control of DWARF expression evaluation to the // DW_AT_location attribute of the referenced DIE. If there is no such // attribute, then there is no effect. Execution of the DWARF expression of // a DW_AT_location attribute may add to and/or remove from values on the @@ -2138,8 +2126,57 @@ llvm::Expected DWARFExpression::Evaluate( // may be used as parameters by the called expression and values left on // the stack by the called expression may be used as return values by prior // agreement between the calling and called expressions. + case DW_OP_call2: case DW_OP_call4: - return llvm::createStringError("unimplemented opcode DW_OP_call4"); + case DW_OP_call_ref: { + if (!dwarf_cu) + return llvm::createStringError( + "%s found without a compile unit being specified", + DW_OP_value_to_name(op)); + + uint64_t die_offset; + bool unit_relative = true; + if (op == DW_OP_call2) + die_offset = opcodes.GetU16(&offset); + else if (op == DW_OP_call4) + die_offset = opcodes.GetU32(&offset); + else { + // The DW_OP_call_ref operand is an offset in the .debug_info + // section, whose size depends on the DWARF format of the compile + // unit. + die_offset = + opcodes.GetMaxU64(&offset, dwarf_cu->GetDWARFOffsetByteSize()); + unit_relative = false; + } + + auto callee_or_err = + dwarf_cu->GetDIELocationExpression(die_offset, unit_relative); + if (!callee_or_err) + return callee_or_err.takeError(); + const DataExtractor &callee_opcodes = callee_or_err->first; + const DWARFExpression::Delegate *callee_cu = callee_or_err->second; + + // The referenced DIE has no DW_AT_location attribute; per the DWARF + // specification the call operation has no effect. + if (callee_opcodes.GetByteSize() == 0) + break; + + if (call_depth >= g_max_dwarf_call_depth) + return llvm::createStringError( + "DWARF expression call depth exceeds %u, likely due to a cycle " + "of DW_OP_call references", + g_max_dwarf_call_depth); + + // Evaluate the called expression against the current state, as if its + // opcodes appeared in place of the call operation. In particular it + // may consume and push values on the current stack. + if (llvm::Error err = EvaluateOpcodes( + exe_ctx, reg_ctx, module_sp, callee_opcodes, callee_cu, reg_kind, + object_address_ptr, stack, dwarf4_location_description_kind, + pieces, op_piece_offset, call_depth + 1)) + return err; + break; + } // OPCODE: DW_OP_stack_value // OPERANDS: None @@ -2311,6 +2348,42 @@ llvm::Expected DWARFExpression::Evaluate( } } + return llvm::Error::success(); +} + +llvm::Expected DWARFExpression::Evaluate( + ExecutionContext *exe_ctx, RegisterContext *reg_ctx, + lldb::ModuleSP module_sp, const DataExtractor &opcodes, + const DWARFExpression::Delegate *dwarf_cu, + const lldb::RegisterKind reg_kind, const Value *initial_value_ptr, + const Value *object_address_ptr) { + + if (opcodes.GetByteSize() == 0) + return llvm::createStringError( + "no location, value may have been optimized out"); + + Stack stack; + + if (initial_value_ptr) + stack.push_back(*initial_value_ptr); + + /// Insertion point for evaluating multi-piece expression. + uint64_t op_piece_offset = 0; + Value pieces; // Used for DW_OP_piece + + // The default kind is a memory location. This is updated by any + // operation that changes this, such as DW_OP_stack_value, and reset + // by composition operations like DW_OP_piece. + LocationDescriptionKind dwarf4_location_description_kind = Memory; + + if (llvm::Error err = EvaluateOpcodes( + exe_ctx, reg_ctx, module_sp, opcodes, dwarf_cu, reg_kind, + object_address_ptr, stack, dwarf4_location_description_kind, pieces, + op_piece_offset, /*call_depth=*/0)) + return std::move(err); + + Log *log = GetLog(LLDBLog::Expressions); + if (stack.empty()) { // Nothing on the stack, check if we created a piece value from DW_OP_piece // or DW_OP_bit_piece opcodes diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 8b0fade86f177..9d388f06ca16b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -727,6 +727,62 @@ DWARFUnit::GetDIEBitSizeAndSign(uint64_t relative_die_offset) const { return std::pair{bit_size, sign}; } +llvm::Expected> +DWARFUnit::GetDIELocationExpression(uint64_t die_offset, + bool unit_relative) const { + // FIXME: the constness has annoying ripple effects. + DWARFUnit *self = const_cast(this); + DWARFDIE die; + if (unit_relative) { + // DW_OP_call2/DW_OP_call4: the offset is relative to the start of this + // unit. + die = self->GetDIE(GetOffset() + die_offset); + } else { + // DW_OP_call_ref: the offset is relative to the start of the .debug_info + // section and may reference a DIE in another unit. + die = self->GetSymbolFileDWARF().DebugInfo().GetDIE( + DIERef::Section::DebugInfo, die_offset); + } + if (!die) + return llvm::createStringError( + "cannot resolve DW_OP_call target DIE at offset 0x%" PRIx64, + die_offset); + + DWARFFormValue form_value; + if (!die.GetDIE()->GetAttributeValue(die.GetCU(), DW_AT_location, form_value, + /*end_attr_offset_ptr=*/nullptr, + /*check_elaborating_dies=*/true)) + // The DIE has no DW_AT_location attribute. Return an empty expression; + // per the DWARF specification the call operation then has no effect. + return std::pair{DataExtractor(), + static_cast(this)}; + + if (!DWARFFormValue::IsBlockForm(form_value.Form())) + return llvm::createStringError( + "DW_OP_call target DIE at offset 0x%" PRIx64 + " has a DW_AT_location that is not an expression block " + "(location lists are not supported)", + die_offset); + + const uint8_t *block_data = form_value.BlockData(); + uint64_t block_length = form_value.Unsigned(); + if (!block_data || block_length == 0) + return std::pair{DataExtractor(), + static_cast(this)}; + + // The attribute may have been found on an elaborating DIE + // (DW_AT_specification, DW_AT_abstract_origin or DW_AT_signature), so read + // the expression block from, and evaluate it against, the unit that + // actually contains it. + const DWARFUnit *expr_unit = form_value.GetUnit(); + const DWARFDataExtractor &data = expr_unit->GetData(); + uint64_t block_offset = block_data - data.GetDataStart(); + DataExtractor expr_data(data, block_offset, block_length); + expr_data.SetAddressByteSize(expr_unit->GetAddressByteSize()); + return std::pair{expr_data, + static_cast(expr_unit)}; +} + lldb::offset_t DWARFUnit::GetVendorDWARFOpcodeSize(const DataExtractor &data, const lldb::offset_t data_offset, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index f55400eeaa448..8d6e554178ea7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -160,6 +160,14 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID { llvm::Expected> GetDIEBitSizeAndSign(uint64_t relative_die_offset) const override; + uint8_t GetDWARFOffsetByteSize() const override { + return GetFormParams().getDwarfOffsetByteSize(); + } + + llvm::Expected> + GetDIELocationExpression(uint64_t die_offset, + bool unit_relative) const override; + lldb::offset_t GetVendorDWARFOpcodeSize(const DataExtractor &data, const lldb::offset_t data_offset, const uint8_t op) const override; diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index fdc9bfae1876c..2b1eff5fcad1a 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -343,6 +343,152 @@ TEST(DWARFExpression, DW_OP_convert) { llvm::Failed()); } +TEST(DWARFExpression, DW_OP_call) { + // Two compile units. CU0 contains a variable DIE whose DW_AT_location + // pushes 0x2211. CU1, the unit the expressions below are evaluated in, + // contains: + // - a variable DIE whose location pushes 0x47 (CU-relative 0x0e) + // - a variable DIE without DW_AT_location (CU-relative 0x13) + // - a variable DIE whose location calls itself (CU-relative 0x15) + // - a variable DIE whose location adds 1 to the value on top of the + // stack (CU-relative 0x1c) + // DW_OP_call2/DW_OP_call4 offsets are relative to the current unit (CU1), + // whereas the DW_OP_call_ref offset is relative to the start of + // .debug_info and here resolves to the DIE in CU0. + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_386 +DWARF: + debug_abbrev: + - Table: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Code: 0x00000002 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_exprloc + - Code: 0x00000003 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_const_value + Form: DW_FORM_data1 + debug_info: + - Version: 4 + AddrSize: 8 + AbbrevTableID: 0 + AbbrOffset: 0x0 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x000000000000000C + # 0x0000000e: DW_AT_location = DW_OP_const2u(0x2211) + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0x0a, 0x11, 0x22 ] + - AbbrCode: 0x00000000 + - Version: 4 + AddrSize: 8 + AbbrevTableID: 0 + AbbrOffset: 0x0 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x000000000000000C + # CU-relative 0x0e: DW_AT_location = DW_OP_const2u(0x0047) + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0x0a, 0x47, 0x00 ] + # CU-relative 0x13: no DW_AT_location. + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000000 + # CU-relative 0x15: DW_AT_location = DW_OP_call4(0x15), i.e. a DIE + # whose location expression calls itself. + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0x99, 0x15, 0x00, 0x00, 0x00 ] + # CU-relative 0x1c: DW_AT_location = DW_OP_lit1, DW_OP_plus. + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0x31, 0x22 ] + - AbbrCode: 0x00000000 +)"; + + // Offsets of the DIEs above, relative to the start of CU1. + uint8_t offs_const_0x47 = 0x0e; + uint8_t offs_no_location = 0x13; + uint8_t offs_self_call = 0x15; + uint8_t offs_add_one = 0x1c; + // Offset of CU0's constant DIE, relative to the start of .debug_info. + uint8_t offs_cu0_const_0x2211 = 0x0e; + + DWARFExpressionTester t(yamldata, /*cu_index=*/1); + ASSERT_TRUE((bool)t.GetDwarfUnit()); + + bool is_signed = true; + bool not_signed = false; + + // Values left on the stack by the called expression are visible to the + // calling expression. + EXPECT_THAT_EXPECTED(t.Eval({DW_OP_call2, offs_const_0x47, 0x00, // + DW_OP_stack_value}), + llvm::HasValue(GetScalar(64, 0x47, not_signed))); + + EXPECT_THAT_EXPECTED( + t.Eval({DW_OP_call4, offs_const_0x47, 0x00, 0x00, 0x00, // + DW_OP_stack_value}), + llvm::HasValue(GetScalar(64, 0x47, not_signed))); + + // DW_OP_call_ref resolves its offset in .debug_info, finding the DIE in + // CU0 (whereas the same unit-relative offset names the 0x47 DIE in CU1). + EXPECT_THAT_EXPECTED( + t.Eval({DW_OP_call_ref, offs_cu0_const_0x2211, 0x00, 0x00, 0x00, // + DW_OP_stack_value}), + llvm::HasValue(GetScalar(64, 0x2211, not_signed))); + + // Calling a DIE that has no DW_AT_location attribute has no effect. + EXPECT_THAT_EXPECTED(t.Eval({DW_OP_lit4, // + DW_OP_call4, offs_no_location, 0, 0, 0, // + DW_OP_stack_value}), + llvm::HasValue(GetScalar(32, 4, is_signed))); + + // Values on the stack at the time of the call may be used as parameters + // by the called expression. + EXPECT_THAT_EXPECTED(t.Eval({DW_OP_lit4, // + DW_OP_call4, offs_add_one, 0, 0, 0, // + DW_OP_stack_value}), + llvm::HasValue(GetScalar(64, 5, is_signed))); + + // + // Errors. + // + + // A self-referencing call must be diagnosed rather than recurse forever. + EXPECT_THAT_ERROR( + t.Eval({DW_OP_call4, offs_self_call, 0, 0, 0}).takeError(), + llvm::Failed()); + + // No DIE at the given offset (it points into the unit header). + EXPECT_THAT_ERROR(t.Eval({DW_OP_call4, 0x01, 0, 0, 0}).takeError(), + llvm::Failed()); + + // No compile unit. + EXPECT_THAT_ERROR( + Evaluate({DW_OP_call4, offs_const_0x47, 0, 0, 0}).takeError(), + llvm::Failed()); +} + TEST(DWARFExpression, DW_OP_stack_value) { EXPECT_THAT_EXPECTED(Evaluate({DW_OP_stack_value}), llvm::Failed()); } From 9492528d35c2df263d2c75ce6732cd282cf85339 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Wed, 10 Jun 2026 19:01:03 +0100 Subject: [PATCH 3/9] Implicit pointers --- lldb/include/lldb/Core/Value.h | 86 ++++- .../include/lldb/Expression/DWARFExpression.h | 157 ++++++--- lldb/source/Core/Value.cpp | 36 +- lldb/source/Expression/DWARFExpression.cpp | 206 +++++++++++- .../Language/OxCaml/OxCamlFormatters.cpp | 317 +++++++++++++++--- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 40 +++ .../Plugins/SymbolFile/DWARF/DWARFUnit.h | 3 + .../OxCaml/OxCamlDynamicLayoutValue.h | 3 + lldb/source/Target/ABI.cpp | 1 + lldb/source/ValueObject/ValueObject.cpp | 20 ++ lldb/source/ValueObject/ValueObjectChild.cpp | 4 + lldb/source/ValueObject/ValueObjectMemory.cpp | 4 + .../ValueObject/ValueObjectVariable.cpp | 10 + .../Expression/DWARFExpressionTest.cpp | 253 ++++++++++++++ 14 files changed, 1034 insertions(+), 106 deletions(-) diff --git a/lldb/include/lldb/Core/Value.h b/lldb/include/lldb/Core/Value.h index 3714621b469ec..fd34a82cfbb67 100644 --- a/lldb/include/lldb/Core/Value.h +++ b/lldb/include/lldb/Core/Value.h @@ -18,7 +18,9 @@ #include "lldb/lldb-private-types.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include #include #include @@ -26,6 +28,7 @@ namespace lldb_private { class DataExtractor; +class DWARFExpressionDelegate; class ExecutionContext; class Module; class Stream; @@ -49,7 +52,46 @@ class Value { LoadAddress, /// A host address value (for memory in the process that < A is /// using liblldb). - HostAddress + HostAddress, + /// A pointer that does not exist in the process being debugged: the + /// pointer itself was optimized away, but the value it would point at + /// is described by another DWARF DIE (DW_OP_implicit_pointer). m_value + /// is unset (deliberately, so that type-unaware consumers asking for a + /// number receive their fail value rather than something that could be + /// mistaken for a real pointer); the pointee is identified by the + /// ImplicitPointerInfo and can be materialized on demand with + /// DWARFExpression::DereferenceImplicitPointer(). + ImplicitPointer + }; + + /// Identifies the pointed-at value of an implicit pointer (a Value whose + /// type is ValueType::ImplicitPointer). + struct ImplicitPointerInfo { + /// The DWARF unit that contained the DW_OP_implicit_pointer expression; + /// used to resolve die_offset. The pointer is owned by the module's + /// symbol file, which must outlive this value (the same lifetime + /// assumption Value already makes for m_context). + const DWARFExpressionDelegate *delegate = nullptr; + /// The offset of the DIE describing the pointed-at value, relative to + /// the start of the .debug_info section. + uint64_t die_offset = 0; + /// Byte offset into the pointed-at value. + int64_t byte_offset = 0; + }; + + /// A byte range within a composite (DW_OP_piece) value's buffer whose + /// piece is an implicit pointer. The buffer bytes in the range are + /// meaningless placeholders: the table entry, never the bytes, is the + /// piece's value. Consumers reading pointer-sized quantities out of a + /// composite buffer must consult the table (see + /// FindImplicitPointerPiece) before interpreting the bytes. + struct ImplicitPointerPiece { + /// Byte offset of the piece within the value's buffer. + uint64_t buffer_offset = 0; + /// Size of the piece in bytes. + uint64_t byte_size = 0; + /// The pointed-at value. + ImplicitPointerInfo pointee; }; /// Type that describes Value::m_context. @@ -82,6 +124,43 @@ class Value { ValueType GetValueType() const; + /// Make this value an implicit pointer (ValueType::ImplicitPointer) to the + /// value described by the DIE at \a die_offset in the .debug_info section + /// of \a delegate's symbol file, at \a byte_offset bytes into that value. + /// Clears the scalar and data buffer; the pointer has no numeric value. + void SetImplicitPointer(const DWARFExpressionDelegate *delegate, + uint64_t die_offset, int64_t byte_offset); + + /// The pointee of this value when GetValueType() == + /// ValueType::ImplicitPointer, std::nullopt otherwise. + const std::optional &GetImplicitPointer() const { + return m_implicit_pointer; + } + + /// Record that the byte range [buffer_offset, buffer_offset + byte_size) + /// of this value's buffer is an implicit-pointer piece whose actual value + /// is \a pointee. + void AddImplicitPointerPiece(uint64_t buffer_offset, uint64_t byte_size, + const ImplicitPointerInfo &pointee) { + m_implicit_pointer_pieces.push_back({buffer_offset, byte_size, pointee}); + } + + /// The implicit-pointer pieces of this composite value, if any. + llvm::ArrayRef GetImplicitPointerPieces() const { + return m_implicit_pointer_pieces; + } + + /// Return the implicit-pointer piece exactly covering + /// [buffer_offset, buffer_offset + byte_size), or nullptr if there is + /// none. + const ImplicitPointerPiece * + FindImplicitPointerPiece(uint64_t buffer_offset, uint64_t byte_size) const { + for (const ImplicitPointerPiece &piece : m_implicit_pointer_pieces) + if (piece.buffer_offset == buffer_offset && piece.byte_size == byte_size) + return &piece; + return nullptr; + } + AddressType GetValueAddressType() const; ContextType GetContextType() const { return m_context_type; } @@ -182,6 +261,11 @@ class Value { ValueType m_value_type = ValueType::Scalar; ContextType m_context_type = ContextType::Invalid; DataBufferHeap m_data_buffer; + /// Only meaningful when m_value_type == ValueType::ImplicitPointer. + std::optional m_implicit_pointer; + /// Byte ranges of m_data_buffer that are implicit-pointer pieces of a + /// composite (DW_OP_piece) value. + std::vector m_implicit_pointer_pieces; }; class ValueList { diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 1510631350013..dc9bd2142bb2e 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -19,10 +19,87 @@ #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" #include "llvm/Support/Error.h" #include +#include #include namespace lldb_private { +/// \class DWARFExpressionDelegate DWARFExpression.h +/// "lldb/Expression/DWARFExpression.h" Interface through which the DWARF +/// expression evaluator accesses the DWARF unit that contains the expression +/// being evaluated. Implemented by the DWARF symbol file plugin's DWARFUnit. +/// +/// This is a top-level class (rather than nested in DWARFExpression) so that +/// it can be forward declared by code that may not include Expression +/// headers, such as lldb_private::Value. +class DWARFExpressionDelegate { +public: + DWARFExpressionDelegate() = default; + virtual ~DWARFExpressionDelegate() = default; + + virtual uint16_t GetVersion() const = 0; + virtual dw_addr_t GetBaseAddress() const = 0; + virtual uint8_t GetAddressByteSize() const = 0; + + /// Return the size in bytes of an offset in the DWARF format of this + /// unit: 4 bytes for the 32-bit DWARF format, 8 bytes for the 64-bit + /// DWARF format. This is the size of the operand of DW_OP_call_ref and + /// of the DIE reference operand of DW_OP_implicit_pointer. + virtual uint8_t GetDWARFOffsetByteSize() const = 0; + + virtual llvm::Expected> + GetDIEBitSizeAndSign(uint64_t relative_die_offset) const = 0; + + /// Return the DW_AT_location expression of the DIE referenced by a + /// DW_OP_call2, DW_OP_call4, DW_OP_call_ref or DW_OP_implicit_pointer + /// operation, together with the delegate of the unit that contains the + /// expression (which may not be this unit when the offset is not unit + /// relative). + /// + /// \param[in] die_offset + /// The offset of the referenced DIE. If \a unit_relative is true, + /// the offset is relative to the start of this unit + /// (DW_OP_call2/DW_OP_call4), otherwise it is an offset in the + /// .debug_info section (DW_OP_call_ref, DW_OP_implicit_pointer). + /// + /// \return + /// The location expression data and the delegate to evaluate it + /// with. An empty (zero length) DataExtractor is returned when the + /// referenced DIE exists but has no DW_AT_location attribute; the + /// caller decides what that means (for the DW_OP_call operations it + /// means the call has no effect; for DW_OP_implicit_pointer it means + /// the pointed-at value is unavailable). An error is returned if the + /// DIE cannot be resolved or its DW_AT_location is not an expression + /// block (i.e. it is a location list, which is not currently + /// supported here). + virtual llvm::Expected< + std::pair> + GetDIELocationExpression(uint64_t die_offset, bool unit_relative) const = 0; + + /// Return the value of the DW_AT_const_value attribute of the DIE at + /// \a die_offset in the .debug_info section. This is used when + /// dereferencing a DW_OP_implicit_pointer whose referenced DIE describes + /// the pointed-at value with a constant rather than a location. Block and + /// string forms are returned as host byte buffers, integer forms as + /// scalars. Returns std::nullopt when the DIE exists but has no + /// DW_AT_const_value attribute, and an error when the DIE cannot be + /// resolved. + virtual llvm::Expected> + GetDIEConstValue(uint64_t die_offset) const = 0; + + virtual dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const = 0; + virtual lldb::offset_t + GetVendorDWARFOpcodeSize(const DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op) const = 0; + virtual bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, + lldb::offset_t &offset, + std::vector &stack) const = 0; + + DWARFExpressionDelegate(const DWARFExpressionDelegate &) = delete; + DWARFExpressionDelegate &operator=(const DWARFExpressionDelegate &) = delete; +}; + /// \class DWARFExpression DWARFExpression.h /// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location /// expression and interprets it. @@ -38,59 +115,9 @@ class DWARFExpression { public: using Stack = std::vector; - class Delegate { - public: - Delegate() = default; - virtual ~Delegate() = default; - - virtual uint16_t GetVersion() const = 0; - virtual dw_addr_t GetBaseAddress() const = 0; - virtual uint8_t GetAddressByteSize() const = 0; - - /// Return the size in bytes of an offset in the DWARF format of this - /// unit: 4 bytes for the 32-bit DWARF format, 8 bytes for the 64-bit - /// DWARF format. This is the size of the operand of DW_OP_call_ref. - virtual uint8_t GetDWARFOffsetByteSize() const = 0; - - virtual llvm::Expected> - GetDIEBitSizeAndSign(uint64_t relative_die_offset) const = 0; - - /// Return the DW_AT_location expression of the DIE referenced by a - /// DW_OP_call2, DW_OP_call4 or DW_OP_call_ref operation, together with - /// the delegate of the unit that contains the expression (which may not - /// be this unit for DW_OP_call_ref). - /// - /// \param[in] die_offset - /// The offset of the referenced DIE. If \a unit_relative is true, - /// the offset is relative to the start of this unit - /// (DW_OP_call2/DW_OP_call4), otherwise it is an offset in the - /// .debug_info section (DW_OP_call_ref). - /// - /// \return - /// The location expression data and the delegate to evaluate it - /// with. An empty (zero length) DataExtractor is returned when the - /// referenced DIE has no DW_AT_location attribute; per the DWARF - /// specification the call operation then has no effect. An error is - /// returned if the DIE cannot be resolved or its DW_AT_location is - /// not an expression block (i.e. it is a location list, which is not - /// currently supported here). - virtual llvm::Expected> - GetDIELocationExpression(uint64_t die_offset, - bool unit_relative) const = 0; - - virtual dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const = 0; - virtual lldb::offset_t - GetVendorDWARFOpcodeSize(const DataExtractor &data, - const lldb::offset_t data_offset, - const uint8_t op) const = 0; - virtual bool ParseVendorDWARFOpcode(uint8_t op, - const DataExtractor &opcodes, - lldb::offset_t &offset, - Stack &stack) const = 0; - - Delegate(const Delegate &) = delete; - Delegate &operator=(const Delegate &) = delete; - }; + /// Compatibility alias; the delegate predates its hoisting to a top-level + /// class and is widely referred to as DWARFExpression::Delegate. + using Delegate = DWARFExpressionDelegate; DWARFExpression(); @@ -185,6 +212,30 @@ class DWARFExpression { const Delegate *dwarf_cu, const lldb::RegisterKind reg_set, const Value *initial_value_ptr, const Value *object_address_ptr); + /// Materialize the value an implicit pointer points at. + /// + /// \a implicit_pointer must be a Value of type + /// Value::ValueType::ImplicitPointer, i.e. the result of evaluating a + /// DWARF expression that ends in DW_OP_implicit_pointer: a pointer that + /// does not exist in the process being debugged, but whose pointed-at + /// value is described by another DIE. This function evaluates the + /// DW_AT_location of that DIE in the given context and applies the + /// implicit pointer's byte offset, yielding the pointed-at value. The + /// result can be any kind of Value: a load address (the pointee does + /// exist in the process's memory), a host address or scalar (the pointee + /// only exists in the debugger), or another implicit pointer (the pointee + /// is itself an eliminated pointer); in the latter cases the value lives + /// in LLDB's own address space, never the process's. + /// + /// Note that failure is always reported as an error: a pointee that is + /// unavailable (e.g. the referenced DIE has no DW_AT_location) is never + /// conflated with a pointee that evaluates to the value zero. + static llvm::Expected + DereferenceImplicitPointer(const Value &implicit_pointer, + ExecutionContext *exe_ctx, + RegisterContext *reg_ctx, + lldb::ModuleSP module_sp); + bool GetExpressionData(DataExtractor &data) const { data = m_data; return data.GetByteSize() > 0; diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index c91b3f852f986..567932898ed9d 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -55,7 +55,9 @@ Value::Value(const void *bytes, int len) Value::Value(const Value &v) : m_value(v.m_value), m_compiler_type(v.m_compiler_type), m_context(v.m_context), m_value_type(v.m_value_type), - m_context_type(v.m_context_type), m_data_buffer() { + m_context_type(v.m_context_type), m_data_buffer(), + m_implicit_pointer(v.m_implicit_pointer), + m_implicit_pointer_pieces(v.m_implicit_pointer_pieces) { const uintptr_t rhs_value = (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS); if ((rhs_value != 0) && @@ -74,6 +76,8 @@ Value &Value::operator=(const Value &rhs) { m_context = rhs.m_context; m_value_type = rhs.m_value_type; m_context_type = rhs.m_context_type; + m_implicit_pointer = rhs.m_implicit_pointer; + m_implicit_pointer_pieces = rhs.m_implicit_pointer_pieces; const uintptr_t rhs_value = (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS); if ((rhs_value != 0) && @@ -110,10 +114,24 @@ void Value::Dump(Stream *strm) { Value::ValueType Value::GetValueType() const { return m_value_type; } +void Value::SetImplicitPointer(const DWARFExpressionDelegate *delegate, + uint64_t die_offset, int64_t byte_offset) { + // Deliberately leave the scalar cleared: an implicit pointer has no + // numeric value, and consumers that ask for one without checking the value + // type should receive their fail value, not something that could be + // mistaken for a real pointer (such as zero). + m_value.Clear(); + m_data_buffer.Clear(); + m_implicit_pointer = ImplicitPointerInfo{delegate, die_offset, byte_offset}; + m_implicit_pointer_pieces.clear(); + m_value_type = ValueType::ImplicitPointer; +} + AddressType Value::GetValueAddressType() const { switch (m_value_type) { case ValueType::Invalid: case ValueType::Scalar: + case ValueType::ImplicitPointer: break; case ValueType::LoadAddress: return eAddressTypeLoad; @@ -159,6 +177,9 @@ size_t Value::AppendDataToHostBuffer(const Value &rhs) { Status error; switch (rhs.GetValueType()) { case ValueType::Invalid: + case ValueType::ImplicitPointer: + // An implicit pointer has no byte representation; do not append + // anything (in particular, not zeros). return 0; case ValueType::Scalar: { const size_t scalar_size = rhs.m_value.GetByteSize(); @@ -300,6 +321,7 @@ lldb::Format Value::GetValueDefaultFormat() { bool Value::GetData(DataExtractor &data) { switch (m_value_type) { case ValueType::Invalid: + case ValueType::ImplicitPointer: return false; case ValueType::Scalar: if (m_value.GetData(data)) @@ -340,6 +362,13 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, case ValueType::Invalid: error = Status::FromErrorString("invalid value"); break; + case ValueType::ImplicitPointer: + // The pointer itself has no memory representation; only the value it + // points at can be materialized, via + // DWARFExpression::DereferenceImplicitPointer(). + error = Status::FromErrorString( + "value is an implicit pointer whose numeric value is not available"); + break; case ValueType::Scalar: { data.SetByteOrder(endian::InlHostByteOrder()); if (ast_type.IsValid()) @@ -593,6 +622,7 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx, Module *module) { switch (m_value_type) { case ValueType::Invalid: case ValueType::Scalar: // raw scalar value + case ValueType::ImplicitPointer: // no numeric value to resolve break; case ValueType::FileAddress: @@ -641,6 +671,8 @@ void Value::Clear() { m_context = nullptr; m_context_type = ContextType::Invalid; m_data_buffer.Clear(); + m_implicit_pointer.reset(); + m_implicit_pointer_pieces.clear(); } const char *Value::GetValueTypeAsCString(ValueType value_type) { @@ -655,6 +687,8 @@ const char *Value::GetValueTypeAsCString(ValueType value_type) { return "load address"; case ValueType::HostAddress: return "host address"; + case ValueType::ImplicitPointer: + return "implicit pointer"; }; llvm_unreachable("enum cases exhausted."); } diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index c0f0bbefc0008..8f680af918e92 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -156,7 +156,6 @@ GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset, case DW_OP_APPLE_uninit: case DW_OP_PGI_omp_thread_num: case DW_OP_hi_user: - case DW_OP_GNU_implicit_pointer: break; case DW_OP_addr: @@ -364,12 +363,20 @@ GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset, return offset - data_offset; } - case DW_OP_implicit_pointer: // 0xa0 4-byte (or 8-byte for DWARF 64) constant - // + LEB128 + case DW_OP_implicit_pointer: // 0xa0 DWARF offset sized DIE offset + // + SLEB128 (DWARF5) + case DW_OP_GNU_implicit_pointer: // 0xf2 GNU extension equivalent { data.Skip_LEB128(&offset); - return (dwarf_cu ? dwarf_cu->GetAddressByteSize() : 4) + offset - - data_offset; + lldb::offset_t ref_size = 4; + if (dwarf_cu) { + ref_size = dwarf_cu->GetDWARFOffsetByteSize(); + // The GNU extension used an address sized reference in pre-DWARF 3 + // units, which had no notion of an offset sized reference. + if (op == DW_OP_GNU_implicit_pointer && dwarf_cu->GetVersion() < 3) + ref_size = dwarf_cu->GetAddressByteSize(); + } + return ref_size + offset - data_offset; } case DW_OP_GNU_entry_value: @@ -921,6 +928,12 @@ static llvm::Error Evaluate_DW_OP_deref(DWARFExpression::Stack &stack, stack.back().GetScalar() = pointer_value; stack.back().ClearContext(); } break; + case Value::ValueType::ImplicitPointer: + // Implicit pointers can only be dereferenced by materializing the + // pointed-at value via its DIE (see + // DWARFExpression::DereferenceImplicitPointer), not by reading memory. + return llvm::createStringError( + "DW_OP_deref of an implicit pointer is not supported"); case Value::ValueType::Invalid: return llvm::createStringError("invalid value type for DW_OP_deref"); } @@ -1222,6 +1235,10 @@ static llvm::Error EvaluateOpcodes( } break; + case Value::ValueType::ImplicitPointer: + return llvm::createStringError( + "DW_OP_deref_size of an implicit pointer is not supported"); + case Value::ValueType::Invalid: return llvm::createStringError("invalid value for DW_OP_deref_size"); @@ -1968,6 +1985,28 @@ static llvm::Error EvaluateOpcodes( piece_byte_size, addr); } break; + case Value::ValueType::ImplicitPointer: { + // The piece is an implicit pointer: it has no actual bytes. + // Append placeholder bytes so that subsequent piece offsets stay + // correct, and record the byte range in the composite's + // implicit-pointer table. The table entry, never the placeholder + // bytes, is the piece's value; consumers must consult the table + // before interpreting any bytes of the composite. + const std::optional &pointee = + curr_piece_source_value.GetImplicitPointer(); + if (!pointee) + return llvm::createStringError( + "implicit pointer piece does not identify its pointee"); + if (curr_piece.ResizeData(piece_byte_size) != piece_byte_size) + return llvm::createStringError( + "failed to resize the piece memory buffer for " + "DW_OP_piece(%" PRIu64 ")", + piece_byte_size); + ::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size); + pieces.AddImplicitPointerPiece(op_piece_offset, piece_byte_size, + *pointee); + } break; + case Value::ValueType::Scalar: { uint32_t bit_size = piece_byte_size * 8; uint32_t bit_offset = 0; @@ -2052,6 +2091,12 @@ static llvm::Error EvaluateOpcodes( "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 ", bit_offset = %" PRIu64 ") from an address value.", piece_bit_size, piece_bit_offset); + + case Value::ValueType::ImplicitPointer: + return llvm::createStringError( + "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 + ", bit_offset = %" PRIu64 ") from an implicit pointer.", + piece_bit_size, piece_bit_offset); } } break; @@ -2080,10 +2125,44 @@ static llvm::Error EvaluateOpcodes( break; } - case DW_OP_implicit_pointer: { + // OPCODE: DW_OP_implicit_pointer (DW_OP_GNU_implicit_pointer is the + // legacy vendor extension it was standardized from) + // OPERANDS: 2 + // A reference to a DIE in the .debug_info section, the size of an + // offset in the DWARF format of the compile unit (4 bytes in the + // 32-bit DWARF format, 8 bytes in the 64-bit DWARF format) + // SLEB128 byte offset into the value of that DIE + // DESCRIPTION: Specifies that the object is a pointer that cannot be + // represented as a real pointer, even though the value it would point to + // can be described: the referenced DIE describes the pointed-at value + // via its DW_AT_location (or DW_AT_const_value) attribute. The resulting + // value carries the DIE reference and byte offset so that the pointed-at + // value can be materialized on demand with + // DWARFExpression::DereferenceImplicitPointer(). The pointer itself has + // no numeric value; in particular it is distinct from a pointer whose + // value is zero. + case DW_OP_implicit_pointer: + case DW_OP_GNU_implicit_pointer: { dwarf4_location_description_kind = Implicit; - return llvm::createStringError("Could not evaluate %s.", - DW_OP_value_to_name(op)); + if (!dwarf_cu) + return llvm::createStringError( + "%s found without a compile unit being specified", + DW_OP_value_to_name(op)); + + // The DIE reference operand has the size of an offset in the DWARF + // format of the compile unit, except for the GNU extension in + // pre-DWARF 3 units, which had no notion of an offset sized + // reference and used an address sized one. + uint32_t ref_byte_size = dwarf_cu->GetDWARFOffsetByteSize(); + if (op == DW_OP_GNU_implicit_pointer && dwarf_cu->GetVersion() < 3) + ref_byte_size = opcodes.GetAddressByteSize(); + const uint64_t die_offset = opcodes.GetMaxU64(&offset, ref_byte_size); + const int64_t byte_offset = opcodes.GetSLEB128(&offset); + + Value result; + result.SetImplicitPointer(dwarf_cu, die_offset, byte_offset); + stack.push_back(result); + break; } // OPCODE: DW_OP_push_object_address @@ -2410,6 +2489,117 @@ llvm::Expected DWARFExpression::Evaluate( return stack.back(); } +llvm::Expected DWARFExpression::DereferenceImplicitPointer( + const Value &implicit_pointer, ExecutionContext *exe_ctx, + RegisterContext *reg_ctx, lldb::ModuleSP module_sp) { + if (implicit_pointer.GetValueType() != Value::ValueType::ImplicitPointer) + return llvm::createStringError( + "cannot dereference a value that is not an implicit pointer"); + const std::optional &info = + implicit_pointer.GetImplicitPointer(); + if (!info || !info->delegate) + return llvm::createStringError( + "implicit pointer does not identify a DWARF unit"); + + auto pointee_loc_or_err = info->delegate->GetDIELocationExpression( + info->die_offset, /*unit_relative=*/false); + if (!pointee_loc_or_err) + return pointee_loc_or_err.takeError(); + const DataExtractor &pointee_opcodes = pointee_loc_or_err->first; + const Delegate *pointee_cu = pointee_loc_or_err->second; + + Value pointee; + if (pointee_opcodes.GetByteSize() != 0) { + llvm::Expected evaluated = + Evaluate(exe_ctx, reg_ctx, module_sp, pointee_opcodes, pointee_cu, + lldb::eRegisterKindDWARF, /*initial_value_ptr=*/nullptr, + /*object_address_ptr=*/nullptr); + if (!evaluated) + return evaluated.takeError(); + pointee = std::move(*evaluated); + } else { + // The DWARF specification allows the referenced DIE to describe the + // pointed-at value with a DW_AT_const_value attribute instead of a + // DW_AT_location. + llvm::Expected> const_value = + info->delegate->GetDIEConstValue(info->die_offset); + if (!const_value) + return const_value.takeError(); + if (!*const_value) + // The pointed-at value is unavailable; report that explicitly so that + // it can never be conflated with a value that happens to be zero. + return llvm::createStringError( + "implicit pointer target DIE at .debug_info offset 0x%" PRIx64 + " has neither DW_AT_location nor DW_AT_const_value; the pointed-at " + "value is unavailable", + info->die_offset); + pointee = std::move(**const_value); + } + + const int64_t byte_offset = info->byte_offset; + switch (pointee.GetValueType()) { + case Value::ValueType::FileAddress: + case Value::ValueType::LoadAddress: + // The pointed-at value exists in the target's memory after all, so the + // result is an ordinary address there. + if (byte_offset != 0) + pointee.GetScalar() += byte_offset; + return pointee; + + case Value::ValueType::HostAddress: { + // The pointed-at value was materialized into a buffer that lives in + // LLDB's own memory, not the target's. Slice off the requested byte + // offset into a fresh value: Value's copy semantics only preserve + // scalars that point at the start of their own buffer, so we must not + // hand out a pointer into the middle of one. + if (byte_offset == 0) + return pointee; + const uint8_t *bytes = pointee.GetBuffer().GetBytes(); + const uint64_t byte_size = pointee.GetBuffer().GetByteSize(); + if (!bytes || byte_offset < 0 || + static_cast(byte_offset) >= byte_size) + return llvm::createStringError( + "implicit pointer byte offset %" PRId64 + " is outside the materialized value (%" PRIu64 " bytes)", + byte_offset, byte_size); + Value sliced(bytes + byte_offset, static_cast(byte_size - byte_offset)); + // Rebase the composite's implicit-pointer table onto the slice. Pieces + // entirely before the slice fall away with their bytes; a piece + // straddling the slice boundary would leave unmarked placeholder bytes + // in the slice, so refuse it. + const uint64_t slice_begin = static_cast(byte_offset); + for (const Value::ImplicitPointerPiece &piece : + pointee.GetImplicitPointerPieces()) { + if (piece.buffer_offset >= slice_begin) + sliced.AddImplicitPointerPiece(piece.buffer_offset - slice_begin, + piece.byte_size, piece.pointee); + else if (piece.buffer_offset + piece.byte_size > slice_begin) + return llvm::createStringError( + "implicit pointer byte offset %" PRId64 + " splits an implicit pointer piece of the pointed-at value", + byte_offset); + } + return sliced; + } + + case Value::ValueType::Scalar: + case Value::ValueType::ImplicitPointer: + // A scalar (e.g. a pointee location ending in DW_OP_stack_value, or an + // integer DW_AT_const_value) or a chained implicit pointer has no + // addressable bytes to offset into. + if (byte_offset != 0) + return llvm::createStringError( + "cannot apply implicit pointer byte offset %" PRId64 " to a %s", + byte_offset, Value::GetValueTypeAsCString(pointee.GetValueType())); + return pointee; + + case Value::ValueType::Invalid: + return llvm::createStringError( + "implicit pointer target evaluated to an invalid value"); + } + llvm_unreachable("all value types handled"); +} + bool DWARFExpression::MatchesOperand( StackFrame &frame, const Instruction::Operand &operand) const { using namespace OperandMatchers; diff --git a/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp b/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp index 780cc77ab9e60..68469e1f73c8a 100644 --- a/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp +++ b/lldb/source/Plugins/Language/OxCaml/OxCamlFormatters.cpp @@ -53,8 +53,12 @@ #include "OxCamlHelpers.h" #include "OxCamlValueFormatters.h" #include "Plugins/TypeSystem/OxCaml/TypeSystemOxCaml.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Reference.h" @@ -87,9 +91,19 @@ static uint64_t MakeLowBitMask(uint64_t bit_size) { return (1ULL << bit_size) - 1ULL; } +// Most formatters receive, alongside [data], the implicit-pointer piece +// table of the composite the bytes came from (empty for values read from +// the target's memory). Ranges listed there contain placeholder bytes, not +// data: their value is the table entry. See FormatImplicitPointer. static bool FormatValue(Stream &stream, OxCamlType *type, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address); + std::optional object_address, + llvm::ArrayRef + implicit_pieces = {}); +static bool FormatImplicitPointer(Stream &stream, OxCamlType *type, + const Value &pointer, + const OxCamlFormatContext &context, + unsigned depth = 0); static bool FormatUnboxedBase(Stream &stream, OxCamlUnboxedBaseType *unboxed_type, DataExtractor &data); @@ -103,11 +117,15 @@ static bool FormatPointer(Stream &stream, OxCamlPointerType *ptr_type, static bool FormatTypedef(Stream &stream, OxCamlTypedefType *typedef_type, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address); + std::optional object_address, + llvm::ArrayRef + implicit_pieces = {}); static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address); + std::optional object_address, + llvm::ArrayRef + implicit_pieces = {}); static bool FormatPlaceholder(Stream &stream, OxCamlPlaceholderType *placeholder_type, DataExtractor &data); @@ -124,7 +142,9 @@ static bool FormatVariantPart(Stream &stream, DataExtractor &data, const OxCamlFormatContext &context, std::optional object_address, - bool is_ocaml_variant); + bool is_ocaml_variant, + llvm::ArrayRef + implicit_pieces = {}); // ============================================================================ // Entry Point: OxCamlValue_SummaryProvider @@ -139,13 +159,6 @@ static bool FormatVariantPart(Stream &stream, bool lldb_private::formatters::oxcaml::OxCamlValue_SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { - DataExtractor data; - Status error; - valobj.GetData(data, error); - - ENSURE(error.Success(), stream, "", - "ValueObject data extraction failed: {0}", error.AsCString()); - CompilerType compiler_type = valobj.GetCompilerType(); void *opaque_type = compiler_type.GetOpaqueQualType(); @@ -168,8 +181,28 @@ bool lldb_private::formatters::oxcaml::OxCamlValue_SummaryProvider( "(ptr={0:P})", process_sp.get()); + // The variable may have been optimized away into an implicit pointer + // (DW_OP_implicit_pointer): it then has no bytes of its own, and the + // value it points at must be materialized from the DWARF description of + // the pointee instead. + if (valobj.GetValue().GetValueType() == Value::ValueType::ImplicitPointer) { + OxCamlFormatContext context{process_sp, valobj.GetExecutionContextRef(), + process_sp->GetByteOrder(), + process_sp->GetAddressByteSize(), + valobj.GetModule()}; + return FormatImplicitPointer(stream, type, valobj.GetValue(), context); + } + + DataExtractor data; + Status error; + valobj.GetData(data, error); + + ENSURE(error.Success(), stream, "", + "ValueObject data extraction failed: {0}", error.AsCString()); + OxCamlFormatContext context{process_sp, valobj.GetExecutionContextRef(), - data.GetByteOrder(), data.GetAddressByteSize()}; + data.GetByteOrder(), data.GetAddressByteSize(), + valobj.GetModule()}; // No object address at entry: [data] holds the OCaml value itself // (typically a register-resident tagged pointer). FormatPointer sets the @@ -481,9 +514,117 @@ static bool FormatPointer(Stream &stream, OxCamlPointerType *ptr_type, static bool FormatTypedef(Stream &stream, OxCamlTypedefType *typedef_type, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address) { + std::optional object_address, + llvm::ArrayRef + implicit_pieces) { return FormatValue(stream, typedef_type->GetUnderlyingType(), data, context, - object_address); + object_address, implicit_pieces); +} + +// Format a value whose location is an implicit pointer +// (DW_OP_implicit_pointer): the pointer itself was optimized away and has no +// numeric value, but the object it would point at is described by another +// DIE. Materialize that object and format it as [type]'s pointee. Failures +// surface as markers; an unavailable pointee is never rendered as a null or +// zero pointer. +static bool FormatImplicitPointer(Stream &stream, OxCamlType *type, + const Value &pointer, + const OxCamlFormatContext &context, + unsigned depth) { + // Guard against reference cycles in (malformed) DWARF; each level of the + // chain materializes one pointee. + ENSURE(depth < 32, stream, "", + "Implicit pointer chain exceeds {0} levels, likely a cycle", 32); + + // Resolve typedef chains to find the pointer type whose pointee we will + // format. + OxCamlType *resolved = type; + while (resolved && resolved->GetKind() == OxCamlType::Typedef) + resolved = static_cast(resolved)->GetUnderlyingType(); + ENSURE(resolved, stream, "", + "Implicit pointer value has unresolved type '{0}'", + type ? type->GetDisplayName() : ""); + ENSURE(resolved->GetKind() == OxCamlType::Pointer, stream, + "", + "Implicit pointer value has non-pointer type '{0}'", + resolved->GetDisplayName()); + auto *ptr_type = static_cast(resolved); + OxCamlType *pointed_to = ptr_type->GetPointedToType(); + ENSURE(pointed_to, stream, "", + "Implicit pointer type '{0}' lacks a resolved target type", + ptr_type->GetDisplayName()); + + ExecutionContext exe_ctx(context.exe_ctx_ref); + RegisterContext *reg_ctx = nullptr; + if (StackFrame *frame = exe_ctx.GetFramePtr()) + reg_ctx = frame->GetRegisterContext().get(); + + llvm::Expected pointee = DWARFExpression::DereferenceImplicitPointer( + pointer, &exe_ctx, reg_ctx, context.module_sp); + if (!pointee) { + OXCAML_EMIT_MARKER(stream, "", + "Failed to materialize the value of an optimized-out " + "pointer of type '{0}': {1}", + ptr_type->GetDisplayName(), + llvm::toString(pointee.takeError())); + return true; + } + + switch (pointee->GetValueType()) { + case Value::ValueType::LoadAddress: { + // The pointed-at object exists in the target's memory after all: + // re-enter the ordinary pointer-chasing path with its load address. + const uint64_t addr = pointee->GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + uint8_t addr_bytes[sizeof(uint64_t)]; + for (unsigned i = 0; i < sizeof(addr_bytes); ++i) + addr_bytes[i] = (context.byte_order == lldb::eByteOrderBig) + ? uint8_t(addr >> (8 * (sizeof(addr_bytes) - 1 - i))) + : uint8_t(addr >> (8 * i)); + DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), context.byte_order, + context.address_byte_size); + return FormatPointer(stream, ptr_type, addr_data, context); + } + + case Value::ValueType::HostAddress: { + // The pointed-at object exists only in the debugger: format the block + // from the materialized buffer, together with its implicit-pointer + // table (fields of the block may themselves be optimized-out + // pointers). Member locations that are constant object-relative + // offsets resolve against the buffer; there is no target-side object + // address. + DataExtractor pointee_data(pointee->GetBuffer().GetBytes(), + pointee->GetBuffer().GetByteSize(), + context.byte_order, context.address_byte_size); + return FormatValue(stream, pointed_to, pointee_data, context, + /*object_address=*/std::nullopt, + pointee->GetImplicitPointerPieces()); + } + + case Value::ValueType::Scalar: { + // The pointed-at object was materialized as a single word (e.g. its + // location is a register or a DW_AT_const_value integer). + uint64_t word = pointee->GetScalar().ULongLong(); + DataExtractor word_data(&word, sizeof(word), context.byte_order, + context.address_byte_size); + return FormatValue(stream, pointed_to, word_data, context, + /*object_address=*/std::nullopt); + } + + case Value::ValueType::ImplicitPointer: + // The pointed-at object is itself an optimized-out pointer. + return FormatImplicitPointer(stream, pointed_to, *pointee, context, + depth + 1); + + case Value::ValueType::FileAddress: + case Value::ValueType::Invalid: + break; + } + OXCAML_EMIT_MARKER(stream, "", + "Unsupported materialized value kind {0} for an " + "optimized-out pointer of type '{1}'", + static_cast(pointee->GetValueType()), + ptr_type->GetDisplayName()); + return true; } // Format an OCaml exception value @@ -801,15 +942,46 @@ ResolveMemberLocation(Stream &stream, const OxCamlMember &member, // Read [byte_size] bytes for a member or discriminator into [out_buffer] // according to a resolved location. -static bool -ReadResolvedMemberBytes(Stream &stream, const OxCamlMember &member, - uint64_t byte_size, - const ResolvedMemberLocation &resolved, - DataExtractor &data, const OxCamlFormatContext &context, - llvm::SmallVectorImpl &out_buffer) { +// +// [implicit_pieces] is the implicit-pointer table of [data]'s composite (if +// any): ranges listed there contain placeholder bytes rather than data, so +// reads overlapping them are refused, except that pieces falling entirely +// inside the read are rebased onto the copied bytes and appended to +// [contained_pieces] when the caller provides it (the caller then interprets +// them against the copy). +static bool ReadResolvedMemberBytes( + Stream &stream, const OxCamlMember &member, uint64_t byte_size, + const ResolvedMemberLocation &resolved, DataExtractor &data, + const OxCamlFormatContext &context, + llvm::SmallVectorImpl &out_buffer, + llvm::ArrayRef implicit_pieces = {}, + llvm::SmallVectorImpl *contained_pieces = + nullptr) { out_buffer.resize(byte_size); if (resolved.source == ResolvedMemberLocation::Source::BufferOffset) { uint64_t offset = resolved.buffer_offset; + for (const Value::ImplicitPointerPiece &piece : implicit_pieces) { + const bool overlaps = piece.buffer_offset < offset + byte_size && + offset < piece.buffer_offset + piece.byte_size; + if (!overlaps) + continue; + const bool contained = + piece.buffer_offset >= offset && + piece.buffer_offset + piece.byte_size <= offset + byte_size; + if (contained && contained_pieces) { + contained_pieces->push_back( + {piece.buffer_offset - offset, piece.byte_size, piece.pointee}); + continue; + } + // Refuse rather than reading the placeholder bytes: an optimized-out + // pointer's value must never be conflated with bytes such as zeros. + OXCAML_EMIT_MARKER( + stream, "", + "Member '{0}' overlaps an optimized-out (implicit pointer) range " + "of its parent that cannot be read as bytes", + member.name.value_or("")); + return false; + } if (offset + byte_size > data.GetByteSize()) { OXCAML_EMIT_MARKER( stream, "", @@ -846,7 +1018,9 @@ ReadResolvedMemberBytes(Stream &stream, const OxCamlMember &member, static bool FormatMember(Stream &stream, const OxCamlMember &member, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address) { + std::optional object_address, + llvm::ArrayRef + implicit_pieces = {}) { auto resolved = ResolveMemberLocation(stream, member, data, context, object_address); if (!resolved.has_value()) @@ -881,7 +1055,7 @@ static bool FormatMember(Stream &stream, const OxCamlMember &member, llvm::SmallVector word; if (!ReadResolvedMemberBytes(stream, member, sizeof(uint64_t), *resolved, - data, context, word)) + data, context, word, implicit_pieces)) return true; DataExtractor word_data(word.data(), word.size(), data.GetByteOrder(), @@ -914,15 +1088,34 @@ static bool FormatMember(Stream &stream, const OxCamlMember &member, } uint64_t member_byte_size = *member_byte_size_expected; + // The member's bytes may not exist at all: if its range is exactly an + // implicit-pointer piece of the parent's composite, the member is an + // optimized-out pointer whose pointee is described by another DIE. + if (resolved->source == ResolvedMemberLocation::Source::BufferOffset) { + for (const Value::ImplicitPointerPiece &piece : implicit_pieces) { + if (piece.buffer_offset == resolved->buffer_offset && + piece.byte_size == member_byte_size) { + Value pointer; + pointer.SetImplicitPointer(piece.pointee.delegate, + piece.pointee.die_offset, + piece.pointee.byte_offset); + return FormatImplicitPointer(stream, member.GetType(), pointer, + context); + } + } + } + llvm::SmallVector buffer; + llvm::SmallVector member_pieces; if (!ReadResolvedMemberBytes(stream, member, member_byte_size, *resolved, - data, context, buffer)) + data, context, buffer, implicit_pieces, + &member_pieces)) return true; DataExtractor member_data(buffer.data(), member_byte_size, data.GetByteOrder(), data.GetAddressByteSize()); return FormatValue(stream, member.GetType(), member_data, context, - resolved->member_object_address); + resolved->member_object_address, member_pieces); } // Returns true if both members have constant data_member_location 0. @@ -935,7 +1128,9 @@ static bool AreBothMembersAtConstantOffsetZero(const OxCamlMember &a, static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address) { + std::optional object_address, + llvm::ArrayRef + implicit_pieces) { const auto &members = struct_type->GetMembers(); const auto &variant_parts = struct_type->GetVariantParts(); @@ -943,7 +1138,7 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, // variant part is rendered as the variant content alone (no braces). if (members.empty() && variant_parts.size() == 1) { return FormatVariantPart(stream, variant_parts[0], data, context, - object_address, true); + object_address, true, implicit_pieces); } // OCaml exception: a union-style struct with "exn" and "raw" members both @@ -955,6 +1150,12 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, const std::string &name1 = members[1].name.value(); if ((name0 == "exn" && name1 == "raw") || (name0 == "raw" && name1 == "exn")) { + // FormatException reads raw bytes itself and cannot interpret + // optimized-out (implicit pointer) ranges. + ENSURE(implicit_pieces.empty(), stream, "", + "Exception value contains optimized-out (implicit pointer) " + "ranges{0}", + ""); return FormatException(stream, data, context); } } @@ -976,7 +1177,8 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, stream.Printf("%s = ", members[i].name.value().c_str()); } - FormatMember(stream, members[i], data, context, object_address); + FormatMember(stream, members[i], data, context, object_address, + implicit_pieces); has_content = true; } @@ -985,7 +1187,7 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, stream.Printf("%s", separator); FormatVariantPart(stream, variant_parts[i], data, context, object_address, - false); + false, implicit_pieces); has_content = true; } @@ -996,7 +1198,22 @@ static bool FormatStructure(Stream &stream, OxCamlStructureType *struct_type, static bool FormatValue(Stream &stream, OxCamlType *type, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address) { + std::optional object_address, + llvm::ArrayRef + implicit_pieces) { + // Only the aggregate formatters below know how to interpret buffers that + // contain optimized-out (implicit pointer) ranges; refuse everywhere else + // rather than reading their placeholder bytes. + if (!implicit_pieces.empty() && + (!type || (type->GetKind() != OxCamlType::Typedef && + type->GetKind() != OxCamlType::Structure))) { + OXCAML_EMIT_MARKER(stream, "", + "Value of type '{0}' contains optimized-out (implicit " + "pointer) ranges, which this formatter cannot render", + type ? type->GetDisplayName() : ""); + return true; + } + if (!type) { Log *log = GetLog(OxCamlLog::Formatting); LLDB_LOG( @@ -1019,10 +1236,10 @@ static bool FormatValue(Stream &stream, OxCamlType *type, DataExtractor &data, context); case OxCamlType::Typedef: return FormatTypedef(stream, static_cast(type), data, - context, object_address); + context, object_address, implicit_pieces); case OxCamlType::Structure: return FormatStructure(stream, static_cast(type), - data, context, object_address); + data, context, object_address, implicit_pieces); case OxCamlType::Array: return FormatArray(stream, static_cast(type), data, context, object_address); @@ -1038,7 +1255,9 @@ static bool FormatValue(Stream &stream, OxCamlType *type, DataExtractor &data, static std::optional ReadDiscriminatorValue(Stream &stream, const OxCamlVariantPart &variant_part, DataExtractor &data, const OxCamlFormatContext &context, - std::optional object_address) { + std::optional object_address, + llvm::ArrayRef + implicit_pieces = {}) { const auto &discriminator = variant_part.GetDiscriminator(); uint64_t discriminator_byte_size = discriminator.GetType()->GetByteSize(); // The discriminator value is later returned as a uint64_t, so wider @@ -1054,7 +1273,8 @@ ReadDiscriminatorValue(Stream &stream, const OxCamlVariantPart &variant_part, llvm::SmallVector buffer; if (!ReadResolvedMemberBytes(stream, discriminator, discriminator_byte_size, - *resolved, data, context, buffer)) + *resolved, data, context, buffer, + implicit_pieces)) return std::nullopt; DataExtractor discr_data(buffer.data(), buffer.size(), data.GetByteOrder(), @@ -1112,7 +1332,9 @@ static bool FormatVariantPartGeneric(Stream &stream, const OxCamlFormatContext &context, std::optional object_address, uint64_t discr_value, - const std::vector &members) { + const std::vector &members, + llvm::ArrayRef + implicit_pieces) { std::string discr_name = "Unknown"; const auto &discriminator = variant_part.GetDiscriminator(); if (discriminator.GetType()->GetKind() == OxCamlType::Enum) { @@ -1133,7 +1355,8 @@ static bool FormatVariantPartGeneric(Stream &stream, stream.Printf("; "); if (members[i].name.has_value()) stream.Printf("%s = ", members[i].name.value().c_str()); - FormatMember(stream, members[i], data, context, object_address); + FormatMember(stream, members[i], data, context, object_address, + implicit_pieces); } stream.Printf("]"); } @@ -1147,7 +1370,9 @@ static bool FormatVariantPartOxCaml(Stream &stream, const OxCamlFormatContext &context, std::optional object_address, uint64_t discr_value, - const std::vector &members) { + const std::vector &members, + llvm::ArrayRef + implicit_pieces) { const auto &discriminator = variant_part.GetDiscriminator(); ENSURE(discriminator.GetType()->GetKind() == OxCamlType::Enum, stream, @@ -1224,7 +1449,8 @@ static bool FormatVariantPartOxCaml(Stream &stream, } } - FormatMember(stream, members[i], data, context, object_address); + FormatMember(stream, members[i], data, context, object_address, + implicit_pieces); } stream.Printf("%s", close_delim); @@ -1240,9 +1466,11 @@ static bool FormatVariantPart(Stream &stream, DataExtractor &data, const OxCamlFormatContext &context, std::optional object_address, - bool is_ocaml_variant) { - auto discr_value_opt = ReadDiscriminatorValue(stream, variant_part, data, - context, object_address); + bool is_ocaml_variant, + llvm::ArrayRef + implicit_pieces) { + auto discr_value_opt = ReadDiscriminatorValue( + stream, variant_part, data, context, object_address, implicit_pieces); ENSURE(discr_value_opt.has_value(), stream, "", "Discriminator value unreadable (variant={0})", variant_part.GetDiscriminator().name); @@ -1257,15 +1485,18 @@ static bool FormatVariantPart(Stream &stream, const auto &members = (*active_variant)->members; if (variant_part.HasArtificialDiscriminator() && members.size() == 1) { - FormatMember(stream, members[0], data, context, object_address); + FormatMember(stream, members[0], data, context, object_address, + implicit_pieces); return true; } if (is_ocaml_variant) { return FormatVariantPartOxCaml(stream, variant_part, data, context, - object_address, discr_value, members); + object_address, discr_value, members, + implicit_pieces); } else { return FormatVariantPartGeneric(stream, variant_part, data, context, - object_address, discr_value, members); + object_address, discr_value, members, + implicit_pieces); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 9d388f06ca16b..88321488335b0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -9,6 +9,7 @@ #include "DWARFUnit.h" #include "lldb/Core/Module.h" +#include "lldb/Core/Value.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/StreamString.h" @@ -783,6 +784,45 @@ DWARFUnit::GetDIELocationExpression(uint64_t die_offset, static_cast(expr_unit)}; } +llvm::Expected> +DWARFUnit::GetDIEConstValue(uint64_t die_offset) const { + // FIXME: the constness has annoying ripple effects. + DWARFUnit *self = const_cast(this); + DWARFDIE die = self->GetSymbolFileDWARF().DebugInfo().GetDIE( + DIERef::Section::DebugInfo, die_offset); + if (!die) + return llvm::createStringError( + "cannot resolve DIE at .debug_info offset 0x%" PRIx64, die_offset); + + DWARFFormValue form_value; + if (!die.GetDIE()->GetAttributeValue(die.GetCU(), DW_AT_const_value, + form_value, + /*end_attr_offset_ptr=*/nullptr, + /*check_elaborating_dies=*/true)) + return std::nullopt; + + if (DWARFFormValue::IsBlockForm(form_value.Form())) { + const uint8_t *block_data = form_value.BlockData(); + const uint64_t block_length = form_value.Unsigned(); + if (!block_data || block_length == 0) + return llvm::createStringError( + "DIE at .debug_info offset 0x%" PRIx64 + " has an empty DW_AT_const_value block", + die_offset); + return Value(block_data, static_cast(block_length)); + } + + if (const char *str = form_value.AsCString()) + return Value(str, strlen(str) + 1); + + // An integer constant. Only DW_FORM_sdata carries a signedness of its + // own; for the fixed-size data forms signedness would come from the + // type, which is not known here. + if (form_value.Form() == DW_FORM_sdata) + return Value(Scalar(form_value.Signed())); + return Value(Scalar(form_value.Unsigned())); +} + lldb::offset_t DWARFUnit::GetVendorDWARFOpcodeSize(const DataExtractor &data, const lldb::offset_t data_offset, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 8d6e554178ea7..9b319651c58ee 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -168,6 +168,9 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID { GetDIELocationExpression(uint64_t die_offset, bool unit_relative) const override; + llvm::Expected> + GetDIEConstValue(uint64_t die_offset) const override; + lldb::offset_t GetVendorDWARFOpcodeSize(const DataExtractor &data, const lldb::offset_t data_offset, const uint8_t op) const override; diff --git a/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h index 4998396e20974..8296ddd39e47e 100644 --- a/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h +++ b/lldb/source/Plugins/TypeSystem/OxCaml/OxCamlDynamicLayoutValue.h @@ -46,6 +46,9 @@ struct OxCamlFormatContext { ExecutionContextRef exe_ctx_ref; lldb::ByteOrder byte_order; uint32_t address_byte_size; + /// The module the value's debug info lives in; needed to evaluate the + /// DWARF descriptions of optimized-out values (implicit pointers). + lldb::ModuleSP module_sp; }; /// A layout fact that may be a constant or a DWARF expression. diff --git a/lldb/source/Target/ABI.cpp b/lldb/source/Target/ABI.cpp index b86fef6bf03e8..7d5a1b4b0cf51 100644 --- a/lldb/source/Target/ABI.cpp +++ b/lldb/source/Target/ABI.cpp @@ -125,6 +125,7 @@ ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type, return {}; case Value::ValueType::HostAddress: case Value::ValueType::FileAddress: + case Value::ValueType::ImplicitPointer: // we odon't do anything with these for now break; case Value::ValueType::Scalar: diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp index a6fb3fad65251..3fa4b90d813ff 100644 --- a/lldb/source/ValueObject/ValueObject.cpp +++ b/lldb/source/ValueObject/ValueObject.cpp @@ -311,6 +311,12 @@ const char *ValueObject::GetLocationAsCStringImpl(const Value &value, m_location_str = "scalar"; break; + case Value::ValueType::ImplicitPointer: + // The pointer was optimized away; it has no numeric value (which is + // distinct from having the value zero). + m_location_str = "implicit pointer"; + break; + case Value::ValueType::LoadAddress: case Value::ValueType::FileAddress: case Value::ValueType::HostAddress: { @@ -801,6 +807,10 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) { case Value::ValueType::Invalid: error = Status::FromErrorString("invalid location"); return false; + case Value::ValueType::ImplicitPointer: + error = Status::FromErrorString( + "cannot modify the value of an implicit pointer"); + return false; case Value::ValueType::Scalar: { Status set_error = m_value.GetScalar().SetValueFromData(data, encoding, byte_size); @@ -1607,6 +1617,7 @@ ValueObject::GetAddressOf(bool scalar_is_load_address) { switch (m_value.GetValueType()) { case Value::ValueType::Invalid: + case Value::ValueType::ImplicitPointer: return {}; case Value::ValueType::Scalar: if (scalar_is_load_address) { @@ -1632,6 +1643,11 @@ ValueObject::AddrAndType ValueObject::GetPointerValue() { switch (m_value.GetValueType()) { case Value::ValueType::Invalid: return {}; + case Value::ValueType::ImplicitPointer: + // The pointer was optimized away and has no numeric value. Returning + // the invalid address (and not zero) keeps this case distinct from a + // pointer whose value is a null pointer. + return {}; case Value::ValueType::Scalar: return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS), GetAddressTypeOfChildren()}; @@ -1728,6 +1744,10 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) { case Value::ValueType::Invalid: error = Status::FromErrorString("invalid location"); return false; + case Value::ValueType::ImplicitPointer: + error = Status::FromErrorString( + "cannot modify the value of an implicit pointer"); + return false; case Value::ValueType::FileAddress: case Value::ValueType::Scalar: break; diff --git a/lldb/source/ValueObject/ValueObjectChild.cpp b/lldb/source/ValueObject/ValueObjectChild.cpp index e29634c2f3322..96fade253e25c 100644 --- a/lldb/source/ValueObject/ValueObjectChild.cpp +++ b/lldb/source/ValueObject/ValueObjectChild.cpp @@ -145,6 +145,10 @@ bool ValueObjectChild::UpdateValue() { switch (m_value.GetValueType()) { case Value::ValueType::Invalid: break; + case Value::ValueType::ImplicitPointer: + m_error = Status::FromErrorString( + "parent value is an implicit pointer with no child storage"); + break; case Value::ValueType::LoadAddress: case Value::ValueType::FileAddress: case Value::ValueType::HostAddress: { diff --git a/lldb/source/ValueObject/ValueObjectMemory.cpp b/lldb/source/ValueObject/ValueObjectMemory.cpp index 3d8d80c6ec480..9ff3356e0ad52 100644 --- a/lldb/source/ValueObject/ValueObjectMemory.cpp +++ b/lldb/source/ValueObject/ValueObjectMemory.cpp @@ -179,6 +179,10 @@ bool ValueObjectMemory::UpdateValue() { case Value::ValueType::Invalid: m_error = Status::FromErrorString("Invalid value"); return false; + case Value::ValueType::ImplicitPointer: + // Values read from the target's memory can never be implicit pointers. + m_error = Status::FromErrorString("unexpected implicit pointer value"); + return false; case Value::ValueType::Scalar: // The variable value is in the Scalar value inside the m_value. We can // point our m_data right to it. diff --git a/lldb/source/ValueObject/ValueObjectVariable.cpp b/lldb/source/ValueObject/ValueObjectVariable.cpp index 12a84f9f2ed74..599c133874342 100644 --- a/lldb/source/ValueObject/ValueObjectVariable.cpp +++ b/lldb/source/ValueObject/ValueObjectVariable.cpp @@ -201,6 +201,15 @@ bool ValueObjectVariable::UpdateValue() { case Value::ValueType::Invalid: m_error = Status::FromErrorString("invalid value"); break; + case Value::ValueType::ImplicitPointer: + // The variable is a pointer that was optimized away, but the value + // it would point at is described by another DIE (the m_value + // carries that reference). The pointer itself has no bytes to read; + // note that its value being unavailable is distinct from it being + // a null pointer. Consumers such as language formatters can + // materialize the pointed-at value with + // DWARFExpression::DereferenceImplicitPointer(). + break; case Value::ValueType::Scalar: // The variable value is in the Scalar value inside the m_value. We can // point our m_data right to it. @@ -262,6 +271,7 @@ void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) { switch (value_type) { case Value::ValueType::Invalid: + case Value::ValueType::ImplicitPointer: break; case Value::ValueType::FileAddress: // If this type is a pointer, then its children will be considered load diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index 2b1eff5fcad1a..4a3a60d5e24eb 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -489,6 +489,259 @@ TEST(DWARFExpression, DW_OP_call) { llvm::Failed()); } +TEST(DWARFExpression, DW_OP_implicit_pointer) { + // A compile unit containing (offsets are relative to the start of + // .debug_info, which coincides with unit-relative offsets here): + // - 0x0e: variable A whose location is the scalar 0x2211 + // (DW_OP_const2u, DW_OP_stack_value) + // - 0x14: variable B whose location is the four implicit bytes + // aa bb cc dd (DW_OP_implicit_value) + // - 0x1c: variable C without DW_AT_location or DW_AT_const_value + // - 0x1e: variable D whose location is an implicit pointer to B + // - 0x26: variable E whose location is the scalar 0 + // (DW_OP_lit0, DW_OP_stack_value) + // - 0x2a: variable F whose value is the integer constant 42 + // (DW_AT_const_value) + // - 0x2c: variable G whose value is the constant bytes 10 20 + // (DW_AT_const_value block) + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_386 +DWARF: + debug_abbrev: + - Table: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Code: 0x00000002 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_exprloc + - Code: 0x00000003 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_const_value + Form: DW_FORM_data1 + - Code: 0x00000004 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Code: 0x00000005 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_const_value + Form: DW_FORM_block1 + debug_info: + - Version: 4 + AddrSize: 8 + AbbrevTableID: 0 + AbbrOffset: 0x0 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x000000000000000C + # 0x0e: A: DW_AT_location = DW_OP_const2u(0x2211), DW_OP_stack_value + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0x0a, 0x11, 0x22, 0x9f ] + # 0x14: B: DW_AT_location = DW_OP_implicit_value(aa bb cc dd) + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0x9e, 0x04, 0xaa, 0xbb, 0xcc, 0xdd ] + # 0x1c: C: neither DW_AT_location nor DW_AT_const_value. + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000000 + # 0x1e: D: DW_AT_location = DW_OP_implicit_pointer(0x14, 0) + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0xa0, 0x14, 0x00, 0x00, 0x00, 0x00 ] + # 0x26: E: DW_AT_location = DW_OP_lit0, DW_OP_stack_value + - AbbrCode: 0x00000002 + Values: + - BlockData: [ 0x30, 0x9f ] + # 0x2a: F: DW_AT_const_value = 42 + - AbbrCode: 0x00000003 + Values: + - Value: 0x000000000000002A + # 0x2c: G: DW_AT_const_value = block(10 20) + - AbbrCode: 0x00000005 + Values: + - BlockData: [ 0x10, 0x20 ] + - AbbrCode: 0x00000000 +)"; + + DWARFExpressionTester t(yamldata, /*cu_index=*/0); + ASSERT_TRUE((bool)t.GetDwarfUnit()); + + auto evaluate = [&](llvm::ArrayRef expr) -> llvm::Expected { + DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle, + /*addr_size*/ 4); + return DWARFExpression::Evaluate( + /*exe_ctx*/ nullptr, /*reg_ctx*/ nullptr, t.GetModule(), extractor, + t.GetDwarfUnit(), lldb::eRegisterKindLLDB, + /*initial_value_ptr*/ nullptr, /*object_address_ptr*/ nullptr); + }; + auto dereference = [&](const Value &v) -> llvm::Expected { + return DWARFExpression::DereferenceImplicitPointer( + v, /*exe_ctx*/ nullptr, /*reg_ctx*/ nullptr, t.GetModule()); + }; + + uint8_t offs_scalar = 0x0e; // A + uint8_t offs_bytes = 0x14; // B + uint8_t offs_no_location = 0x1c; // C + uint8_t offs_chained = 0x1e; // D + uint8_t offs_zero = 0x26; // E + uint8_t offs_const_scalar = 0x2a; // F + uint8_t offs_const_block = 0x2c; // G + + // Evaluating DW_OP_implicit_pointer yields an implicit-pointer value + // carrying the DIE reference and byte offset. The pointer itself has no + // numeric value: asking for one yields the caller's fail value, never + // something that could be mistaken for a real pointer. + llvm::Expected result = + evaluate({DW_OP_implicit_pointer, offs_scalar, 0, 0, 0, 2}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + ASSERT_EQ(result->GetValueType(), Value::ValueType::ImplicitPointer); + ASSERT_TRUE(result->GetImplicitPointer().has_value()); + EXPECT_EQ(result->GetImplicitPointer()->die_offset, (uint64_t)offs_scalar); + EXPECT_EQ(result->GetImplicitPointer()->byte_offset, 2); + EXPECT_EQ(result->GetScalar().ULongLong(LLDB_INVALID_ADDRESS), + LLDB_INVALID_ADDRESS); + + // The legacy GNU extension behaves identically. + result = evaluate({DW_OP_GNU_implicit_pointer, offs_scalar, 0, 0, 0, 0}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + EXPECT_EQ(result->GetValueType(), Value::ValueType::ImplicitPointer); + + // Dereferencing materializes the pointed-at value: here a scalar. + result = evaluate({DW_OP_implicit_pointer, offs_scalar, 0, 0, 0, 0}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + llvm::Expected pointee = dereference(*result); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + EXPECT_EQ(pointee->GetValueType(), Value::ValueType::Scalar); + EXPECT_EQ(pointee->GetScalar().ULongLong(), 0x2211u); + + // ...here a blob of bytes living in the debugger's memory, with the + // implicit pointer's byte offset applied. + result = evaluate({DW_OP_implicit_pointer, offs_bytes, 0, 0, 0, 1}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + pointee = dereference(*result); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + ASSERT_EQ(pointee->GetValueType(), Value::ValueType::HostAddress); + ASSERT_EQ(pointee->GetBuffer().GetByteSize(), 3u); + EXPECT_EQ(pointee->GetBuffer().GetBytes()[0], 0xbb); + EXPECT_EQ(pointee->GetBuffer().GetBytes()[2], 0xdd); + + // A chain of implicit pointers: D's own location is an implicit pointer, + // so dereferencing yields another implicit pointer, which in turn + // dereferences to B's bytes. + result = evaluate({DW_OP_implicit_pointer, offs_chained, 0, 0, 0, 0}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + pointee = dereference(*result); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + ASSERT_EQ(pointee->GetValueType(), Value::ValueType::ImplicitPointer); + ASSERT_TRUE(pointee->GetImplicitPointer().has_value()); + EXPECT_EQ(pointee->GetImplicitPointer()->die_offset, (uint64_t)offs_bytes); + pointee = dereference(*pointee); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + ASSERT_EQ(pointee->GetValueType(), Value::ValueType::HostAddress); + ASSERT_EQ(pointee->GetBuffer().GetByteSize(), 4u); + EXPECT_EQ(pointee->GetBuffer().GetBytes()[0], 0xaa); + + // A pointee that legitimately evaluates to zero is a success... + result = evaluate({DW_OP_implicit_pointer, offs_zero, 0, 0, 0, 0}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + pointee = dereference(*result); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + EXPECT_EQ(pointee->GetValueType(), Value::ValueType::Scalar); + EXPECT_EQ(pointee->GetScalar().ULongLong(/*fail_value=*/1), 0u); + + // The pointed-at value may also be described by a DW_AT_const_value + // attribute instead of a DW_AT_location: an integer constant... + result = evaluate({DW_OP_implicit_pointer, offs_const_scalar, 0, 0, 0, 0}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + pointee = dereference(*result); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + EXPECT_EQ(pointee->GetValueType(), Value::ValueType::Scalar); + EXPECT_EQ(pointee->GetScalar().ULongLong(), 42u); + + // ...or a block of bytes, with the byte offset applied. + result = evaluate({DW_OP_implicit_pointer, offs_const_block, 0, 0, 0, 1}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + pointee = dereference(*result); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + ASSERT_EQ(pointee->GetValueType(), Value::ValueType::HostAddress); + ASSERT_EQ(pointee->GetBuffer().GetByteSize(), 1u); + EXPECT_EQ(pointee->GetBuffer().GetBytes()[0], 0x20); + + // ...whereas an unavailable pointee (neither DW_AT_location nor + // DW_AT_const_value on the referenced DIE) is an error, never a zero + // value. + result = evaluate({DW_OP_implicit_pointer, offs_no_location, 0, 0, 0, 0}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + EXPECT_THAT_EXPECTED(dereference(*result), llvm::Failed()); + + // A DIE offset that does not resolve is likewise an error. + result = evaluate({DW_OP_implicit_pointer, 0x01, 0, 0, 0, 0}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + EXPECT_THAT_EXPECTED(dereference(*result), llvm::Failed()); + + // A byte offset cannot be applied to a scalar pointee. + result = evaluate({DW_OP_implicit_pointer, offs_scalar, 0, 0, 0, 2}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + EXPECT_THAT_EXPECTED(dereference(*result), llvm::Failed()); + + // A composite (DW_OP_piece) value with an implicit-pointer piece: the + // composite's buffer carries placeholder bytes for the piece, and the + // piece's actual value is recorded in the implicit-pointer table. This is + // how an optimized-out boxed value is described: each piece is one field + // of the block, and pointer-valued fields may be implicit pointers. + result = evaluate({DW_OP_lit1, DW_OP_stack_value, DW_OP_piece, 4, // + DW_OP_implicit_pointer, offs_bytes, 0, 0, 0, 0, // + DW_OP_piece, 8}); + ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); + ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress); + ASSERT_EQ(result->GetBuffer().GetByteSize(), 12u); + EXPECT_EQ(result->GetBuffer().GetBytes()[0], 1); + ASSERT_EQ(result->GetImplicitPointerPieces().size(), 1u); + // The second field's range is in the table; the first field's is not. + EXPECT_EQ(result->FindImplicitPointerPiece(0, 4), nullptr); + const Value::ImplicitPointerPiece *piece = + result->FindImplicitPointerPiece(4, 8); + ASSERT_NE(piece, nullptr); + EXPECT_EQ(piece->pointee.die_offset, (uint64_t)offs_bytes); + EXPECT_EQ(piece->pointee.byte_offset, 0); + + // The recorded piece dereferences like any other implicit pointer. + Value piece_pointer; + piece_pointer.SetImplicitPointer(piece->pointee.delegate, + piece->pointee.die_offset, + piece->pointee.byte_offset); + pointee = dereference(piece_pointer); + ASSERT_THAT_EXPECTED(pointee, llvm::Succeeded()); + ASSERT_EQ(pointee->GetValueType(), Value::ValueType::HostAddress); + ASSERT_EQ(pointee->GetBuffer().GetByteSize(), 4u); + EXPECT_EQ(pointee->GetBuffer().GetBytes()[0], 0xaa); + + // Without a compile unit the operation cannot be evaluated. + EXPECT_THAT_EXPECTED(Evaluate({DW_OP_implicit_pointer, 0x0e, 0, 0, 0, 0}), + llvm::Failed()); +} + TEST(DWARFExpression, DW_OP_stack_value) { EXPECT_THAT_EXPECTED(Evaluate({DW_OP_stack_value}), llvm::Failed()); } From 1e2716d788b73e19893b89b0eb23c9c2d2b70755 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Thu, 11 Jun 2026 15:42:24 +0100 Subject: [PATCH 4/9] more pointers --- .../include/lldb/Expression/DWARFExpression.h | 35 ++++-- lldb/source/Expression/DWARFExpression.cpp | 56 +++++++++- .../Language/OxCaml/LogChannelOxCaml.h | 11 +- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 103 ++++++++++++++++-- .../Plugins/SymbolFile/DWARF/DWARFUnit.h | 5 +- 5 files changed, 184 insertions(+), 26 deletions(-) diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index dc9bd2142bb2e..37e9b3e829f63 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -62,19 +62,38 @@ class DWARFExpressionDelegate { /// (DW_OP_call2/DW_OP_call4), otherwise it is an offset in the /// .debug_info section (DW_OP_call_ref, DW_OP_implicit_pointer). /// + /// \param[in] pc_function_offset + /// The offset of the program counter from the entry point of the + /// function the frame is executing in, or std::nullopt when there is + /// no frame or function. When the referenced DIE's DW_AT_location is + /// a location list rather than a single expression, this selects the + /// list entry that applies. A function-relative offset is used + /// because location list ranges are expressed in the address space + /// of the DWARF that defines them, which is not necessarily the + /// address space the program runs in (for example on Darwin without + /// a dSYM, where the DWARF lives in the .o files); the offset is the + /// same in both spaces and is re-anchored at the DWARF-side + /// function's entry point. + /// /// \return /// The location expression data and the delegate to evaluate it /// with. An empty (zero length) DataExtractor is returned when the - /// referenced DIE exists but has no DW_AT_location attribute; the - /// caller decides what that means (for the DW_OP_call operations it - /// means the call has no effect; for DW_OP_implicit_pointer it means - /// the pointed-at value is unavailable). An error is returned if the - /// DIE cannot be resolved or its DW_AT_location is not an expression - /// block (i.e. it is a location list, which is not currently - /// supported here). + /// referenced DIE exists but has no location description that + /// applies: either it has no DW_AT_location attribute at all, or the + /// attribute is a location list none of whose entries cover the + /// program counter. The caller decides what that means (for the + /// DW_OP_call operations the call has no effect, which + /// compiler-emitted guard expressions rely on to detect unavailable + /// values; for DW_OP_implicit_pointer the pointed-at value is + /// unavailable). An error is returned if the DIE cannot be resolved, + /// or if its DW_AT_location is a location list and + /// \a pc_function_offset is unknown (the applicable entry then + /// cannot be determined at all). virtual llvm::Expected< std::pair> - GetDIELocationExpression(uint64_t die_offset, bool unit_relative) const = 0; + GetDIELocationExpression(uint64_t die_offset, bool unit_relative, + std::optional pc_function_offset) + const = 0; /// Return the value of the DW_AT_const_value attribute of the DIE at /// \a die_offset in the .debug_info section. This is used when diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 8f680af918e92..0effeaa8b4c8a 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -966,6 +966,45 @@ static Scalar DerefSizeExtractDataHelper(uint8_t *addr_bytes, /// references in (malformed) DWARF, which would otherwise recurse forever. static constexpr uint32_t g_max_dwarf_call_depth = 64; +/// Return the offset of the program counter from the entry point of the +/// function the frame is executing in, for selecting the entry of a +/// location list that applies at that point in the program (see +/// DWARFExpressionDelegate::GetDIELocationExpression). Returns std::nullopt +/// when there is no frame or no function, never an offset that could be +/// mistaken for a real one. +static std::optional +GetPCFunctionOffsetForLocationLists(ExecutionContext *exe_ctx, + RegisterContext *reg_ctx) { + StackFrame *frame = exe_ctx ? exe_ctx->GetFramePtr() : nullptr; + Address pc; + if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) { + if (!frame) + return std::nullopt; + lldb::RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); + if (!reg_ctx_sp || !reg_ctx_sp->GetPCForSymbolication(pc)) + return std::nullopt; + } + if (!pc.IsValid() || !frame) + return std::nullopt; + const SymbolContext &sc = + frame->GetSymbolContext(lldb::eSymbolContextFunction); + if (!sc.function) + return std::nullopt; + Target *target = exe_ctx->GetTargetPtr(); + lldb::addr_t pc_addr = pc.GetLoadAddress(target); + lldb::addr_t func_addr = sc.function->GetAddress().GetLoadAddress(target); + if (pc_addr == LLDB_INVALID_ADDRESS || func_addr == LLDB_INVALID_ADDRESS) { + // Not loaded into a process (e.g. static analysis of a binary): both + // addresses are still comparable as file addresses. + pc_addr = pc.GetFileAddress(); + func_addr = sc.function->GetAddress().GetFileAddress(); + } + if (pc_addr == LLDB_INVALID_ADDRESS || func_addr == LLDB_INVALID_ADDRESS || + pc_addr < func_addr) + return std::nullopt; + return pc_addr - func_addr; +} + /// Evaluate the DWARF expression in \a opcodes against \a stack. /// /// This implements the opcode interpreter loop of DWARFExpression::Evaluate, @@ -2228,8 +2267,12 @@ static llvm::Error EvaluateOpcodes( unit_relative = false; } - auto callee_or_err = - dwarf_cu->GetDIELocationExpression(die_offset, unit_relative); + // The current PC selects the applicable entry when the referenced + // DIE's DW_AT_location is a location list rather than a single + // expression. + auto callee_or_err = dwarf_cu->GetDIELocationExpression( + die_offset, unit_relative, + GetPCFunctionOffsetForLocationLists(exe_ctx, reg_ctx)); if (!callee_or_err) return callee_or_err.takeError(); const DataExtractor &callee_opcodes = callee_or_err->first; @@ -2501,8 +2544,11 @@ llvm::Expected DWARFExpression::DereferenceImplicitPointer( return llvm::createStringError( "implicit pointer does not identify a DWARF unit"); + // The current PC selects the applicable entry when the pointee DIE's + // DW_AT_location is a location list rather than a single expression. auto pointee_loc_or_err = info->delegate->GetDIELocationExpression( - info->die_offset, /*unit_relative=*/false); + info->die_offset, /*unit_relative=*/false, + GetPCFunctionOffsetForLocationLists(exe_ctx, reg_ctx)); if (!pointee_loc_or_err) return pointee_loc_or_err.takeError(); const DataExtractor &pointee_opcodes = pointee_loc_or_err->first; @@ -2530,8 +2576,8 @@ llvm::Expected DWARFExpression::DereferenceImplicitPointer( // it can never be conflated with a value that happens to be zero. return llvm::createStringError( "implicit pointer target DIE at .debug_info offset 0x%" PRIx64 - " has neither DW_AT_location nor DW_AT_const_value; the pointed-at " - "value is unavailable", + " has no DW_AT_location applicable at the current PC and no " + "DW_AT_const_value; the pointed-at value is unavailable", info->die_offset); pointee = std::move(**const_value); } diff --git a/lldb/source/Plugins/Language/OxCaml/LogChannelOxCaml.h b/lldb/source/Plugins/Language/OxCaml/LogChannelOxCaml.h index 4587a27adeea6..0529a708cd7f5 100644 --- a/lldb/source/Plugins/Language/OxCaml/LogChannelOxCaml.h +++ b/lldb/source/Plugins/Language/OxCaml/LogChannelOxCaml.h @@ -29,12 +29,17 @@ LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); #define OXCAML_EXPLAIN_ERROR_MARKER(DISPLAY_TOKEN, FORMAT_STRING, ...) \ do { \ + /* The format arguments must be evaluated exactly once, whether or not \ + the log channel is enabled: call sites pass expressions with side \ + effects, such as llvm::toString(expected.takeError()), which must run \ + to consume the error (an unconsumed llvm::Expected error aborts). */ \ + std::string oxcaml_explanation__ = \ + llvm::formatv(FORMAT_STRING, __VA_ARGS__).str(); \ ::lldb_private::Log *oxcaml_log__ = \ ::lldb_private::GetLog(::lldb_private::OxCamlLog::UserVisibleErrors); \ if (oxcaml_log__) \ - LLDB_LOG(oxcaml_log__, "{0}; displaying {1} ({2})", \ - llvm::formatv(FORMAT_STRING, __VA_ARGS__), (DISPLAY_TOKEN), \ - __func__); \ + LLDB_LOG(oxcaml_log__, "{0}; displaying {1} ({2})", oxcaml_explanation__, \ + (DISPLAY_TOKEN), __func__); \ } while (false) #define OXCAML_EMIT_MARKER(STREAM, MARKER_EXPR, ERROR_FMT, ...) \ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 88321488335b0..54f82af9dbbbb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -10,6 +10,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/StreamString.h" @@ -729,8 +730,9 @@ DWARFUnit::GetDIEBitSizeAndSign(uint64_t relative_die_offset) const { } llvm::Expected> -DWARFUnit::GetDIELocationExpression(uint64_t die_offset, - bool unit_relative) const { +DWARFUnit::GetDIELocationExpression( + uint64_t die_offset, bool unit_relative, + std::optional pc_function_offset) const { // FIXME: the constness has annoying ripple effects. DWARFUnit *self = const_cast(this); DWARFDIE die; @@ -758,12 +760,97 @@ DWARFUnit::GetDIELocationExpression(uint64_t die_offset, return std::pair{DataExtractor(), static_cast(this)}; - if (!DWARFFormValue::IsBlockForm(form_value.Form())) - return llvm::createStringError( - "DW_OP_call target DIE at offset 0x%" PRIx64 - " has a DW_AT_location that is not an expression block " - "(location lists are not supported)", - die_offset); + if (!DWARFFormValue::IsBlockForm(form_value.Form())) { + // The DW_AT_location is a location list: which expression describes the + // value depends on the program counter. Parse the list and select the + // entry covering the current PC. + const DWARFUnit *expr_unit = form_value.GetUnit(); + if (!pc_function_offset) + return llvm::createStringError( + "DIE at offset 0x%" PRIx64 " has a location list DW_AT_location, " + "but the current PC is unknown so no entry can be selected", + die_offset); + + // Location list ranges are expressed in the address space of this + // DWARF, which is not necessarily the address space the program runs + // in (for example on Darwin without a dSYM, where the DWARF lives in + // the .o files). Translate the function-relative PC into this space by + // anchoring it at the entry point of the function containing the + // referenced DIE; DIEs whose locations are referenced by DW_OP_call* + // or DW_OP_implicit_pointer describe values of the function being + // executed, so this is the same function the PC offset is relative to. + DWARFDIE func_die = die; + while (func_die && func_die.Tag() != DW_TAG_subprogram) + func_die = func_die.GetParent(); + if (!func_die) + return llvm::createStringError( + "DIE at offset 0x%" PRIx64 " has a location list DW_AT_location " + "but no enclosing DW_TAG_subprogram to anchor the PC against", + die_offset); + const dw_addr_t func_low_pc = + func_die.GetAttributeValueAsAddress(DW_AT_low_pc, LLDB_INVALID_ADDRESS); + if (func_low_pc == LLDB_INVALID_ADDRESS) + return llvm::createStringError( + "the function enclosing the DIE at offset 0x%" PRIx64 + " has no DW_AT_low_pc to anchor the PC against for its location " + "list", + die_offset); + const dw_addr_t pc_file_addr = func_low_pc + *pc_function_offset; + + DataExtractor loc_data = expr_unit->GetLocationData(); + uint64_t loc_offset = form_value.Unsigned(); + if (form_value.Form() == DW_FORM_loclistx) { + std::optional indexed_offset = + const_cast(expr_unit)->GetLoclistOffset(loc_offset); + if (!indexed_offset) + return llvm::createStringError( + "DIE at offset 0x%" PRIx64 " has an unresolvable DW_FORM_loclistx " + "location list index %" PRIu64, + die_offset, loc_offset); + loc_offset = *indexed_offset; + } + if (!loc_data.ValidOffset(loc_offset)) + return llvm::createStringError( + "DIE at offset 0x%" PRIx64 " has a location list offset 0x%" PRIx64 + " outside the location list section", + die_offset, loc_offset); + + loc_data = DataExtractor(loc_data, loc_offset, + loc_data.GetByteSize() - loc_offset); + lldb::ModuleSP module_sp = + GetSymbolFileDWARF().GetObjectFile()->GetModule(); + DWARFExpressionList location_list(module_sp, DWARFExpression(), expr_unit); + if (!expr_unit->ParseDWARFLocationList(loc_data, location_list)) + return llvm::createStringError( + "failed to parse the location list of the DIE at offset 0x%" PRIx64, + die_offset); + + // The list entries hold file address ranges; passing + // LLDB_INVALID_ADDRESS as the function load address makes the lookup + // interpret pc_file_addr in file address terms as well. + const DWARFExpression *expr = location_list.GetExpressionAtAddress( + LLDB_INVALID_ADDRESS, pc_file_addr); + if (!expr) + // No entry covers the current PC: the value is unavailable at this + // point in the program. This is the location list analogue of a + // missing DW_AT_location attribute, so report it the same way, with + // an empty expression. DW_OP_call* then has no effect, which + // compiler-emitted guard expressions (push a fallback; call; branch + // on whether the call pushed a value) rely on, and dereferencing an + // implicit pointer reports the pointee as unavailable. + return std::pair{DataExtractor(), + static_cast(this)}; + + DataExtractor expr_data; + if (!expr->GetExpressionData(expr_data)) + return llvm::createStringError( + "failed to extract the location list expression of the DIE at " + "offset 0x%" PRIx64, + die_offset); + expr_data.SetAddressByteSize(expr_unit->GetAddressByteSize()); + return std::pair{expr_data, + static_cast(expr_unit)}; + } const uint8_t *block_data = form_value.BlockData(); uint64_t block_length = form_value.Unsigned(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 9b319651c58ee..8306f6f7761d5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -165,8 +165,9 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID { } llvm::Expected> - GetDIELocationExpression(uint64_t die_offset, - bool unit_relative) const override; + GetDIELocationExpression(uint64_t die_offset, bool unit_relative, + std::optional pc_function_offset) + const override; llvm::Expected> GetDIEConstValue(uint64_t die_offset) const override; From 125701da414a4a0d3dab814b43be631f9a999be6 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Thu, 11 Jun 2026 15:58:42 +0100 Subject: [PATCH 5/9] debug map --- .../lldb/Expression/DWARFExpressionList.h | 22 ++++++++++++ lldb/source/Expression/DWARFExpression.cpp | 25 +++++++++++++ .../source/Expression/DWARFExpressionList.cpp | 33 +++++++++++++++++ .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 36 +++++++++++++++++++ 4 files changed, 116 insertions(+) diff --git a/lldb/include/lldb/Expression/DWARFExpressionList.h b/lldb/include/lldb/Expression/DWARFExpressionList.h index d303ad834b354..cedb96bbbacf2 100644 --- a/lldb/include/lldb/Expression/DWARFExpressionList.h +++ b/lldb/include/lldb/Expression/DWARFExpressionList.h @@ -93,6 +93,23 @@ class DWARFExpressionList { std::function const &link_address_callback); + /// Rewrite the operand of the DW_OP_addr operation in each expression of + /// the list by passing it through \a link_address_callback. This is used + /// when the expressions come from a .o file behind a debug map (Darwin + /// without a dSYM): DW_OP_addr operands then hold .o file addresses, + /// which must be linked into the executable's address space to be + /// resolvable at evaluation time. Expressions without a DW_OP_addr are + /// left untouched. + /// + /// \return + /// True if every DW_OP_addr operand found was successfully linked + /// and rewritten; false if any was left unlinked (the callback + /// returned LLDB_INVALID_ADDRESS, e.g. the referenced object did + /// not make it into the linked executable) or could not be parsed. + bool LinkDWOPAddrOperands( + std::function const + &link_address_callback); + bool MatchesOperand(StackFrame &frame, const Instruction::Operand &operand) const; @@ -120,6 +137,11 @@ class DWARFExpressionList { void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } + /// Return the module whose DWARF the expressions came from, if it is + /// still loaded. Addresses pushed by DW_OP_addr within the expressions + /// are file addresses in this module's address space. + lldb::ModuleSP GetModule() const { return m_module_wp.lock(); } + llvm::Expected Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::addr_t func_load_addr, diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 0effeaa8b4c8a..fc7b0ba1518ec 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -790,6 +790,18 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, return maybe_result.takeError(); } + // A DW_AT_call_value expression produces a value, not a location, so a + // DW_OP_addr within it (e.g. a pointer argument to a statically + // allocated object) denotes the address as the value. Resolve such a + // file address here, where the module it belongs to (the caller + // expression's own) is known: the caller may be in a different module + // than the callee whose expression we resume below, and under a Darwin + // debug map each .o has its own file address space, so resolving it any + // later could consult the wrong module. + if (maybe_result->GetValueType() == Value::ValueType::FileAddress) + maybe_result->ConvertToLoadAddress(param_expr.GetModule().get(), + parent_exe_ctx.GetTargetPtr()); + stack.push_back(*maybe_result); return llvm::Error::success(); } @@ -2306,7 +2318,20 @@ static llvm::Error EvaluateOpcodes( // rather is a constant value. The value from the top of the stack is the // value to be used. This is the actual object value and not the location. case DW_OP_stack_value: + if (stack.empty()) + return llvm::createStringError( + "expression stack needs at least 1 item for DW_OP_stack_value"); dwarf4_location_description_kind = Implicit; + // The value may be an as-yet unresolved file address (e.g. DW_OP_addr + // ... DW_OP_stack_value, describing a pointer to a statically + // allocated object). DW_OP_addr pushes an address "relocated by the + // consumer"; complete that deferred relocation now, before the + // conversion to a plain scalar erases the value's address provenance. + // Otherwise consumers would receive the unrelocated address (under a + // Darwin debug map, an address in the .o file's own address space). + // If the address cannot be resolved (no target, or the module is not + // loaded), the value is left as the file address, as before. + stack.back().ConvertToLoadAddress(module_sp.get(), target); stack.back().SetValueType(Value::ValueType::Scalar); break; diff --git a/lldb/source/Expression/DWARFExpressionList.cpp b/lldb/source/Expression/DWARFExpressionList.cpp index ef7333518f008..06579ba990700 100644 --- a/lldb/source/Expression/DWARFExpressionList.cpp +++ b/lldb/source/Expression/DWARFExpressionList.cpp @@ -11,6 +11,8 @@ #include "lldb/Symbol/Function.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" @@ -144,6 +146,37 @@ bool DWARFExpressionList::LinkThreadLocalStorage( return true; } +bool DWARFExpressionList::LinkDWOPAddrOperands( + std::function const + &link_address_callback) { + bool all_linked = true; + for (size_t i = 0; i < m_exprs.GetSize(); ++i) { + DWARFExpression &expr = m_exprs.GetMutableEntryAtIndex(i)->data; + llvm::Expected file_addr = + expr.GetLocation_DW_OP_addr(m_dwarf_cu); + if (!file_addr) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), file_addr.takeError(), + "Cannot link DW_OP_addr operand: {0}"); + all_linked = false; + continue; + } + if (*file_addr == LLDB_INVALID_ADDRESS) + // The expression has no DW_OP_addr operation. + continue; + const lldb::addr_t linked_file_addr = link_address_callback(*file_addr); + if (linked_file_addr == LLDB_INVALID_ADDRESS) { + // The object the address refers to did not make it into the linked + // executable. Leave the expression untouched; evaluating it will not + // produce a resolvable address. + all_linked = false; + continue; + } + if (!expr.Update_DW_OP_addr(m_dwarf_cu, linked_file_addr)) + all_linked = false; + } + return all_linked; +} + bool DWARFExpressionList::MatchesOperand( StackFrame &frame, const Instruction::Operand &operand) const { RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index c47145b3622c0..d45845c33e9a8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3598,6 +3598,19 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, this, unlinked_file_addr); }); scope = eValueTypeVariableThreadLocal; + } else { + // A local's location list entries may also contain DW_OP_addr + // operands holding .o file addresses, e.g. a pointer to a + // statically allocated object described as DW_OP_addr , + // DW_OP_stack_value. Link them into the executable's address + // space, like the static-variable case above does for its + // single expression. + location_list.LinkDWOPAddrOperands( + [this, debug_map_symfile]( + lldb::addr_t unlinked_file_addr) -> lldb::addr_t { + return debug_map_symfile->LinkOSOFileAddress( + this, unlinked_file_addr); + }); } } } @@ -4089,6 +4102,29 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { CallSiteParameterArray parameters = CollectCallSiteParameters(module, child); + // The expressions above were built from the raw DWARF, so under a debug + // map any DW_OP_addr operand they contain still holds a .o file address. + // Link such operands into the executable's address space, and point the + // expressions at the linked module so the addresses resolve there when + // they are evaluated. Note that LocationInCallee must stay untouched: it + // is matched byte-for-byte against the callee's DW_OP_entry_value + // sub-expression (also raw DWARF) and is never evaluated. + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) { + ModuleSP linked_module_sp = + debug_map_symfile->GetObjectFile()->GetModule(); + const auto link_address = [this](lldb::addr_t file_addr) { + return FixupAddress(file_addr); + }; + for (CallSiteParameter ¶m : parameters) { + param.LocationInCaller.LinkDWOPAddrOperands(link_address); + param.LocationInCaller.SetModule(linked_module_sp); + } + if (call_target) { + call_target->LinkDWOPAddrOperands(link_address); + call_target->SetModule(linked_module_sp); + } + } + std::unique_ptr edge; if (call_origin) { LLDB_LOG(log, From 9d5ce0cd453d076c4d8b0d656a168c837d98e5c0 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Mon, 15 Jun 2026 11:30:57 +0100 Subject: [PATCH 6/9] potential entry value fixes --- .../include/lldb/Expression/DWARFExpression.h | 51 +++- .../lldb/Expression/DWARFExpressionList.h | 10 +- lldb/include/lldb/Symbol/Function.h | 20 +- lldb/source/Expression/DWARFExpression.cpp | 230 +++++++++++------- .../source/Expression/DWARFExpressionList.cpp | 5 +- lldb/source/Symbol/Function.cpp | 10 +- lldb/source/Target/StackFrameList.cpp | 31 ++- 7 files changed, 247 insertions(+), 110 deletions(-) diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 37e9b3e829f63..f762568c7b603 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -24,6 +24,49 @@ namespace lldb_private { +class CallEdge; + +/// Context for resolving a DW_OP_entry_value that refers to the entry of a +/// function which is not represented by a live stack frame. +/// +/// Normally DW_OP_entry_value is resolved by walking the live call stack from +/// the frame being evaluated up to its caller, then finding the call site that +/// produced the activation (see Evaluate_DW_OP_entry_value). That walk is +/// impossible while the stack frame list is still being built, which is when +/// tail-call frames are synthesized: the function whose entry value is +/// referenced was reached through the static call graph and has no frame of +/// its own to walk back from, and re-entering the frame list would deadlock. +/// +/// This structure supplies that information explicitly instead. \ref edge is +/// the call that produced the activation whose entry is referenced; its call +/// site parameters map a callee-side location (matched against the +/// DW_OP_entry_value sub-expression) to a caller-side location. That +/// caller-side location is then evaluated either in \ref caller_frame, when +/// the caller is a live frame, or — when the caller is itself a frameless link +/// in a tail-call chain — by recursively resolving any DW_OP_entry_value it +/// contains against \ref outer, chaining back through the tail-call chain until +/// a live frame is reached. +/// +/// A frameless caller can only contribute values that are themselves further +/// entry values or constants. If its caller-side location needs state that a +/// vanished activation cannot provide (a register, frame base, or stack slot), +/// evaluation fails rather than producing an unreliable value. +struct EntryValueResolutionContext { + /// The call edge whose call site parameters describe the entry value. Never + /// null in a well-formed context. + const CallEdge *edge = nullptr; + + /// The live frame of the caller (the function containing \ref edge's call + /// site), or null when that caller is itself a frameless link in a tail-call + /// chain. + StackFrame *caller_frame = nullptr; + + /// When \ref caller_frame is null, how to resolve a DW_OP_entry_value that + /// appears within the caller-side location expression. A null \ref outer + /// together with a null \ref caller_frame means the chain cannot be resolved. + const EntryValueResolutionContext *outer = nullptr; +}; + /// \class DWARFExpressionDelegate DWARFExpression.h /// "lldb/Expression/DWARFExpression.h" Interface through which the DWARF /// expression evaluator accesses the DWARF unit that contains the expression @@ -225,11 +268,17 @@ class DWARFExpression { /// \return /// True on success; false otherwise. If error_ptr is non-NULL, /// details of the failure are provided through it. + /// \param[in] entry_value_ctx + /// Optional explicit context for resolving a DW_OP_entry_value whose + /// referenced function has no live stack frame (used while synthesizing + /// tail-call frames). When null, DW_OP_entry_value is resolved by walking + /// the live call stack instead. \see EntryValueResolutionContext. static llvm::Expected Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::ModuleSP module_sp, const DataExtractor &opcodes, const Delegate *dwarf_cu, const lldb::RegisterKind reg_set, - const Value *initial_value_ptr, const Value *object_address_ptr); + const Value *initial_value_ptr, const Value *object_address_ptr, + const EntryValueResolutionContext *entry_value_ctx = nullptr); /// Materialize the value an implicit pointer points at. /// diff --git a/lldb/include/lldb/Expression/DWARFExpressionList.h b/lldb/include/lldb/Expression/DWARFExpressionList.h index cedb96bbbacf2..76e81cc210b7b 100644 --- a/lldb/include/lldb/Expression/DWARFExpressionList.h +++ b/lldb/include/lldb/Expression/DWARFExpressionList.h @@ -142,11 +142,11 @@ class DWARFExpressionList { /// are file addresses in this module's address space. lldb::ModuleSP GetModule() const { return m_module_wp.lock(); } - llvm::Expected Evaluate(ExecutionContext *exe_ctx, - RegisterContext *reg_ctx, - lldb::addr_t func_load_addr, - const Value *initial_value_ptr, - const Value *object_address_ptr) const; + llvm::Expected + Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, + lldb::addr_t func_load_addr, const Value *initial_value_ptr, + const Value *object_address_ptr, + const EntryValueResolutionContext *entry_value_ctx = nullptr) const; private: // RangeDataVector requires a comparator for DWARFExpression, but it doesn't diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h index 21b3f9ab4a70c..306fce320a3ca 100644 --- a/lldb/include/lldb/Symbol/Function.h +++ b/lldb/include/lldb/Symbol/Function.h @@ -274,8 +274,16 @@ class CallEdge { /// /// Note that this might lazily invoke the DWARF parser. A register context /// from the caller's activation is needed to find indirect call targets. - virtual Function *GetCallee(ModuleList &images, - ExecutionContext &exe_ctx) = 0; + /// + /// \param[in] entry_value_ctx + /// Optional context for resolving a DW_OP_entry_value in an indirect + /// call target whose containing function has no live frame, as happens + /// while synthesizing tail-call frames. Null in the common case, where + /// DW_OP_entry_value resolves against the live call stack. + /// \see EntryValueResolutionContext. + virtual Function * + GetCallee(ModuleList &images, ExecutionContext &exe_ctx, + const EntryValueResolutionContext *entry_value_ctx = nullptr) = 0; /// Get the load PC address of the instruction which executes after the call /// returns. Returns LLDB_INVALID_ADDRESS iff this is a tail call. \p caller @@ -339,7 +347,9 @@ class DirectCallEdge : public CallEdge { lldb::addr_t caller_address, bool is_tail_call, CallSiteParameterArray &¶meters); - Function *GetCallee(ModuleList &images, ExecutionContext &exe_ctx) override; + Function * + GetCallee(ModuleList &images, ExecutionContext &exe_ctx, + const EntryValueResolutionContext *entry_value_ctx) override; private: void ParseSymbolFileAndResolve(ModuleList &images); @@ -368,7 +378,9 @@ class IndirectCallEdge : public CallEdge { AddrType caller_address_type, lldb::addr_t caller_address, bool is_tail_call, CallSiteParameterArray &¶meters); - Function *GetCallee(ModuleList &images, ExecutionContext &exe_ctx) override; + Function * + GetCallee(ModuleList &images, ExecutionContext &exe_ctx, + const EntryValueResolutionContext *entry_value_ctx) override; private: // Used to describe an indirect call. diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index fc7b0ba1518ec..a6d8653d89cc2 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -604,12 +604,12 @@ bool DWARFExpression::LinkThreadLocalStorage( return true; } -static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, - ExecutionContext *exe_ctx, - RegisterContext *reg_ctx, - const DataExtractor &opcodes, - lldb::offset_t &opcode_offset, - Log *log) { +static llvm::Error +Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, + ExecutionContext *exe_ctx, RegisterContext *reg_ctx, + const DataExtractor &opcodes, + lldb::offset_t &opcode_offset, Log *log, + const EntryValueResolutionContext *entry_value_ctx) { // DW_OP_entry_value(sub-expr) describes the location a variable had upon // function entry: this variable location is presumed to be optimized out at // the current PC value. The caller of the function may have call site @@ -655,84 +655,113 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, // and evaluates the corresponding location for that parameter in `parent`. // 1. Find the function which pushed the current frame onto the stack. - if ((!exe_ctx || !exe_ctx->HasTargetScope()) || !reg_ctx) { - return llvm::createStringError("no exe/reg context"); - } - - StackFrame *current_frame = exe_ctx->GetFramePtr(); - Thread *thread = exe_ctx->GetThreadPtr(); - if (!current_frame || !thread) - return llvm::createStringError("no current frame/thread"); + if (!exe_ctx || !exe_ctx->HasTargetScope()) + return llvm::createStringError("no exe/target context"); + // A register context is only needed for the live-stack walk below; an + // explicit resolution context carries everything it needs itself. + if (!entry_value_ctx && !reg_ctx) + return llvm::createStringError("no register context"); Target &target = exe_ctx->GetTargetRef(); - StackFrameSP parent_frame = nullptr; - addr_t return_pc = LLDB_INVALID_ADDRESS; - uint32_t current_frame_idx = current_frame->GetFrameIndex(); - - for (uint32_t parent_frame_idx = current_frame_idx + 1;; parent_frame_idx++) { - parent_frame = thread->GetStackFrameAtIndex(parent_frame_idx); - // If this is null, we're at the end of the stack. - if (!parent_frame) - break; - - // Record the first valid return address, even if this is an inlined frame, - // in order to look up the associated call edge in the first non-inlined - // parent frame. - if (return_pc == LLDB_INVALID_ADDRESS) { - return_pc = parent_frame->GetFrameCodeAddress().GetLoadAddress(&target); - LLDB_LOG(log, "immediate ancestor with pc = {0:x}", return_pc); - } - - // If we've found an inlined frame, skip it (these have no call site - // parameters). - if (parent_frame->IsInlined()) - continue; + ModuleList &modlist = target.GetImages(); - // We've found the first non-inlined parent frame. - break; - } - if (!parent_frame || !parent_frame->GetRegisterContext()) { - return llvm::createStringError("no parent frame with reg ctx"); - } + // The call edge whose call site parameters describe the entry value, plus how + // to evaluate the matched caller-side location: either in a live frame + // (\ref caller_frame), or — for a frameless link in a tail-call chain — by + // chaining any DW_OP_entry_value it contains through \ref outer_ctx. + const CallEdge *call_edge = nullptr; + StackFrameSP caller_frame; + const EntryValueResolutionContext *outer_ctx = nullptr; + + if (entry_value_ctx) { + // Explicit resolution: the referenced function has no live frame (this + // happens while synthesizing tail-call frames). Use the supplied edge and + // caller context directly. Walking the live stack here is both impossible + // (the function has no frame) and unsafe (it would re-enter the stack frame + // list while it is being built). + call_edge = entry_value_ctx->edge; + if (!call_edge) + return llvm::createStringError("entry value context has no call edge"); + if (entry_value_ctx->caller_frame) + caller_frame = entry_value_ctx->caller_frame->shared_from_this(); + outer_ctx = entry_value_ctx->outer; + if (!caller_frame && !outer_ctx) + return llvm::createStringError( + "entry value caller is frameless and cannot be resolved"); + } else { + StackFrame *current_frame = exe_ctx->GetFramePtr(); + Thread *thread = exe_ctx->GetThreadPtr(); + if (!current_frame || !thread) + return llvm::createStringError("no current frame/thread"); + + addr_t return_pc = LLDB_INVALID_ADDRESS; + uint32_t current_frame_idx = current_frame->GetFrameIndex(); + + for (uint32_t parent_frame_idx = current_frame_idx + 1;; + parent_frame_idx++) { + caller_frame = thread->GetStackFrameAtIndex(parent_frame_idx); + // If this is null, we're at the end of the stack. + if (!caller_frame) + break; - Function *parent_func = - parent_frame->GetSymbolContext(eSymbolContextFunction).function; - if (!parent_func) - return llvm::createStringError("no parent function"); + // Record the first valid return address, even if this is an inlined + // frame, in order to look up the associated call edge in the first + // non-inlined parent frame. + if (return_pc == LLDB_INVALID_ADDRESS) { + return_pc = caller_frame->GetFrameCodeAddress().GetLoadAddress(&target); + LLDB_LOG(log, "immediate ancestor with pc = {0:x}", return_pc); + } - // 2. Find the call edge in the parent function responsible for creating the - // current activation. - Function *current_func = - current_frame->GetSymbolContext(eSymbolContextFunction).function; - if (!current_func) - return llvm::createStringError("no current function"); + // If we've found an inlined frame, skip it (these have no call site + // parameters). + if (caller_frame->IsInlined()) + continue; - CallEdge *call_edge = nullptr; - ModuleList &modlist = target.GetImages(); - ExecutionContext parent_exe_ctx = *exe_ctx; - parent_exe_ctx.SetFrameSP(parent_frame); - if (!parent_frame->IsArtificial()) { - // If the parent frame is not artificial, the current activation may be - // produced by an ambiguous tail call. In this case, refuse to proceed. - call_edge = parent_func->GetCallEdgeForReturnAddress(return_pc, target); - if (!call_edge) { - return llvm::createStringError( - llvm::formatv("no call edge for retn-pc = {0:x} in parent frame {1}", - return_pc, parent_func->GetName())); - } - Function *callee_func = call_edge->GetCallee(modlist, parent_exe_ctx); - if (callee_func != current_func) { - return llvm::createStringError( - "ambiguous call sequence, can't find real parent frame"); + // We've found the first non-inlined parent frame. + break; } - } else { - // The StackFrameList solver machinery has deduced that an unambiguous tail - // call sequence that produced the current activation. The first edge in - // the parent that points to the current function must be valid. - for (auto &edge : parent_func->GetTailCallingEdges()) { - if (edge->GetCallee(modlist, parent_exe_ctx) == current_func) { - call_edge = edge.get(); - break; + if (!caller_frame || !caller_frame->GetRegisterContext()) + return llvm::createStringError("no parent frame with reg ctx"); + + Function *parent_func = + caller_frame->GetSymbolContext(eSymbolContextFunction).function; + if (!parent_func) + return llvm::createStringError("no parent function"); + + // 2. Find the call edge in the parent function responsible for creating + // the current activation. + Function *current_func = + current_frame->GetSymbolContext(eSymbolContextFunction).function; + if (!current_func) + return llvm::createStringError("no current function"); + + ExecutionContext parent_exe_ctx = *exe_ctx; + parent_exe_ctx.SetFrameSP(caller_frame); + if (!caller_frame->IsArtificial()) { + // If the parent frame is not artificial, the current activation may be + // produced by an ambiguous tail call. In this case, refuse to proceed. + CallEdge *return_edge = + parent_func->GetCallEdgeForReturnAddress(return_pc, target); + if (!return_edge) + return llvm::createStringError(llvm::formatv( + "no call edge for retn-pc = {0:x} in parent frame {1}", return_pc, + parent_func->GetName())); + Function *callee_func = return_edge->GetCallee( + modlist, parent_exe_ctx, /*entry_value_ctx=*/nullptr); + if (callee_func != current_func) + return llvm::createStringError( + "ambiguous call sequence, can't find real parent frame"); + call_edge = return_edge; + } else { + // The StackFrameList solver machinery has deduced that an unambiguous + // tail call sequence produced the current activation. The first edge in + // the parent that points to the current function must be valid. + for (auto &edge : parent_func->GetTailCallingEdges()) { + if (edge->GetCallee(modlist, parent_exe_ctx, + /*entry_value_ctx=*/nullptr) == current_func) { + call_edge = edge.get(); + break; + } } } } @@ -779,11 +808,31 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, // subexpresion whenever llvm does. const DWARFExpressionList ¶m_expr = matched_param->LocationInCaller; - llvm::Expected maybe_result = param_expr.Evaluate( - &parent_exe_ctx, parent_frame->GetRegisterContext().get(), - LLDB_INVALID_ADDRESS, - /*initial_value_ptr=*/nullptr, - /*object_address_ptr=*/nullptr); + // Evaluate the caller-side location to obtain the entry value. + llvm::Expected maybe_result = + [&]() -> llvm::Expected { + if (caller_frame) { + // The caller is a live frame: evaluate the location in it as usual. + ExecutionContext caller_exe_ctx = *exe_ctx; + caller_exe_ctx.SetFrameSP(caller_frame); + return param_expr.Evaluate(&caller_exe_ctx, + caller_frame->GetRegisterContext().get(), + LLDB_INVALID_ADDRESS, + /*initial_value_ptr=*/nullptr, + /*object_address_ptr=*/nullptr); + } + // The caller is itself a frameless link in a tail-call chain. Its + // registers and stack are gone; only further entry values and constants + // can be recovered. Evaluate with no frame and no register context so that + // any access to the vanished activation's state fails cleanly, and chain a + // nested DW_OP_entry_value to the outer resolution context. + ExecutionContext frameless_ctx(exe_ctx->GetTargetSP(), + /*get_process=*/true); + return param_expr.Evaluate(&frameless_ctx, /*reg_ctx=*/nullptr, + LLDB_INVALID_ADDRESS, + /*initial_value_ptr=*/nullptr, + /*object_address_ptr=*/nullptr, outer_ctx); + }(); if (!maybe_result) { LLDB_LOG(log, "Evaluate_DW_OP_entry_value: call site param evaluation failed"); @@ -800,7 +849,7 @@ static llvm::Error Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, // later could consult the wrong module. if (maybe_result->GetValueType() == Value::ValueType::FileAddress) maybe_result->ConvertToLoadAddress(param_expr.GetModule().get(), - parent_exe_ctx.GetTargetPtr()); + exe_ctx->GetTargetPtr()); stack.push_back(*maybe_result); return llvm::Error::success(); @@ -1032,7 +1081,8 @@ static llvm::Error EvaluateOpcodes( const lldb::RegisterKind reg_kind, const Value *object_address_ptr, DWARFExpression::Stack &stack, LocationDescriptionKind &dwarf4_location_description_kind, Value &pieces, - uint64_t &op_piece_offset, const uint32_t call_depth) { + uint64_t &op_piece_offset, const uint32_t call_depth, + const EntryValueResolutionContext *entry_value_ctx) { Process *process = nullptr; StackFrame *frame = nullptr; Target *target = nullptr; @@ -2307,7 +2357,7 @@ static llvm::Error EvaluateOpcodes( if (llvm::Error err = EvaluateOpcodes( exe_ctx, reg_ctx, module_sp, callee_opcodes, callee_cu, reg_kind, object_address_ptr, stack, dwarf4_location_description_kind, - pieces, op_piece_offset, call_depth + 1)) + pieces, op_piece_offset, call_depth + 1, entry_value_ctx)) return err; break; } @@ -2476,8 +2526,9 @@ static llvm::Error EvaluateOpcodes( case DW_OP_GNU_entry_value: case DW_OP_entry_value: { - if (llvm::Error err = Evaluate_DW_OP_entry_value(stack, exe_ctx, reg_ctx, - opcodes, offset, log)) + if (llvm::Error err = + Evaluate_DW_OP_entry_value(stack, exe_ctx, reg_ctx, opcodes, + offset, log, entry_value_ctx)) return llvm::createStringError( "could not evaluate DW_OP_entry_value: %s", llvm::toString(std::move(err)).c_str()); @@ -2503,7 +2554,8 @@ llvm::Expected DWARFExpression::Evaluate( lldb::ModuleSP module_sp, const DataExtractor &opcodes, const DWARFExpression::Delegate *dwarf_cu, const lldb::RegisterKind reg_kind, const Value *initial_value_ptr, - const Value *object_address_ptr) { + const Value *object_address_ptr, + const EntryValueResolutionContext *entry_value_ctx) { if (opcodes.GetByteSize() == 0) return llvm::createStringError( @@ -2526,7 +2578,7 @@ llvm::Expected DWARFExpression::Evaluate( if (llvm::Error err = EvaluateOpcodes( exe_ctx, reg_ctx, module_sp, opcodes, dwarf_cu, reg_kind, object_address_ptr, stack, dwarf4_location_description_kind, pieces, - op_piece_offset, /*call_depth=*/0)) + op_piece_offset, /*call_depth=*/0, entry_value_ctx)) return std::move(err); Log *log = GetLog(LLDBLog::Expressions); diff --git a/lldb/source/Expression/DWARFExpressionList.cpp b/lldb/source/Expression/DWARFExpressionList.cpp index 06579ba990700..b99634849478b 100644 --- a/lldb/source/Expression/DWARFExpressionList.cpp +++ b/lldb/source/Expression/DWARFExpressionList.cpp @@ -265,7 +265,8 @@ void DWARFExpressionList::GetDescription(Stream *s, llvm::Expected DWARFExpressionList::Evaluate( ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::addr_t func_load_addr, const Value *initial_value_ptr, - const Value *object_address_ptr) const { + const Value *object_address_ptr, + const EntryValueResolutionContext *entry_value_ctx) const { ModuleSP module_sp = m_module_wp.lock(); DataExtractor data; RegisterKind reg_kind; @@ -300,5 +301,5 @@ llvm::Expected DWARFExpressionList::Evaluate( reg_kind = expr.GetRegisterKind(); return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data, m_dwarf_cu, reg_kind, initial_value_ptr, - object_address_ptr); + object_address_ptr, entry_value_ctx); } diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 6114eccd935ee..95e1a78d346b5 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -201,7 +201,8 @@ DirectCallEdge::DirectCallEdge(const char *symbol_name, lazy_callee.symbol_name = symbol_name; } -Function *DirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &) { +Function *DirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &, + const EntryValueResolutionContext *) { ParseSymbolFileAndResolve(images); assert(resolved && "Did not resolve lazy callee"); return lazy_callee.def; @@ -216,14 +217,15 @@ IndirectCallEdge::IndirectCallEdge(DWARFExpressionList call_target, std::move(parameters)), call_target(std::move(call_target)) {} -Function *IndirectCallEdge::GetCallee(ModuleList &images, - ExecutionContext &exe_ctx) { +Function * +IndirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &exe_ctx, + const EntryValueResolutionContext *entry_value_ctx) { Log *log = GetLog(LLDBLog::Step); Status error; llvm::Expected callee_addr_val = call_target.Evaluate( &exe_ctx, exe_ctx.GetRegisterContext(), LLDB_INVALID_ADDRESS, /*initial_value_ptr=*/nullptr, - /*object_address_ptr=*/nullptr); + /*object_address_ptr=*/nullptr, entry_value_ctx); if (!callee_addr_val) { LLDB_LOG_ERROR(log, callee_addr_val.takeError(), "IndirectCallEdge: Could not evaluate expression: {0}"); diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index 16cd2548c2784..310346744b0aa 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -177,7 +177,13 @@ static void FindInterveningFrames(Function &begin, Function &end, } // The first callee may not be resolved, or there may be nothing to fill in. - Function *first_callee = first_edge->GetCallee(images, exe_ctx); + // No explicit entry-value resolution context applies here: a DW_OP_entry_value + // in this regular call's target would refer to the begin function's own + // entry, for which we have no call edge (it would require walking to the + // begin frame's caller, which is unavailable while the frame list is being + // built). Such a target therefore simply stays unresolved, as before. + Function *first_callee = + first_edge->GetCallee(images, exe_ctx, /*entry_value_ctx=*/nullptr); if (!first_callee) { LLDB_LOG(log, "Could not resolve callee"); return; @@ -207,12 +213,20 @@ static void FindInterveningFrames(Function &begin, Function &end, void search(CallEdge &first_edge, Function &first_callee, CallSequence &path) { - dfs(first_edge, first_callee); + // The first callee was reached by a regular (non-tail) call from the + // frame in \ref context, which is a live frame. A DW_OP_entry_value in + // one of the first callee's outgoing edges therefore refers to the first + // callee's entry and is resolved against that live caller via + // \ref first_edge. + EntryValueResolutionContext first_ctx{&first_edge, context.GetFramePtr(), + /*outer=*/nullptr}; + dfs(first_edge, first_callee, &first_ctx); if (!ambiguous) path = std::move(solution_path); } - void dfs(CallEdge ¤t_edge, Function &callee) { + void dfs(CallEdge ¤t_edge, Function &callee, + const EntryValueResolutionContext *callee_ctx) { // Found a path to the target function. if (&callee == end) { if (solution_path.empty()) @@ -234,14 +248,21 @@ static void FindInterveningFrames(Function &begin, Function &end, // Search the calls made from this callee. active_path.push_back(CallDescriptor{&callee}); for (const auto &edge : callee.GetTailCallingEdges()) { - Function *next_callee = edge->GetCallee(images, context); + // A DW_OP_entry_value in this edge's indirect target refers to the + // entry of \p callee; \ref callee_ctx says how to resolve it. The + // function reached through this edge is itself frameless (it was + // tail-called), so if its own entry values are needed deeper in the + // search they chain back through \ref callee_ctx. + Function *next_callee = edge->GetCallee(images, context, callee_ctx); if (!next_callee) continue; std::tie(active_path.back().address_type, active_path.back().address) = edge->GetCallerAddress(callee, target); - dfs(*edge, *next_callee); + EntryValueResolutionContext next_ctx{ + edge.get(), /*caller_frame=*/nullptr, callee_ctx}; + dfs(*edge, *next_callee, &next_ctx); if (ambiguous) return; } From c8dd633d2cc30cb27771b6a5b0c0a5837567ee0b Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Tue, 16 Jun 2026 08:18:57 +0100 Subject: [PATCH 7/9] dsymutil etc --- lldb/source/Expression/DWARFExpression.cpp | 47 ++++- .../llvm/DWARFLinker/Classic/DWARFLinker.h | 25 ++- .../Classic/DWARFLinkerCompileUnit.h | 11 +- llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp | 191 +++++++++++++++++- .../Classic/DWARFLinkerCompileUnit.cpp | 15 +- 5 files changed, 267 insertions(+), 22 deletions(-) diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index a6d8653d89cc2..8ec9f8c0aeb71 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -672,6 +672,11 @@ Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, const CallEdge *call_edge = nullptr; StackFrameSP caller_frame; const EntryValueResolutionContext *outer_ctx = nullptr; + // Backing storage for an [outer_ctx] synthesized in the live-stack-walk path + // below, when the current activation was entered by a tail call from a + // frameless function that the (live) parent frame called. Kept at function + // scope so [outer_ctx] remains valid through the parameter evaluation. + std::optional tail_link_ctx; if (entry_value_ctx) { // Explicit resolution: the referenced function has no live frame (this @@ -738,8 +743,9 @@ Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, ExecutionContext parent_exe_ctx = *exe_ctx; parent_exe_ctx.SetFrameSP(caller_frame); if (!caller_frame->IsArtificial()) { - // If the parent frame is not artificial, the current activation may be - // produced by an ambiguous tail call. In this case, refuse to proceed. + // The parent frame is not artificial, so the current activation was + // produced either by a direct call from the parent, or by a tail call + // from a frameless function that the parent called. CallEdge *return_edge = parent_func->GetCallEdgeForReturnAddress(return_pc, target); if (!return_edge) @@ -748,10 +754,43 @@ Evaluate_DW_OP_entry_value(DWARFExpression::Stack &stack, parent_func->GetName())); Function *callee_func = return_edge->GetCallee( modlist, parent_exe_ctx, /*entry_value_ctx=*/nullptr); - if (callee_func != current_func) + if (callee_func == current_func) { + // The parent called the current function directly. + call_edge = return_edge; + } else if (callee_func) { + // The parent called \ref callee_func, which is not the current function + // but may have entered it by a tail call, leaving no frame of its own + // (e.g. a thunk or a partial-application veneer that loads its arguments + // and tail-calls the real callee). Find the unique tail-calling edge + // from \ref callee_func to the current function and resolve the entry + // value through it. That edge is frameless: \ref callee_func's own entry + // values, and any indirect callee it names, chain back through \ref + // return_edge to this live parent frame. + tail_link_ctx = EntryValueResolutionContext{ + return_edge, caller_frame.get(), /*outer=*/nullptr}; + for (auto &edge : callee_func->GetTailCallingEdges()) { + if (edge->GetCallee(modlist, parent_exe_ctx, &*tail_link_ctx) != + current_func) + continue; + if (call_edge) { + // More than one tail call reaches the current function: ambiguous. + call_edge = nullptr; + break; + } + call_edge = edge.get(); + } + if (!call_edge) + return llvm::createStringError( + "ambiguous call sequence, can't find real parent frame"); + // \ref callee_func has no live frame; evaluate the matched parameter as + // a frameless tail-call link chained to the parent via \ref return_edge. + caller_frame = nullptr; + outer_ctx = &*tail_link_ctx; + } else { + // The parent's indirect call target could not be resolved. return llvm::createStringError( "ambiguous call sequence, can't find real parent frame"); - call_edge = return_edge; + } } else { // The StackFrameList solver machinery has deduced that an unambiguous // tail call sequence produced the current activation. The first edge in diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h index 5b9535380aebf..afc87fafe76ed 100644 --- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h @@ -671,11 +671,32 @@ class LLVM_ABI DWARFLinker : public DWARFLinkerBase { const DWARFFile &File, CompileUnit &Unit); - /// Clone a DWARF expression that may be referencing another DIE. + /// A DIE reference embedded in a cloned DWARF expression. DIE offsets are + /// only final after every unit is cloned, so the reference operand is + /// emitted as a patchable value and fixed up later (see cloneExpression() + /// and CompileUnit::fixupForwardReferences()). + struct ExpressionDIEReference { + /// Byte offset of the reference operand within the cloned expression. + uint64_t BufferOffset; + /// Size of the operand in bytes (2, 4 or 8). + uint8_t Size; + /// (Possibly placeholder) clone of the referenced DIE. + DIE *RefDie; + /// Compile unit owning \p RefDie. + const CompileUnit *RefUnit; + /// True for absolute .debug_info references (DW_OP_call_ref, + /// DW_OP_implicit_pointer); false for CU-relative ones (DW_OP_call2/4). + bool SectionRelative; + }; + + /// Clone a DWARF expression that may be referencing another DIE. Any DIE + /// references found in the expression are appended to \p References so the + /// caller can emit them as patchable values. void cloneExpression(DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File, CompileUnit &Unit, SmallVectorImpl &OutputBuffer, - int64_t AddrRelocAdjustment, bool IsLittleEndian); + int64_t AddrRelocAdjustment, bool IsLittleEndian, + SmallVectorImpl &References); /// Clone an attribute referencing another DIE and add /// it to \p Die. diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h index 714badfabf89c..4939a9ffef9a4 100644 --- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h +++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h @@ -196,9 +196,12 @@ class CompileUnit { /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p /// Attr. The attribute should be fixed up later to point to the absolute /// offset of \p Die in the debug_info section or to the canonical offset of - /// \p Ctxt if it is non-null. + /// \p Ctxt if it is non-null. When \p SectionRelative is false the fixup + /// instead uses the offset of \p Die relative to the start of \p RefUnit, + /// as needed by CU-relative DWARF expression references (DW_OP_call2/call4). LLVM_ABI void noteForwardReference(DIE *Die, const CompileUnit *RefUnit, - DeclContext *Ctxt, PatchLocation Attr); + DeclContext *Ctxt, PatchLocation Attr, + bool SectionRelative = true); /// Apply all fixups recorded by noteForwardReference(). LLVM_ABI void fixupForwardReferences(); @@ -297,8 +300,8 @@ class CompileUnit { /// The offsets for the attributes in this array couldn't be set while /// cloning because for cross-cu forward references the target DIE's offset /// isn't known you emit the reference attribute. - std::vector< - std::tuple> + std::vector> ForwardDIEReferences; /// The ranges in that map are the PC ranges for functions in this unit, diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index 222dc88098102..843b6616665af 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -630,6 +630,10 @@ unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE, case dwarf::DW_TAG_base_type: // DWARF Expressions may reference basic types, but scanning them // is expensive. Basic types are tiny, so just keep all of them. + case dwarf::DW_TAG_dwarf_procedure: + // DWARF procedures are the targets of DW_OP_call2/call4/call_ref. Those + // calls can appear in location lists, which the keep-analysis does not + // scan, so keep all procedures (they are small) to be safe. case dwarf::DW_TAG_imported_module: case dwarf::DW_TAG_imported_declaration: case dwarf::DW_TAG_imported_unit: @@ -738,6 +742,57 @@ void DWARFLinker::markODRCanonicalDie(const DWARFDie &Die, CompileUnit &CU) { Info.Ctxt->setHasCanonicalDIE(); } +/// Collect DIEs referenced by DWARF expression operands inside the location +/// expression \p Val and append them to \p ReferencedDIEs. DW_OP_call2/call4, +/// DW_OP_call_ref and DW_OP_implicit_pointer (and its GNU predecessor) all +/// carry a reference to another DIE; those targets must be kept so that +/// DIECloner::cloneExpression() can later remap the reference to its new +/// location instead of emitting a dangling offset. +static void collectExpressionReferencedDIEs( + const DWARFFormValue &Val, CompileUnit &CU, const UnitListTy &Units, + SmallVectorImpl> &ReferencedDIEs) { + std::optional> Expr = Val.getAsBlock(); + if (!Expr || Expr->empty()) + return; + + DWARFUnit &Unit = CU.getOrigUnit(); + DataExtractor Data(toStringRef(*Expr), Unit.getContext().isLittleEndian(), + Unit.getAddressByteSize()); + DWARFExpression Expression(Data, Unit.getAddressByteSize(), + Unit.getFormParams().Format); + + for (const DWARFExpression::Operation &Op : Expression) { + if (Op.isError()) + break; + + uint64_t RefOffset; + switch (Op.getCode()) { + case dwarf::DW_OP_call2: + case dwarf::DW_OP_call4: + // Compilation-unit-relative reference (DW_FORM_ref2/ref4-like). + RefOffset = Unit.getOffset() + Op.getRawOperand(0); + break; + case dwarf::DW_OP_call_ref: + case dwarf::DW_OP_implicit_pointer: + case dwarf::DW_OP_GNU_implicit_pointer: + // Section-relative reference (DW_FORM_ref_addr-like). + RefOffset = Op.getRawOperand(0); + break; + default: + continue; + } + + CompileUnit *RefUnit = getUnitForOffset(Units, RefOffset); + if (!RefUnit) + continue; + DWARFDie RefDie = RefUnit->getOrigUnit().getDIEForOffset(RefOffset); + if (!RefDie || RefDie.isNULL()) + continue; + RefUnit->getInfo(RefDie).Prune = false; + ReferencedDIEs.emplace_back(RefDie, *RefUnit); + } +} + /// Look at DIEs referenced by the given DIE and decide whether they should be /// kept. All DIEs referenced though attributes should be kept. void DWARFLinker::lookForRefDIEsToKeep( @@ -757,8 +812,18 @@ void DWARFLinker::lookForRefDIEsToKeep( DWARFFormValue Val(AttrSpec.Form); if (!Val.isFormClass(DWARFFormValue::FC_Reference) || AttrSpec.Attr == dwarf::DW_AT_sibling) { - DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, - Unit.getFormParams()); + // A location expression may reference other DIEs through DW_OP_call* and + // DW_OP_implicit_pointer; those targets must be kept too. Everything else + // is skipped. + if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) && + (Val.isFormClass(DWARFFormValue::FC_Block) || + Val.isFormClass(DWARFFormValue::FC_Exprloc))) { + Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit); + collectExpressionReferencedDIEs(Val, CU, Units, ReferencedDIEs); + } else { + DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, + Unit.getFormParams()); + } continue; } @@ -1156,11 +1221,50 @@ unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute( void DWARFLinker::DIECloner::cloneExpression( DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File, CompileUnit &Unit, SmallVectorImpl &OutputBuffer, - int64_t AddrRelocAdjustment, bool IsLittleEndian) { + int64_t AddrRelocAdjustment, bool IsLittleEndian, + SmallVectorImpl &References) { using Encoding = DWARFExpression::Operation::Encoding; uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize(); + // Record a reference to the DIE at original .debug_info offset \p AbsOffset + // and reserve \p Size zero bytes for the operand in the output buffer. The + // referenced DIE's clone may not exist yet (forward reference), so a + // placeholder is created if needed and the final offset is filled in by + // CompileUnit::fixupForwardReferences() once all DIEs are cloned. With + // \p SectionRelative the patched value is an absolute .debug_info offset + // (DW_FORM_ref_addr-like); otherwise it is relative to the start of the + // referenced unit (DW_FORM_ref2/ref4-like). + auto AppendDIEReference = [&](uint64_t AbsOffset, unsigned Size, + bool SectionRelative, const Twine &Kind) { + DIE *RefClone = nullptr; + CompileUnit *RefUnit = getUnitForOffset(CompileUnits, AbsOffset); + DWARFDie RefDie = + RefUnit ? RefUnit->getOrigUnit().getDIEForOffset(AbsOffset) : DWARFDie(); + if (!RefUnit || !RefDie || RefDie.isNULL()) { + Linker.reportWarning(Kind + " references an unknown DIE.", File); + } else { + CompileUnit::DIEInfo &Info = RefUnit->getInfo(RefDie); + if (!Info.Keep) { + Linker.reportWarning(Kind + " references a DIE that was not kept.", + File); + } else { + if (!Info.Clone) { + // Forward (or not-yet-cloned) reference: create the placeholder the + // real clone will reuse, exactly like cloneDieReferenceAttribute(). + Info.UnclonedReference = true; + Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag())); + } + RefClone = Info.Clone; + } + } + + if (RefClone) + References.push_back({OutputBuffer.size(), static_cast(Size), + RefClone, RefUnit, SectionRelative}); + OutputBuffer.append(Size, uint8_t(0)); + }; + uint64_t OpOffset = 0; for (auto &Op : Expression) { auto Desc = Op.getDescription(); @@ -1266,6 +1370,33 @@ void DWARFLinker::DIECloner::cloneExpression( } } else Linker.reportWarning("cannot read DW_OP_constx operand.", File); + } else if (Op.getCode() == dwarf::DW_OP_call_ref || + Op.getCode() == dwarf::DW_OP_implicit_pointer || + Op.getCode() == dwarf::DW_OP_GNU_implicit_pointer) { + // These take a .debug_info-section-relative reference to a DIE + // (interpreted like DW_FORM_ref_addr) as their first operand. + // DW_OP_implicit_pointer additionally carries a trailing SLEB128 byte + // offset, copied unmodified. The reference is recorded for deferred + // patching so it is correct even for forward references. The operand + // width matches what the decoder consumed (DWARF32 vs DWARF64). + unsigned RefSize = Op.getOperandEndOffset(0) - (OpOffset + 1); + OutputBuffer.push_back(Op.getCode()); + AppendDIEReference(Op.getRawOperand(0), RefSize, /*SectionRelative=*/true, + dwarf::OperationEncodingString(Op.getCode())); + StringRef Tail = + Data.getData().slice(Op.getOperandEndOffset(0), Op.getEndOffset()); + OutputBuffer.append(Tail.begin(), Tail.end()); + } else if (Op.getCode() == dwarf::DW_OP_call2 || + Op.getCode() == dwarf::DW_OP_call4) { + // DW_OP_call2/call4 take a compilation-unit-relative reference to a DIE + // (interpreted like DW_FORM_ref2/ref4), encoded as a fixed 2- or 4-byte + // value. Record it for deferred patching to the cloned DIE's new + // unit-relative offset. + unsigned RefSize = Op.getOperandEndOffset(0) - (OpOffset + 1); + uint64_t AbsOffset = Op.getRawOperand(0) + Unit.getOrigUnit().getOffset(); + OutputBuffer.push_back(Op.getCode()); + AppendDIEReference(AbsOffset, RefSize, /*SectionRelative=*/false, + dwarf::OperationEncodingString(Op.getCode())); } else { // Copy over everything else unmodified. StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset()); @@ -1297,6 +1428,7 @@ unsigned DWARFLinker::DIECloner::cloneBlockAttribute( // If the block is a DWARF Expression, clone it into the temporary // buffer using cloneExpression(), otherwise copy the data directly. SmallVector Buffer; + SmallVector References; ArrayRef Bytes = *Val.getAsBlock(); if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) && (Val.isFormClass(DWARFFormValue::FC_Block) || @@ -1306,12 +1438,32 @@ unsigned DWARFLinker::DIECloner::cloneBlockAttribute( DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(), OrigUnit.getFormParams().Format); cloneExpression(Data, Expr, File, Unit, Buffer, - Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian); + Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian, + References); Bytes = Buffer; } - for (auto Byte : Bytes) - Attr->addValue(DIEAlloc, static_cast(0), - dwarf::DW_FORM_data1, DIEInteger(Byte)); + // Emit the expression bytes as DIE values. DIE references collected by + // cloneExpression() are emitted as a single patchable integer and recorded + // for fixup once DIE offsets are final; all other bytes are emitted as + // individual DW_FORM_data1 values. + size_t NextRef = 0; + for (size_t I = 0, E = Bytes.size(); I != E;) { + if (NextRef < References.size() && References[NextRef].BufferOffset == I) { + const ExpressionDIEReference &Ref = References[NextRef++]; + dwarf::Form Form = Ref.Size == 2 ? dwarf::DW_FORM_data2 + : Ref.Size == 4 ? dwarf::DW_FORM_data4 + : dwarf::DW_FORM_data8; + auto Patch = Attr->addValue(DIEAlloc, static_cast(0), + Form, DIEInteger(0)); + Unit.noteForwardReference(Ref.RefDie, Ref.RefUnit, /*Ctxt=*/nullptr, Patch, + Ref.SectionRelative); + I += Ref.Size; + } else { + Attr->addValue(DIEAlloc, static_cast(0), + dwarf::DW_FORM_data1, DIEInteger(Bytes[I])); + ++I; + } + } // FIXME: If DIEBlock and DIELoc just reuses the Size field of // the DIE class, this "if" could be replaced by @@ -2748,11 +2900,34 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit(); DataExtractor Data(SrcBytes, IsLittleEndian, OrigUnit.getAddressByteSize()); + SmallVector References; cloneExpression(Data, DWARFExpression(Data, OrigUnit.getAddressByteSize(), OrigUnit.getFormParams().Format), File, *CurrentUnit, OutBytes, RelocAdjustment, - IsLittleEndian); + IsLittleEndian, References); + // Location lists are written straight into the section and cannot be + // patched afterwards, so resolve any DIE references now. The current + // unit (and all earlier units) have already been fully cloned, so the + // referenced DIE offsets are final. A reference into a not-yet-cloned + // later unit is left unresolved, with a warning. + for (const ExpressionDIEReference &Ref : References) { + uint64_t TargetOffset = Ref.RefDie->getOffset(); + if (!TargetOffset) { + Linker.reportWarning("DWARF expression in a location list " + "references a DIE in a later unit; reference " + "left unresolved.", + File); + continue; + } + if (Ref.SectionRelative) + TargetOffset += Ref.RefUnit->getStartOffset(); + for (unsigned I = 0; I != Ref.Size; ++I) { + unsigned Shift = IsLittleEndian ? I : Ref.Size - 1 - I; + OutBytes[Ref.BufferOffset + I] = + (TargetOffset >> (8 * Shift)) & 0xff; + } + } }; generateUnitLocations(*CurrentUnit, File, ProcessExpr); emitDebugAddrSection(*CurrentUnit, DwarfVersion); diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp index 027363aa394e0..44a9fe492cc44 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp @@ -136,8 +136,9 @@ uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) { /// Keep track of a forward cross-cu reference from this unit /// to \p Die that lives in \p RefUnit. void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit, - DeclContext *Ctxt, PatchLocation Attr) { - ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr); + DeclContext *Ctxt, PatchLocation Attr, + bool SectionRelative) { + ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr, SectionRelative); } void CompileUnit::fixupForwardReferences() { @@ -146,14 +147,20 @@ void CompileUnit::fixupForwardReferences() { const CompileUnit *RefUnit; PatchLocation Attr; DeclContext *Ctxt; - std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref; + bool SectionRelative; + std::tie(RefDie, RefUnit, Ctxt, Attr, SectionRelative) = Ref; if (Ctxt && Ctxt->hasCanonicalDIE()) { assert(Ctxt->getCanonicalDIEOffset() && "Canonical die offset is not set"); Attr.set(Ctxt->getCanonicalDIEOffset()); } else { assert(RefDie->getOffset() && "Referenced die offset is not set"); - Attr.set(RefDie->getOffset() + RefUnit->getStartOffset()); + // CU-relative references (DW_OP_call2/call4 in a DWARF expression) use + // the offset of the DIE within its unit; everything else is an absolute + // .debug_info offset. + Attr.set(SectionRelative + ? RefDie->getOffset() + RefUnit->getStartOffset() + : RefDie->getOffset()); } } } From 3c9ae2a0b4e44ad1ca686bd91ac2128ecc74b179 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Thu, 18 Jun 2026 16:27:43 +0100 Subject: [PATCH 8/9] dsymutil fixes (unsure) --- llvm/include/llvm/DWARFLinker/AddressesMap.h | 14 ++++ .../llvm/DWARFLinker/Classic/DWARFLinker.h | 9 ++- llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp | 32 +++++++- llvm/tools/dsymutil/DwarfLinkerForBinary.cpp | 78 +++++++++++++++++++ llvm/tools/dsymutil/DwarfLinkerForBinary.h | 22 +++++- 5 files changed, 151 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/DWARFLinker/AddressesMap.h b/llvm/include/llvm/DWARFLinker/AddressesMap.h index e2215c70dc34e..f1ca823f48274 100644 --- a/llvm/include/llvm/DWARFLinker/AddressesMap.h +++ b/llvm/include/llvm/DWARFLinker/AddressesMap.h @@ -55,6 +55,20 @@ class AddressesMap { virtual std::optional getSubprogramRelocAdjustment(const DWARFDie &DIE, bool Verbose) = 0; + /// Maps the object-file address \p ObjectAddress carried by a DW_OP_addr + /// operand inside a *location list* expression to its address in the linked + /// binary. Location-list sections (.debug_loc/.debug_loclists) are not + /// covered by applyValidRelocs (which only handles .debug_info), so the + /// address operands of their expressions have to be relocated explicitly + /// when the list is cloned. + /// \returns the linked address, or std::nullopt if \p ObjectAddress does not + /// correspond to a known live symbol. The default implementation performs no + /// mapping. + virtual std::optional + getExprOpAddressLinkedAddress(uint64_t ObjectAddress) { + return std::nullopt; + } + // Returns the library install name associated to the AddessesMap. virtual std::optional getLibraryInstallName() = 0; diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h index afc87fafe76ed..7581ad626a39b 100644 --- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h @@ -692,11 +692,18 @@ class LLVM_ABI DWARFLinker : public DWARFLinkerBase { /// Clone a DWARF expression that may be referencing another DIE. Any DIE /// references found in the expression are appended to \p References so the /// caller can emit them as patchable values. + /// + /// When \p RelocateExprLocAddr is true the expression is part of a location + /// list (.debug_loc/.debug_loclists), whose address operands are not + /// relocated by applyValidRelocs; any DW_OP_addr operand is then translated + /// to its linked address via the debug map. For exprlocs in .debug_info it + /// must be false, as those operands are relocated by applyValidRelocs. void cloneExpression(DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File, CompileUnit &Unit, SmallVectorImpl &OutputBuffer, int64_t AddrRelocAdjustment, bool IsLittleEndian, - SmallVectorImpl &References); + SmallVectorImpl &References, + bool RelocateExprLocAddr = false); /// Clone an attribute referencing another DIE and add /// it to \p Die. diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index 843b6616665af..df5e64e6589a2 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -1222,7 +1222,8 @@ void DWARFLinker::DIECloner::cloneExpression( DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File, CompileUnit &Unit, SmallVectorImpl &OutputBuffer, int64_t AddrRelocAdjustment, bool IsLittleEndian, - SmallVectorImpl &References) { + SmallVectorImpl &References, + bool RelocateExprLocAddr) { using Encoding = DWARFExpression::Operation::Encoding; uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize(); @@ -1370,6 +1371,32 @@ void DWARFLinker::DIECloner::cloneExpression( } } else Linker.reportWarning("cannot read DW_OP_constx operand.", File); + } else if (RelocateExprLocAddr && Op.getCode() == dwarf::DW_OP_addr) { + // A DW_OP_addr operand inside a location list carries the object-file + // address of a symbol (e.g. a statically-allocated OCaml closure). + // Location lists are not relocated by applyValidRelocs, so translate the + // operand to its linked address via the debug map here. (For exprlocs in + // .debug_info, RelocateExprLocAddr is false and the operand is relocated + // by applyValidRelocs instead, so this must not run for them.) + uint64_t ObjectAddress = Op.getRawOperand(0); + std::optional LinkedAddress; + if (File.Addresses) + LinkedAddress = + File.Addresses->getExprOpAddressLinkedAddress(ObjectAddress); + if (LinkedAddress) { + OutputBuffer.push_back(dwarf::DW_OP_addr); + uint64_t Address = *LinkedAddress; + if (IsLittleEndian != sys::IsLittleEndianHost) + sys::swapByteOrder(Address); + ArrayRef AddressBytes( + reinterpret_cast(&Address), OrigAddressByteSize); + OutputBuffer.append(AddressBytes.begin(), AddressBytes.end()); + } else { + // Unknown address; copy the operation unmodified rather than emit a + // bogus value. + StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset()); + OutputBuffer.append(Bytes.begin(), Bytes.end()); + } } else if (Op.getCode() == dwarf::DW_OP_call_ref || Op.getCode() == dwarf::DW_OP_implicit_pointer || Op.getCode() == dwarf::DW_OP_GNU_implicit_pointer) { @@ -2905,7 +2932,8 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( DWARFExpression(Data, OrigUnit.getAddressByteSize(), OrigUnit.getFormParams().Format), File, *CurrentUnit, OutBytes, RelocAdjustment, - IsLittleEndian, References); + IsLittleEndian, References, + /*RelocateExprLocAddr=*/true); // Location lists are written straight into the section and cannot be // patched afterwards, so resolve any DIE references now. The current // unit (and all earlier units) have already been fully cloned, so the diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index 138c5d0a513ed..b77128e9832fb 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -591,7 +591,54 @@ void DwarfLinkerForBinary::copySwiftReflectionMetadata( } } +void DwarfLinkerForBinary::buildMainBinarySymbolMap(const DebugMap &Map) { + if (Map.getBinaryPath().empty()) + return; + + auto ObjectEntry = BinHolder.getObjectEntry(Map.getBinaryPath()); + if (!ObjectEntry) { + consumeError(ObjectEntry.takeError()); + return; + } + + auto Object = + ObjectEntry->getObjectAs(Map.getTriple()); + if (!Object) { + consumeError(Object.takeError()); + return; + } + + for (const object::SymbolRef &Sym : Object->symbols()) { + Expected FlagsOrErr = Sym.getFlags(); + if (!FlagsOrErr) { + consumeError(FlagsOrErr.takeError()); + continue; + } + // Undefined symbols have no address in this binary. + if (*FlagsOrErr & object::SymbolRef::SF_Undefined) + continue; + + Expected NameOrErr = Sym.getName(); + if (!NameOrErr) { + consumeError(NameOrErr.takeError()); + continue; + } + if (NameOrErr->empty()) + continue; + + Expected AddrOrErr = Sym.getValue(); + if (!AddrOrErr) { + consumeError(AddrOrErr.takeError()); + continue; + } + + MainBinarySymbolAddresses[*NameOrErr] = *AddrOrErr; + } +} + bool DwarfLinkerForBinary::link(const DebugMap &Map) { + buildMainBinarySymbolMap(Map); + if (Options.DWARFLinkerType == DsymutilDWARFLinkerType::Parallel) return linkImpl(Map, Options.FileType); @@ -958,6 +1005,16 @@ void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO( if (const auto *Mapping = DMO.lookupSymbol(*SymbolName)) ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping->getKey(), Mapping->getValue()); + else if (auto GlobalIt = Linker.MainBinarySymbolAddresses.find(*SymbolName); + GlobalIt != Linker.MainBinarySymbolAddresses.end()) + // Cross-module reference: the target symbol is defined in another + // object and so is absent from this object's debug map. Resolve it via + // the linked binary's global symbol table instead. The addend (0 for a + // plain symbol reference) is preserved; [relocate] computes + // BinaryAddress + Addend. + ValidRelocs.emplace_back( + Offset64, RelocSize, Addend, *SymbolName, + SymbolMapping(std::nullopt, GlobalIt->getValue(), 0)); } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) { // Do not store the addend. The addend was the address of the symbol in // the object file, the address in the binary that is stored in the debug @@ -1117,6 +1174,27 @@ DwarfLinkerForBinary::AddressManager::getExprOpAddressRelocAdjustment( return std::nullopt; } +std::optional +DwarfLinkerForBinary::AddressManager::getExprOpAddressLinkedAddress( + uint64_t ObjectAddress) { + if (!DbgMapObj) + return std::nullopt; + // The debug map records, for each symbol, its address in the object file and + // in the linked binary. A DW_OP_addr operand inside a location list holds the + // object-file address of such a symbol (e.g. a statically-allocated OCaml + // closure), so translate it to the corresponding linked address. + if (const DebugMapObject::DebugMapEntry *Mapping = + DbgMapObj->lookupObjectAddress(ObjectAddress)) { + uint64_t SymObjectAddress = + Mapping->getValue().ObjectAddress + ? uint64_t(*Mapping->getValue().ObjectAddress) + : ObjectAddress; + return uint64_t(Mapping->getValue().BinaryAddress) + + (ObjectAddress - SymObjectAddress); + } + return std::nullopt; +} + std::optional DwarfLinkerForBinary::AddressManager::getSubprogramRelocAdjustment( const DWARFDie &DIE, bool Verbose) { diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h index 53f9e183ebe88..fc310b0e43cc5 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h @@ -121,6 +121,11 @@ class DwarfLinkerForBinary { std::optional LibInstallName; + /// The debug map object this manager was built from. Used to map the + /// object-file address of a DW_OP_addr operand inside a location list to + /// its linked address. Outlives this manager. + const DebugMapObject *DbgMapObj = nullptr; + /// Returns list of valid relocations from \p Relocs, /// between \p StartOffset and \p NextOffset. /// @@ -145,7 +150,8 @@ class DwarfLinkerForBinary { const DebugMapObject &DMO, std::shared_ptr DLBRM) : Linker(Linker), SrcFileName(DMO.getObjectFilename()), - DebugMapObjectType(MachO::N_OSO), DwarfLinkerRelocMap(DLBRM) { + DebugMapObjectType(MachO::N_OSO), DwarfLinkerRelocMap(DLBRM), + DbgMapObj(&DMO) { if (DMO.getRelocationMap().has_value()) { DebugMapObjectType = MachO::N_LIB; LibInstallName.emplace(DMO.getInstallName().value()); @@ -207,6 +213,9 @@ class DwarfLinkerForBinary { std::optional getSubprogramRelocAdjustment(const DWARFDie &DIE, bool Verbose) override; + std::optional + getExprOpAddressLinkedAddress(uint64_t ObjectAddress) override; + std::optional getLibraryInstallName() override; bool applyValidRelocs(MutableArrayRef Data, uint64_t BaseOffset, @@ -269,11 +278,22 @@ class DwarfLinkerForBinary { Error emitRelocations(const DebugMap &DM, std::vector &ObjectsForLinking); + /// Populate \p MainBinarySymbolAddresses from the linked binary's symbol + /// table, so that cross-module symbol references in debug info (whose target + /// symbol is absent from the referencing object's debug map) can still be + /// relocated. See \p AddressManager::findValidRelocsMachO. + void buildMainBinarySymbolMap(const DebugMap &Map); + raw_fd_ostream &OutFile; BinaryHolder &BinHolder; LinkOptions Options; std::mutex &ErrorHandlerMutex; + /// Maps a defined symbol name in the linked binary to its address. Used as a + /// fallback to resolve extern relocations against symbols defined in another + /// object (and hence missing from the current object's debug map). + StringMap MainBinarySymbolAddresses; + std::vector EmptyWarnings; /// A list of all .swiftinterface files referenced by the debug From 110d893710d5cdc26f15880555a82374161b70b5 Mon Sep 17 00:00:00 2001 From: Mark Shinwell Date: Mon, 6 Jul 2026 17:20:12 +0100 Subject: [PATCH 9/9] marshalling --- extern_standalone/extern_standalone.c | 1074 ++++++++++++++++ extern_standalone/extern_standalone.cpp | 1086 +++++++++++++++++ .../extern_standalone_check_big.ml | 12 + .../extern_standalone_check_readback.ml | 43 + .../extern_standalone_compare.py | 31 + .../extern_standalone_gen_expected.ml | 35 + .../extern_standalone_gen_expected_big.ml | 11 + extern_standalone/extern_standalone_test.c | 219 ++++ .../extern_standalone_test_big.c | 91 ++ .../lldb_external_printer/README.md | 82 ++ .../lldb_external_printer/build.sh | 11 + .../lldb_external_printer/printer | Bin 0 -> 1284840 bytes .../lldb_external_printer/printer.cmi | Bin 0 -> 925 bytes .../lldb_external_printer/printer.cmx | Bin 0 -> 1867 bytes .../lldb_external_printer/printer.ml | 50 + .../lldb_external_printer/printer.o | Bin 0 -> 6752 bytes .../lldb_external_printer/test_program | Bin 0 -> 1209824 bytes .../lldb_external_printer/test_program.cmi | Bin 0 -> 919 bytes .../lldb_external_printer/test_program.cmx | Bin 0 -> 2201 bytes .../lldb_external_printer/test_program.ml | 22 + .../lldb_external_printer/test_program.o | Bin 0 -> 4800 bytes .../lldb_external_printer/test_types.cmi | Bin 0 -> 1591 bytes .../lldb_external_printer/test_types.cmx | Bin 0 -> 2175 bytes .../lldb_external_printer/test_types.ml | 19 + .../lldb_external_printer/test_types.o | Bin 0 -> 4616 bytes lldb/include/lldb/Core/PluginManager.h | 8 + .../include/lldb/DataFormatters/TypeSummary.h | 61 +- lldb/include/lldb/Target/Language.h | 20 + lldb/source/API/SBTypeSummary.cpp | 3 + lldb/source/Commands/CommandObjectType.cpp | 63 + lldb/source/Commands/Options.td | 17 +- lldb/source/Core/PluginManager.cpp | 15 + lldb/source/DataFormatters/TypeSummary.cpp | 133 ++ .../Plugins/Language/OxCaml/CMakeLists.txt | 15 + .../OxCaml/LanguageOxCamlProperties.td | 15 + .../Language/OxCaml/OxCamlExternalPrinter.cpp | 137 +++ .../Language/OxCaml/OxCamlExternalPrinter.h | 58 + .../Language/OxCaml/OxCamlFormatters.cpp | 7 + .../Language/OxCaml/OxCamlLanguage.cpp | 55 +- .../Plugins/Language/OxCaml/OxCamlLanguage.h | 12 + .../Plugins/Language/OxCaml/OxCamlMarshal.cpp | 1048 ++++++++++++++++ .../Plugins/Language/OxCaml/OxCamlMarshal.h | 83 ++ lldb/source/Target/Language.cpp | 17 + 43 files changed, 4548 insertions(+), 5 deletions(-) create mode 100644 extern_standalone/extern_standalone.c create mode 100644 extern_standalone/extern_standalone.cpp create mode 100644 extern_standalone/extern_standalone_check_big.ml create mode 100644 extern_standalone/extern_standalone_check_readback.ml create mode 100644 extern_standalone/extern_standalone_compare.py create mode 100644 extern_standalone/extern_standalone_gen_expected.ml create mode 100644 extern_standalone/extern_standalone_gen_expected_big.ml create mode 100644 extern_standalone/extern_standalone_test.c create mode 100644 extern_standalone/extern_standalone_test_big.c create mode 100644 extern_standalone/lldb_external_printer/README.md create mode 100755 extern_standalone/lldb_external_printer/build.sh create mode 100755 extern_standalone/lldb_external_printer/printer create mode 100644 extern_standalone/lldb_external_printer/printer.cmi create mode 100644 extern_standalone/lldb_external_printer/printer.cmx create mode 100644 extern_standalone/lldb_external_printer/printer.ml create mode 100644 extern_standalone/lldb_external_printer/printer.o create mode 100755 extern_standalone/lldb_external_printer/test_program create mode 100644 extern_standalone/lldb_external_printer/test_program.cmi create mode 100644 extern_standalone/lldb_external_printer/test_program.cmx create mode 100644 extern_standalone/lldb_external_printer/test_program.ml create mode 100644 extern_standalone/lldb_external_printer/test_program.o create mode 100644 extern_standalone/lldb_external_printer/test_types.cmi create mode 100644 extern_standalone/lldb_external_printer/test_types.cmx create mode 100644 extern_standalone/lldb_external_printer/test_types.ml create mode 100644 extern_standalone/lldb_external_printer/test_types.o create mode 100644 lldb/source/Plugins/Language/OxCaml/LanguageOxCamlProperties.td create mode 100644 lldb/source/Plugins/Language/OxCaml/OxCamlExternalPrinter.cpp create mode 100644 lldb/source/Plugins/Language/OxCaml/OxCamlExternalPrinter.h create mode 100644 lldb/source/Plugins/Language/OxCaml/OxCamlMarshal.cpp create mode 100644 lldb/source/Plugins/Language/OxCaml/OxCamlMarshal.h diff --git a/extern_standalone/extern_standalone.c b/extern_standalone/extern_standalone.c new file mode 100644 index 0000000000000..467a6ce70c5c9 --- /dev/null +++ b/extern_standalone/extern_standalone.c @@ -0,0 +1,1074 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Standalone version of the marshalling ("extern") code from + runtime/extern.c (OxCaml runtime), i.e. the writer side of the Marshal + standard library module. All required definitions from the OCaml + runtime headers (mlvalues.h, gc.h, intext.h, misc.h, config.h/m.h) are + inlined below; only standard C headers are included, although a + compiler providing GCC-style builtins (GCC, Clang) is required. + + Values passed to the entry points must use the native-code OxCaml value + representation: 64-bit words, blocks preceded by a one-word header with + 8 reserved bits, 46 size bits, 2 colour bits and 8 tag bits. Header + colour bits are ignored. The reachable-words machinery that also lives + in runtime/extern.c is not included here. + + Differences from runtime/extern.c: + - 64-bit platforms only (an OxCaml requirement anyway). Support for + reading marshalled data back on 32-bit platforms has also been + removed: the COMPAT_32 flag is gone and the header field giving the + size in words when read on a 32-bit platform is written as 0 (64-bit + readers do not consult it). + - Compression (the COMPRESSED flag and the associated zstd hook) is + not supported. + - The caml_serialize_* functions for user-defined marshallers are + omitted. Consequently custom blocks (Custom_tag: Int32, Int64, + Nativeint, Bigarray, ...) cannot be marshalled, since their + serialization functions would have no way to write output; they are + rejected like other abstract values. + - Byte-swapping is done with the __builtin_bswap* builtins rather + than the runtime's hand-written shifts and byte copies. + - Errors are reported by returning a [caml_extern_error] code (with the + message available via [caml_extern_error_message]) instead of raising + OCaml exceptions. Internally this uses setjmp/longjmp, mirroring + the runtime's raise-through behaviour. + - Marshalling flags are not supported: sharing is always preserved, + as with an empty flag list passed to the Marshal functions. + - The only entry point is caml_output_value_to_malloc; the other + entry points of the runtime version (channel-based, to OCaml bytes, + or to a caller-supplied buffer) are omitted. + - Closures cannot be marshalled, since the runtime's code-fragment + table is not available here. Like continuations and custom, + abstract and mixed blocks, they cause + CAML_EXTERN_ERROR_INVALID_ARGUMENT to be returned. + - Memory is allocated with malloc/calloc/free instead of caml_stat_*. + - The extern state is a single global instead of being per-domain + (Caml_state->extern_state); this code is therefore not thread-safe. + - Function names are kept from the runtime, so this file cannot be + linked into a program that also links the OCaml runtime. */ + +#include +#include +#include +#include +#include +#include + +/* --------------------------------------------------------------------- */ +/* Platform configuration (from caml/config.h and the generated caml/m.h) */ + +#if UINTPTR_MAX != 0xFFFFFFFFFFFFFFFFull +#error "extern_standalone.c only supports 64-bit platforms" +#endif + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define ARCH_BIG_ENDIAN +#endif + +/* Doubles are assumed to be IEEE 754 and to have the same byte order as + integers. This holds on all supported 64-bit platforms; the runtime's + ARCH_FLOAT_ENDIANNESS mixed-endian configurations only existed on + 32-bit ARM. */ + +/* From caml/misc.h */ + +typedef intptr_t intnat; +typedef uintptr_t uintnat; +typedef size_t asize_t; + +static inline int caml_umul_overflow(uintnat a, uintnat b, uintnat * res) +{ + return __builtin_mul_overflow(a, b, res); +} + +/* --------------------------------------------------------------------- */ +/* Value representation (from caml/mlvalues.h) */ + +typedef intnat value; +typedef uintnat header_t; +typedef uintnat mlsize_t; +typedef unsigned int tag_t; + +#define Is_null(v) ((v) == 0) + +static inline int Is_long(value x) { + return ((x & 1) != 0 || x == 0); +} + +static inline int Is_block(value x) { + return ((x & 1) == 0 && x != 0); +} + +#define Long_val(x) ((x) >> 1) + +/* Headers: 8 reserved bits (nonzero only for mixed blocks), then 46 + size bits, 2 colour bits and 8 tag bits (see the top of this file). + In the runtime Hd_val is a relaxed atomic load. Make_header uses + the colour for out-of-heap blocks (NOT_MARKABLE, i.e. 3) and zero + reserved bits. */ + +#define Hd_val(val) (((volatile header_t *) (val)) [-1]) +#define Tag_hd(hd) ((tag_t) ((hd) & 0xFF)) +#define Wosize_hd(hd) \ + ((mlsize_t) (((hd) >> 10) & (((header_t) 1 << 46) - 1))) +#define Reserved_hd(hd) ((hd) >> 56) +#define Tag_val(val) Tag_hd(Hd_val(val)) +#define Wosize_val(val) Wosize_hd(Hd_val(val)) + +#define Make_header(wosize, tag) \ + (((header_t) (wosize) << 10) + (3 << 8) + (tag)) + +#define Field(x, i) (((volatile value *)(x)) [i]) /* Also an l-value. */ +#define Forward_val(v) Field(v, 0) +#define String_val(x) ((const char *) (x)) + +#define Forcing_tag 244 +#define Cont_tag 245 +#define Lazy_tag 246 +#define Closure_tag 247 +#define Infix_tag 249 +#define Forward_tag 250 +#define Abstract_tag 251 +#define String_tag 252 +#define Double_tag 253 +#define Double_array_tag 254 +#define Custom_tag 255 + +/* From caml/str.c */ + +static mlsize_t caml_string_length(value s) +{ + const char * p = (const char *) s; + mlsize_t temp = Wosize_val(s) * sizeof(value) - 1; + assert (p[temp - p[temp]] == 0); + return temp - p[temp]; +} + +/* --------------------------------------------------------------------- */ +/* The marshal format (from caml/intext.h) */ + +/* Magic number */ + +#define Intext_magic_number_small 0x8495A6BE +#define Intext_magic_number_big 0x8495A6BF + +/* Header format for the "small" model: 20 bytes + 0 "small" magic number + 4 length of marshaled data, in bytes + 8 number of shared blocks + 12 size in words when read on a 32-bit platform + (always 0 here: 32-bit readers are not supported) + 16 size in words when read on a 64-bit platform + The 4 numbers are 32 bits each, in big endian. + + Header format for the "big" model: 32 bytes + 0 "big" magic number + 4 four reserved bytes, currently set to 0 + 8 length of marshaled data, in bytes + 16 number of shared blocks + 24 size in words when read on a 64-bit platform + The 3 numbers are 64 bits each, in big endian. +*/ + +#define MAX_INTEXT_HEADER_SIZE 32 + +/* Codes for the compact format */ + +#define PREFIX_SMALL_BLOCK 0x80 +#define PREFIX_SMALL_INT 0x40 +#define PREFIX_SMALL_STRING 0x20 +#define CODE_INT8 0x0 +#define CODE_INT16 0x1 +#define CODE_INT32 0x2 +#define CODE_INT64 0x3 +#define CODE_SHARED8 0x4 +#define CODE_SHARED16 0x5 +#define CODE_SHARED32 0x6 +#define CODE_SHARED64 0x14 +#define CODE_BLOCK32 0x8 +#define CODE_BLOCK64 0x13 +#define CODE_STRING8 0x9 +#define CODE_STRING32 0xA +#define CODE_STRING64 0x15 +#define CODE_DOUBLE_BIG 0xB +#define CODE_DOUBLE_LITTLE 0xC +#define CODE_DOUBLE_ARRAY8_BIG 0xD +#define CODE_DOUBLE_ARRAY8_LITTLE 0xE +#define CODE_DOUBLE_ARRAY32_BIG 0xF +#define CODE_DOUBLE_ARRAY32_LITTLE 0x7 +#define CODE_DOUBLE_ARRAY64_BIG 0x16 +#define CODE_DOUBLE_ARRAY64_LITTLE 0x17 +#define CODE_CODEPOINTER 0x10 +#define CODE_INFIXPOINTER 0x11 +#define OLD_CODE_CUSTOM 0x12 // no longer supported +#define CODE_CUSTOM_LEN 0x18 +#define CODE_CUSTOM_FIXED 0x19 + +#define CODE_UNBOXED_INT64 0x1a // Jane Street extensions +#define CODE_NULL 0x1f + +#ifdef ARCH_BIG_ENDIAN +#define CODE_DOUBLE_NATIVE CODE_DOUBLE_BIG +#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_BIG +#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_BIG +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_BIG +#else +#define CODE_DOUBLE_NATIVE CODE_DOUBLE_LITTLE +#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_LITTLE +#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_LITTLE +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_LITTLE +#endif + +/* Size-ing data structures for extern. Chosen so that + sizeof(struct output_block) is slightly below 8Kb. */ + +#define SIZE_EXTERN_OUTPUT_BLOCK 8100 + +struct caml_output_block { + struct caml_output_block * next; + char * end; + char data[SIZE_EXTERN_OUTPUT_BLOCK]; +}; + +/* --------------------------------------------------------------------- */ +/* Public interface of this file */ + +/* Errors. The runtime raises Out_of_memory / Invalid_argument; here + the error is returned and the corresponding message (a string + literal) is available via [caml_extern_error_message]. */ + +typedef enum { + CAML_EXTERN_OK = 0, + CAML_EXTERN_ERROR_OUT_OF_MEMORY = 1, + CAML_EXTERN_ERROR_INVALID_ARGUMENT = 2 +} caml_extern_error; + +const char * caml_extern_error_message(void); + +caml_extern_error caml_output_value_to_malloc + (value v, /*out*/ char ** buf, /*out*/ intnat * len); + /* Marshal [v] to a buffer allocated with malloc. On success returns + CAML_EXTERN_OK and stores the buffer and its length in bytes in + [*buf] and [*len]; the caller is responsible for freeing the + buffer. On failure returns an error code and writes neither + [*buf] nor [*len]. Sharing within [v] is always preserved, as + with an empty flag list in the runtime. Values with no external + representation (closures, continuations, custom / abstract / mixed + blocks) yield CAML_EXTERN_ERROR_INVALID_ARGUMENT. */ + +void caml_free_extern_state (void); + /* Free the internal state (lazily allocated on first use and then + reused across calls). */ + +/* --------------------------------------------------------------------- */ +/* The marshaller itself (from runtime/extern.c) */ + +/* Stack for pending values to marshal */ + +#define EXTERN_STACK_INIT_SIZE 256 +#define EXTERN_STACK_MAX_SIZE (1024*1024*100) + +struct extern_item { volatile value * v; mlsize_t count; }; + +/* Hash table to record already-marshaled objects and their positions */ + +struct object_position { value obj; uintnat pos; }; + +/* The hash table uses open addressing, linear probing, and a redundant + representation: + - a bitvector [present] records which entries of the table are occupied; + - an array [entries] records (object, position) pairs for the entries + that are occupied. + The bitvector is much smaller than the array (1/128th on 64-bit + platforms, 1/64th on 32-bit platforms), so it has better locality, + making it faster to determine that an object is not in the table. + Also, it makes it faster to empty or initialize a table: only the + [present] bitvector needs to be filled with zeros, the [entries] + array can be left uninitialized. +*/ + +struct position_table { + int shift; + mlsize_t size; /* size == 1 << (wordsize - shift) */ + mlsize_t mask; /* mask == size - 1 */ + mlsize_t threshold; /* threshold == a fixed fraction of size */ + uintnat * present; /* [Bitvect_size(size)] */ + struct object_position * entries; /* [size] */ +}; + +#define Bits_word (8 * sizeof(uintnat)) +#define Bitvect_size(n) (((n) + Bits_word - 1) / Bits_word) + +#define POS_TABLE_INIT_SIZE_LOG2 8 +#define POS_TABLE_INIT_SIZE (1 << POS_TABLE_INIT_SIZE_LOG2) + +struct caml_extern_state { + + uintnat obj_counter; /* Number of objects emitted so far */ + uintnat size_64; /* Size in words of 64-bit block for struct. */ + + /* Return point for error reporting (replaces raising OCaml + exceptions in the runtime version) */ + jmp_buf error_return; + + /* Stack for pending value to marshal */ + struct extern_item extern_stack_init[EXTERN_STACK_INIT_SIZE]; + struct extern_item * extern_stack; + struct extern_item * extern_stack_limit; + + /* Hash table to record already marshalled objects */ + uintnat pos_table_present_init[Bitvect_size(POS_TABLE_INIT_SIZE)]; + struct object_position pos_table_entries_init[POS_TABLE_INIT_SIZE]; + struct position_table pos_table; + + /* To buffer the output */ + + char * extern_ptr; + char * extern_limit; + + struct caml_output_block * extern_output_first; + struct caml_output_block * extern_output_block; +}; + +/* The extern state. The runtime keeps this per-domain in + Caml_state->extern_state; here it is a single global. */ + +static struct caml_extern_state * extern_state = NULL; + +/* Error reporting, replacing the exception raising of the runtime + version. All messages are string literals. */ + +static caml_extern_error extern_error_code = CAML_EXTERN_OK; +static const char * extern_error_msg = NULL; + +const char * caml_extern_error_message(void) +{ + return extern_error_msg; +} + +_Noreturn static void extern_raise(struct caml_extern_state* s, + caml_extern_error code, const char * msg) +{ + extern_error_code = code; + extern_error_msg = msg; + longjmp(s->error_return, 1); +} + +static void init_extern_stack(struct caml_extern_state* s) +{ + /* (Re)initialize the globals for next time around */ + s->extern_stack = s->extern_stack_init; + s->extern_stack_limit = s->extern_stack + EXTERN_STACK_INIT_SIZE; +} + +/* Returns NULL on out-of-memory (the runtime version raises). */ +static struct caml_extern_state* init_extern_state (void) +{ + struct caml_extern_state* s; + + if (extern_state != NULL) + return extern_state; + + s = malloc(sizeof(struct caml_extern_state)); + if (s == NULL) return NULL; + + s->obj_counter = 0; + s->size_64 = 0; + init_extern_stack(s); + + extern_state = s; + return s; +} + +void caml_free_extern_state (void) +{ + if (extern_state != NULL) { + free(extern_state); + extern_state = NULL; + } +} + +/* Forward declarations */ + +_Noreturn static void extern_out_of_memory(struct caml_extern_state* s); + +_Noreturn static +void extern_invalid_argument(struct caml_extern_state* s, + const char *msg); + +_Noreturn static void extern_stack_overflow(struct caml_extern_state* s); + +static void free_extern_output(struct caml_extern_state* s); + +static void extern_free_stack(struct caml_extern_state* s) +{ + /* Free the extern stack if needed */ + if (s->extern_stack != s->extern_stack_init) { + free(s->extern_stack); + init_extern_stack(s); + } +} + +static struct extern_item * extern_resize_stack(struct caml_extern_state* s, + const struct extern_item * sp) +{ + asize_t newsize = 2 * (s->extern_stack_limit - s->extern_stack); + asize_t sp_offset = sp - s->extern_stack; + struct extern_item * newstack; + + if (newsize >= EXTERN_STACK_MAX_SIZE) extern_stack_overflow(s); + newstack = calloc(newsize, sizeof(struct extern_item)); + if (newstack == NULL) extern_stack_overflow(s); + + /* Copy items from the old stack to the new stack */ + memcpy (newstack, s->extern_stack, + sizeof(struct extern_item) * sp_offset); + + /* Free the old stack if it is not the initial stack */ + if (s->extern_stack != s->extern_stack_init) + free(s->extern_stack); + + s->extern_stack = newstack; + s->extern_stack_limit = newstack + newsize; + return newstack + sp_offset; +} + +/* Multiplicative Fibonacci hashing + (Knuth, TAOCP vol 3, section 6.4, page 518). + HASH_FACTOR is (sqrt(5) - 1) / 2 * 2^wordsize. */ +#define HASH_FACTOR 11400714819323198486UL +#define Hash(v,shift) (((uintnat)(v) * HASH_FACTOR) >> (shift)) + +/* When the table becomes 2/3 full, its size is increased. */ +#define Threshold(sz) (((sz) * 2) / 3) + +/* Initialize the position table */ + +static void extern_init_position_table(struct caml_extern_state* s) +{ + s->pos_table.size = POS_TABLE_INIT_SIZE; + s->pos_table.shift = 8 * sizeof(value) - POS_TABLE_INIT_SIZE_LOG2; + s->pos_table.mask = POS_TABLE_INIT_SIZE - 1; + s->pos_table.threshold = Threshold(POS_TABLE_INIT_SIZE); + s->pos_table.present = s->pos_table_present_init; + s->pos_table.entries = s->pos_table_entries_init; + memset(s->pos_table_present_init, 0, + Bitvect_size(POS_TABLE_INIT_SIZE) * sizeof(uintnat)); +} + +/* Free the position table */ + +static void extern_free_position_table(struct caml_extern_state* s) +{ + if (s->pos_table.present != s->pos_table_present_init) { + free(s->pos_table.present); + free(s->pos_table.entries); + /* Protect against repeated calls to extern_free_position_table */ + s->pos_table.present = s->pos_table_present_init; + s->pos_table.entries = s->pos_table_entries_init; + } +} + +/* Accessing bitvectors */ + +static inline uintnat bitvect_test(uintnat * bv, uintnat i) +{ + return bv[i / Bits_word] & ((uintnat) 1 << (i & (Bits_word - 1))); +} + +static inline void bitvect_set(uintnat * bv, uintnat i) +{ + bv[i / Bits_word] |= ((uintnat) 1 << (i & (Bits_word - 1))); +} + +/* Grow the position table */ + +static void extern_resize_position_table(struct caml_extern_state *s) +{ + mlsize_t new_size, new_byte_size; + int new_shift; + uintnat * new_present; + struct object_position * new_entries; + uintnat h; + struct position_table old = s->pos_table; + + /* Grow the table quickly (x 8) up to 10^6 entries, + more slowly (x 2) afterwards. */ + if (old.size < 1000000) { + new_size = 8 * old.size; + new_shift = old.shift - 3; + } else { + new_size = 2 * old.size; + new_shift = old.shift - 1; + } + if (new_size == 0 + || caml_umul_overflow(new_size, sizeof(struct object_position), + &new_byte_size)) + extern_out_of_memory(s); + new_entries = malloc(new_byte_size); + if (new_entries == NULL) extern_out_of_memory(s); + new_present = + calloc(Bitvect_size(new_size), sizeof(uintnat)); + if (new_present == NULL) { + free(new_entries); + extern_out_of_memory(s); + } + s->pos_table.size = new_size; + s->pos_table.shift = new_shift; + s->pos_table.mask = new_size - 1; + s->pos_table.threshold = Threshold(new_size); + s->pos_table.present = new_present; + s->pos_table.entries = new_entries; + + /* Insert every entry of the old table in the new table */ + for (uintnat i = 0; i < old.size; i++) { + if (! bitvect_test(old.present, i)) continue; + h = Hash(old.entries[i].obj, s->pos_table.shift); + while (bitvect_test(new_present, h)) { + h = (h + 1) & s->pos_table.mask; + } + bitvect_set(new_present, h); + new_entries[h] = old.entries[i]; + } + + /* Free the old tables if they are not the initial ones */ + if (old.present != s->pos_table_present_init) { + free(old.present); + free(old.entries); + } +} + +/* Determine whether the given object [obj] is in the hash table. + If so, set [*pos_out] to its position in the output and return 1. + If not, return 0. + Either way, set [*h_out] to the hash value appropriate for + [extern_record_location]. */ +static inline int extern_lookup_position(struct caml_extern_state *s, value obj, + uintnat * pos_out, uintnat * h_out) +{ + uintnat h = Hash(obj, s->pos_table.shift); + while (1) { + if (! bitvect_test(s->pos_table.present, h)) { + *h_out = h; + return 0; + } + if (s->pos_table.entries[h].obj == obj) { + *h_out = h; + *pos_out = s->pos_table.entries[h].pos; + return 1; + } + h = (h + 1) & s->pos_table.mask; + } +} + +/* Record the output position for the given object [obj]. */ +/* The [h] parameter is the index in the hash table where the object + must be inserted. It was determined during lookup. */ +static void extern_record_location(struct caml_extern_state* s, + value obj, uintnat h) +{ + bitvect_set(s->pos_table.present, h); + s->pos_table.entries[h].obj = obj; + s->pos_table.entries[h].pos = s->obj_counter; + s->obj_counter++; + if (s->obj_counter >= s->pos_table.threshold) + extern_resize_position_table(s); +} + +/* To buffer the output */ + +static void init_extern_output(struct caml_extern_state* s) +{ + s->extern_output_first = + malloc(sizeof(struct caml_output_block)); + if (s->extern_output_first == NULL) + extern_raise(s, CAML_EXTERN_ERROR_OUT_OF_MEMORY, + "output_value: out of memory"); + s->extern_output_block = s->extern_output_first; + s->extern_output_block->next = NULL; + s->extern_ptr = s->extern_output_block->data; + s->extern_limit = s->extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK; +} + +static void close_extern_output(struct caml_extern_state* s) +{ + s->extern_output_block->end = s->extern_ptr; +} + +static void free_extern_output(struct caml_extern_state* s) +{ + for (struct caml_output_block *blk = s->extern_output_first, *nextblk; + blk != NULL; + blk = nextblk) { + nextblk = blk->next; + free(blk); + } + s->extern_output_first = NULL; + extern_free_stack(s); + extern_free_position_table(s); +} + +static void grow_extern_output(struct caml_extern_state *s, intnat required) +{ + struct caml_output_block * blk; + intnat extra; + + s->extern_output_block->end = s->extern_ptr; + if (required <= SIZE_EXTERN_OUTPUT_BLOCK / 2) + extra = 0; + else + extra = required; + blk = malloc(sizeof(struct caml_output_block) + extra); + if (blk == NULL) extern_out_of_memory(s); + s->extern_output_block->next = blk; + s->extern_output_block = blk; + s->extern_output_block->next = NULL; + s->extern_ptr = s->extern_output_block->data; + s->extern_limit = + s->extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK + extra; +} + +static intnat extern_output_length(struct caml_extern_state* s) +{ + struct caml_output_block * blk; + intnat len; + + for (len = 0, blk = s->extern_output_first; blk != NULL; blk = blk->next) + len += blk->end - blk->data; + return len; +} + +/* Error raising, with cleanup */ + +static void extern_out_of_memory(struct caml_extern_state* s) +{ + free_extern_output(s); + extern_raise(s, CAML_EXTERN_ERROR_OUT_OF_MEMORY, + "output_value: out of memory"); +} + +static void extern_invalid_argument(struct caml_extern_state *s, + const char *msg) +{ + free_extern_output(s); + extern_raise(s, CAML_EXTERN_ERROR_INVALID_ARGUMENT, msg); +} + +static void extern_stack_overflow(struct caml_extern_state* s) +{ + free_extern_output(s); + extern_raise(s, CAML_EXTERN_ERROR_OUT_OF_MEMORY, + "output_value: stack overflow"); +} + +/* Conversion to big-endian */ + +#ifdef ARCH_BIG_ENDIAN +#define Htobe16(x) ((uint16_t) (x)) +#define Htobe32(x) ((uint32_t) (x)) +#define Htobe64(x) ((uint64_t) (x)) +#else +#define Htobe16(x) __builtin_bswap16((uint16_t) (x)) +#define Htobe32(x) __builtin_bswap32((uint32_t) (x)) +#define Htobe64(x) __builtin_bswap64((uint64_t) (x)) +#endif + +static inline void store16(char * dst, int n) +{ + uint16_t u = Htobe16(n); + memcpy(dst, &u, 2); +} + +static inline void store32(char * dst, intnat n) +{ + uint32_t u = Htobe32(n); + memcpy(dst, &u, 4); +} + +static inline void store64(char * dst, int64_t n) +{ + uint64_t u = Htobe64(n); + memcpy(dst, &u, 8); +} + +/* Write characters, integers, and blocks in the output buffer */ + +static inline void writebyte(struct caml_extern_state* s, int c) +{ + if (s->extern_ptr >= s->extern_limit) grow_extern_output(s, 1); + *s->extern_ptr++ = c; +} + +static void writeblock(struct caml_extern_state* s, const char * data, + intnat len) +{ + if (s->extern_ptr + len > s->extern_limit) grow_extern_output(s, len); + memcpy(s->extern_ptr, data, len); + s->extern_ptr += len; +} + +static inline void writeblock_float8(struct caml_extern_state* s, + const double * data, intnat ndoubles) +{ + /* Doubles have the same byte order as integers, so they can be + written natively; the CODE_DOUBLE*_NATIVE codes record which + endianness that is. (The runtime additionally handles mixed-endian + doubles here, which only exist on 32-bit ARM.) */ + writeblock(s, (const char *) data, ndoubles * 8); +} + +static void writecode8(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 2 > s->extern_limit) grow_extern_output(s, 2); + s->extern_ptr[0] = code; + s->extern_ptr[1] = val; + s->extern_ptr += 2; +} + +static void writecode16(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 3 > s->extern_limit) grow_extern_output(s, 3); + s->extern_ptr[0] = code; + store16(s->extern_ptr + 1, (int) val); + s->extern_ptr += 3; +} + +static void writecode32(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 5 > s->extern_limit) grow_extern_output(s, 5); + s->extern_ptr[0] = code; + store32(s->extern_ptr + 1, val); + s->extern_ptr += 5; +} + +static void writecode64(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 9 > s->extern_limit) grow_extern_output(s, 9); + s->extern_ptr[0] = code; + store64(s->extern_ptr + 1, val); + s->extern_ptr += 9; +} + +/* Marshaling integers */ + +static inline void extern_int(struct caml_extern_state* s, intnat n) +{ + if (n >= 0 && n < 0x40) { + writebyte(s, PREFIX_SMALL_INT + n); + } else if (n >= -(1 << 7) && n < (1 << 7)) { + writecode8(s, CODE_INT8, n); + } else if (n >= -(1 << 15) && n < (1 << 15)) { + writecode16(s, CODE_INT16, n); + } else if (n < -((intnat)1 << 30) || n >= ((intnat)1 << 30)) { + writecode64(s, CODE_INT64, n); + } else { + writecode32(s, CODE_INT32, n); + } +} + +static inline void extern_null(struct caml_extern_state* s) +{ + writecode8(s, CODE_NULL, 0); +} + +/* Marshaling references to previously-marshaled blocks */ + +static inline void extern_shared_reference(struct caml_extern_state* s, + uintnat d) +{ + if (d < 0x100) { + writecode8(s, CODE_SHARED8, d); + } else if (d < 0x10000) { + writecode16(s, CODE_SHARED16, d); + } else if (d >= (uintnat)1 << 32) { + writecode64(s, CODE_SHARED64, d); + } else { + writecode32(s, CODE_SHARED32, d); + } +} + +/* Marshaling block headers */ + +static inline void extern_header(struct caml_extern_state* s, + mlsize_t sz, tag_t tag) +{ + if (tag < 16 && sz < 8) { + writebyte(s, PREFIX_SMALL_BLOCK + tag + (sz << 4)); + } else { + header_t hd = Make_header(sz, tag); + if (hd < (uintnat)1 << 32) + writecode32(s, CODE_BLOCK32, hd); + else + writecode64(s, CODE_BLOCK64, hd); + } +} + +/* Marshaling strings */ + +static inline void extern_string(struct caml_extern_state *s, + value v, mlsize_t len) +{ + if (len < 0x20) { + writebyte(s, PREFIX_SMALL_STRING + len); + } else if (len < 0x100) { + writecode8(s, CODE_STRING8, len); + } else { + if (len < (uintnat)1 << 32) + writecode32(s, CODE_STRING32, len); + else + writecode64(s, CODE_STRING64, len); + } + writeblock(s, String_val(v), len); +} + +/* Marshaling FP numbers */ + +static inline void extern_double(struct caml_extern_state* s, value v) +{ + writebyte(s, CODE_DOUBLE_NATIVE); + writeblock_float8(s, (double *) v, 1); +} + +/* Marshaling FP arrays */ + +static inline void extern_double_array(struct caml_extern_state* s, + value v, mlsize_t nfloats) +{ + if (nfloats < 0x100) { + writecode8(s, CODE_DOUBLE_ARRAY8_NATIVE, nfloats); + } else { + if (nfloats < (uintnat) 1 << 32) + writecode32(s, CODE_DOUBLE_ARRAY32_NATIVE, nfloats); + else + writecode64(s, CODE_DOUBLE_ARRAY64_NATIVE, nfloats); + } + writeblock_float8(s, (double *) v, nfloats); +} + +/* Marshal the given value in the output buffer */ + +static void extern_rec(struct caml_extern_state* s, value v) +{ + struct extern_item * sp; + uintnat h = 0; + uintnat pos = 0; + + /* for Double_tag and Double_array_tag */ + static_assert(sizeof(double) == 8, ""); + + extern_init_position_table(s); + sp = s->extern_stack; + + while(1) { + if (Is_null(v)) { + extern_null(s); + } else if (Is_long(v)) { + extern_int(s, Long_val(v)); + } + else { + header_t hd = Hd_val(v); + tag_t tag = Tag_hd(hd); + mlsize_t sz = Wosize_hd(hd); + if (Reserved_hd(hd) != 0) { + /* Nonzero reserved header bits indicate a mixed block. */ + extern_invalid_argument(s, "output_value: mixed block"); + break; + } + + if (tag == Forward_tag) { + value f = Forward_val (v); + if (Is_block (f) + && ( Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag + || Tag_val (f) == Forcing_tag + /* Double_tag check because of flat float arrays */ + || Tag_val (f) == Double_tag + )){ + /* Do not short-circuit the pointer. */ + }else{ + v = f; + continue; + } + } + /* Atoms are treated specially for two reasons: they are not allocated + in the externed block, and they are automatically shared. */ + if (sz == 0) { + extern_header(s, 0, tag); + goto next_item; + } + /* Check if object already seen */ + if (extern_lookup_position(s, v, &pos, &h)) { + extern_shared_reference(s, s->obj_counter - pos); + goto next_item; + } + /* Output the contents of the object */ + switch(tag) { + case String_tag: { + mlsize_t len = caml_string_length(v); + extern_string(s, v, len); + s->size_64 += 1 + (len + 8) / 8; + extern_record_location(s, v, h); + break; + } + case Double_tag: { + extern_double(s, v); + s->size_64 += 1 + 1; + extern_record_location(s, v, h); + break; + } + case Double_array_tag: { + /* sizeof(double) == sizeof(value), per the static_assert above */ + mlsize_t nfloats = Wosize_val(v); + extern_double_array(s, v, nfloats); + s->size_64 += 1 + nfloats; + extern_record_location(s, v, h); + break; + } + case Abstract_tag: + extern_invalid_argument(s, "output_value: abstract value (Abstract)"); + break; + case Infix_tag: + /* An infix pointer into a closure block; closures cannot be + marshalled (see Closure_tag below). */ + extern_invalid_argument(s, "output_value: functional value"); + break; + case Custom_tag: + /* Custom blocks (Int32, Int64, Nativeint, Bigarray, ...) cannot + be marshalled here: their serialization functions would need the + caml_serialize_* entry points, which are not provided. */ + extern_invalid_argument(s, "output_value: abstract value (Custom)"); + break; + case Closure_tag: + /* The runtime's code-fragment table is not available here, so + code pointers, and hence closures, cannot be marshalled. */ + extern_invalid_argument(s, "output_value: functional value"); + break; + case Cont_tag: + extern_invalid_argument(s, "output_value: continuation value"); + break; + default: { + extern_header(s, sz, tag); + s->size_64 += 1 + sz; + extern_record_location(s, v, h); + /* Remember that we still have to serialize fields 1 ... sz - 1 */ + if (sz > 1) { + sp++; + if (sp >= s->extern_stack_limit) + sp = extern_resize_stack(s, sp); + sp->v = &Field(v, 1); + sp->count = sz - 1; + } + /* Continue serialization with the first field */ + v = Field(v, 0); + continue; + } + } + } + next_item: + /* Pop one more item to marshal, if any */ + if (sp == s->extern_stack) { + /* We are done. Cleanup the stack and leave the function */ + extern_free_stack(s); + extern_free_position_table(s); + return; + } + v = *((sp->v)++); + if (--(sp->count) == 0) sp--; + } + /* Never reached as function leaves with return */ +} + +static intnat extern_value(struct caml_extern_state* s, value v, + /*out*/ char header[MAX_INTEXT_HEADER_SIZE], + /*out*/ int * header_len) +{ + intnat res_len; + /* Initializations */ + s->obj_counter = 0; + s->size_64 = 0; + /* Marshal the object */ + extern_rec(s, v); + /* Record end of output */ + close_extern_output(s); + /* Write the header */ + res_len = extern_output_length(s); + if (res_len >= ((intnat)1 << 32) || s->size_64 >= ((intnat)1 << 32)) { + /* The object is too big for the small header format. + Use the big header. */ + store32(header, Intext_magic_number_big); + store32(header + 4, 0); + store64(header + 8, res_len); + store64(header + 16, s->obj_counter); + store64(header + 24, s->size_64); + *header_len = 32; + return res_len; + } + /* Use the small header format. The field at offset 12 is the size in + words when read on a 32-bit platform; 32-bit readers are not + supported, so 0 is written instead. */ + store32(header, Intext_magic_number_small); + store32(header + 4, res_len); + store32(header + 8, s->obj_counter); + store32(header + 12, 0); + store32(header + 16, s->size_64); + *header_len = 20; + return res_len; +} + +/* The entry point */ + +caml_extern_error +caml_output_value_to_malloc(value v, + /*out*/ char ** buf, + /*out*/ intnat * len) +{ + char header[MAX_INTEXT_HEADER_SIZE]; + int header_len; + intnat data_len; + char * res; + struct caml_extern_state* s = init_extern_state (); + + if (s == NULL) { + extern_error_code = CAML_EXTERN_ERROR_OUT_OF_MEMORY; + extern_error_msg = "output_value: out of memory"; + return extern_error_code; + } + extern_error_msg = NULL; + if (setjmp(s->error_return) != 0) return extern_error_code; + + init_extern_output(s); + data_len = extern_value(s, v, header, &header_len); + res = malloc(header_len + data_len); + if (res == NULL) extern_out_of_memory(s); + *buf = res; + *len = header_len + data_len; + memcpy(res, header, header_len); + res += header_len; + for (struct caml_output_block *blk = s->extern_output_first, *nextblk; + blk != NULL; + blk = nextblk) { + intnat n = blk->end - blk->data; + memcpy(res, blk->data, n); + res += n; + nextblk = blk->next; + free(blk); + } + return CAML_EXTERN_OK; +} diff --git a/extern_standalone/extern_standalone.cpp b/extern_standalone/extern_standalone.cpp new file mode 100644 index 0000000000000..cdef3d61364dc --- /dev/null +++ b/extern_standalone/extern_standalone.cpp @@ -0,0 +1,1086 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Standalone version of the marshalling ("extern") code from + runtime/extern.c (OxCaml runtime), i.e. the writer side of the Marshal + standard library module. All required definitions from the OCaml + runtime headers (mlvalues.h, gc.h, intext.h, misc.h, config.h/m.h) are + inlined below; only standard C headers are included, although a + compiler providing GCC-style builtins (GCC, Clang) is required. + + This file is the C++ counterpart of extern_standalone.c. It differs + only in using [[noreturn]] instead of [[noreturn]], casting the results + of malloc/calloc, and giving the public interface extern "C" linkage + (so that this build can be linked with C code such as + extern_standalone_test.c). + + Values passed to the entry points must use the native-code OxCaml value + representation: 64-bit words, blocks preceded by a one-word header with + 8 reserved bits, 46 size bits, 2 colour bits and 8 tag bits. Header + colour bits are ignored. The reachable-words machinery that also lives + in runtime/extern.c is not included here. + + Differences from runtime/extern.c: + - 64-bit platforms only (an OxCaml requirement anyway). Support for + reading marshalled data back on 32-bit platforms has also been + removed: the COMPAT_32 flag is gone and the header field giving the + size in words when read on a 32-bit platform is written as 0 (64-bit + readers do not consult it). + - Compression (the COMPRESSED flag and the associated zstd hook) is + not supported. + - The caml_serialize_* functions for user-defined marshallers are + omitted. Consequently custom blocks (Custom_tag: Int32, Int64, + Nativeint, Bigarray, ...) cannot be marshalled, since their + serialization functions would have no way to write output; they are + rejected like other abstract values. + - Byte-swapping is done with the __builtin_bswap* builtins rather + than the runtime's hand-written shifts and byte copies. + - Errors are reported by returning a [caml_extern_error] code (with the + message available via [caml_extern_error_message]) instead of raising + OCaml exceptions. Internally this uses setjmp/longjmp, mirroring + the runtime's raise-through behaviour. + - Marshalling flags are not supported: sharing is always preserved, + as with an empty flag list passed to the Marshal functions. + - The only entry point is caml_output_value_to_malloc; the other + entry points of the runtime version (channel-based, to OCaml bytes, + or to a caller-supplied buffer) are omitted. + - Closures cannot be marshalled, since the runtime's code-fragment + table is not available here. Like continuations and custom, + abstract and mixed blocks, they cause + CAML_EXTERN_ERROR_INVALID_ARGUMENT to be returned. + - Memory is allocated with malloc/calloc/free instead of caml_stat_*. + - The extern state is a single global instead of being per-domain + (Caml_state->extern_state); this code is therefore not thread-safe. + - Function names are kept from the runtime, so this file cannot be + linked into a program that also links the OCaml runtime. */ + +#include +#include +#include +#include +#include +#include + +/* --------------------------------------------------------------------- */ +/* Platform configuration (from caml/config.h and the generated caml/m.h) */ + +#if UINTPTR_MAX != 0xFFFFFFFFFFFFFFFFull +#error "extern_standalone.cpp only supports 64-bit platforms" +#endif + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define ARCH_BIG_ENDIAN +#endif + +/* Doubles are assumed to be IEEE 754 and to have the same byte order as + integers. This holds on all supported 64-bit platforms; the runtime's + ARCH_FLOAT_ENDIANNESS mixed-endian configurations only existed on + 32-bit ARM. */ + +/* From caml/misc.h */ + +typedef intptr_t intnat; +typedef uintptr_t uintnat; +typedef size_t asize_t; + +static inline int caml_umul_overflow(uintnat a, uintnat b, uintnat * res) +{ + return __builtin_mul_overflow(a, b, res); +} + +/* --------------------------------------------------------------------- */ +/* Value representation (from caml/mlvalues.h) */ + +typedef intnat value; +typedef uintnat header_t; +typedef uintnat mlsize_t; +typedef unsigned int tag_t; + +#define Is_null(v) ((v) == 0) + +static inline int Is_long(value x) { + return ((x & 1) != 0 || x == 0); +} + +static inline int Is_block(value x) { + return ((x & 1) == 0 && x != 0); +} + +#define Long_val(x) ((x) >> 1) + +/* Headers: 8 reserved bits (nonzero only for mixed blocks), then 46 + size bits, 2 colour bits and 8 tag bits (see the top of this file). + In the runtime Hd_val is a relaxed atomic load. Make_header uses + the colour for out-of-heap blocks (NOT_MARKABLE, i.e. 3) and zero + reserved bits. */ + +#define Hd_val(val) (((volatile header_t *) (val)) [-1]) +#define Tag_hd(hd) ((tag_t) ((hd) & 0xFF)) +#define Wosize_hd(hd) \ + ((mlsize_t) (((hd) >> 10) & (((header_t) 1 << 46) - 1))) +#define Reserved_hd(hd) ((hd) >> 56) +#define Tag_val(val) Tag_hd(Hd_val(val)) +#define Wosize_val(val) Wosize_hd(Hd_val(val)) + +#define Make_header(wosize, tag) \ + (((header_t) (wosize) << 10) + (3 << 8) + (tag)) + +#define Field(x, i) (((volatile value *)(x)) [i]) /* Also an l-value. */ +#define Forward_val(v) Field(v, 0) +#define String_val(x) ((const char *) (x)) + +#define Forcing_tag 244 +#define Cont_tag 245 +#define Lazy_tag 246 +#define Closure_tag 247 +#define Infix_tag 249 +#define Forward_tag 250 +#define Abstract_tag 251 +#define String_tag 252 +#define Double_tag 253 +#define Double_array_tag 254 +#define Custom_tag 255 + +/* From caml/str.c */ + +static mlsize_t caml_string_length(value s) +{ + const char * p = (const char *) s; + mlsize_t temp = Wosize_val(s) * sizeof(value) - 1; + assert (p[temp - p[temp]] == 0); + return temp - p[temp]; +} + +/* --------------------------------------------------------------------- */ +/* The marshal format (from caml/intext.h) */ + +/* Magic number */ + +#define Intext_magic_number_small 0x8495A6BE +#define Intext_magic_number_big 0x8495A6BF + +/* Header format for the "small" model: 20 bytes + 0 "small" magic number + 4 length of marshaled data, in bytes + 8 number of shared blocks + 12 size in words when read on a 32-bit platform + (always 0 here: 32-bit readers are not supported) + 16 size in words when read on a 64-bit platform + The 4 numbers are 32 bits each, in big endian. + + Header format for the "big" model: 32 bytes + 0 "big" magic number + 4 four reserved bytes, currently set to 0 + 8 length of marshaled data, in bytes + 16 number of shared blocks + 24 size in words when read on a 64-bit platform + The 3 numbers are 64 bits each, in big endian. +*/ + +#define MAX_INTEXT_HEADER_SIZE 32 + +/* Codes for the compact format */ + +#define PREFIX_SMALL_BLOCK 0x80 +#define PREFIX_SMALL_INT 0x40 +#define PREFIX_SMALL_STRING 0x20 +#define CODE_INT8 0x0 +#define CODE_INT16 0x1 +#define CODE_INT32 0x2 +#define CODE_INT64 0x3 +#define CODE_SHARED8 0x4 +#define CODE_SHARED16 0x5 +#define CODE_SHARED32 0x6 +#define CODE_SHARED64 0x14 +#define CODE_BLOCK32 0x8 +#define CODE_BLOCK64 0x13 +#define CODE_STRING8 0x9 +#define CODE_STRING32 0xA +#define CODE_STRING64 0x15 +#define CODE_DOUBLE_BIG 0xB +#define CODE_DOUBLE_LITTLE 0xC +#define CODE_DOUBLE_ARRAY8_BIG 0xD +#define CODE_DOUBLE_ARRAY8_LITTLE 0xE +#define CODE_DOUBLE_ARRAY32_BIG 0xF +#define CODE_DOUBLE_ARRAY32_LITTLE 0x7 +#define CODE_DOUBLE_ARRAY64_BIG 0x16 +#define CODE_DOUBLE_ARRAY64_LITTLE 0x17 +#define CODE_CODEPOINTER 0x10 +#define CODE_INFIXPOINTER 0x11 +#define OLD_CODE_CUSTOM 0x12 // no longer supported +#define CODE_CUSTOM_LEN 0x18 +#define CODE_CUSTOM_FIXED 0x19 + +#define CODE_UNBOXED_INT64 0x1a // Jane Street extensions +#define CODE_NULL 0x1f + +#ifdef ARCH_BIG_ENDIAN +#define CODE_DOUBLE_NATIVE CODE_DOUBLE_BIG +#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_BIG +#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_BIG +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_BIG +#else +#define CODE_DOUBLE_NATIVE CODE_DOUBLE_LITTLE +#define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_LITTLE +#define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_LITTLE +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_LITTLE +#endif + +/* Size-ing data structures for extern. Chosen so that + sizeof(struct output_block) is slightly below 8Kb. */ + +#define SIZE_EXTERN_OUTPUT_BLOCK 8100 + +struct caml_output_block { + struct caml_output_block * next; + char * end; + char data[SIZE_EXTERN_OUTPUT_BLOCK]; +}; + +/* --------------------------------------------------------------------- */ +/* Public interface of this file */ + +/* Errors. The runtime raises Out_of_memory / Invalid_argument; here + the error is returned and the corresponding message (a string + literal) is available via [caml_extern_error_message]. */ + +typedef enum { + CAML_EXTERN_OK = 0, + CAML_EXTERN_ERROR_OUT_OF_MEMORY = 1, + CAML_EXTERN_ERROR_INVALID_ARGUMENT = 2 +} caml_extern_error; + +extern "C" { + +const char * caml_extern_error_message(void); + +caml_extern_error caml_output_value_to_malloc + (value v, /*out*/ char ** buf, /*out*/ intnat * len); + /* Marshal [v] to a buffer allocated with malloc. On success returns + CAML_EXTERN_OK and stores the buffer and its length in bytes in + [*buf] and [*len]; the caller is responsible for freeing the + buffer. On failure returns an error code and writes neither + [*buf] nor [*len]. Sharing within [v] is always preserved, as + with an empty flag list in the runtime. Values with no external + representation (closures, continuations, custom / abstract / mixed + blocks) yield CAML_EXTERN_ERROR_INVALID_ARGUMENT. */ + +void caml_free_extern_state (void); + /* Free the internal state (lazily allocated on first use and then + reused across calls). */ + +} /* extern "C" */ + +/* --------------------------------------------------------------------- */ +/* The marshaller itself (from runtime/extern.c) */ + +/* Stack for pending values to marshal */ + +#define EXTERN_STACK_INIT_SIZE 256 +#define EXTERN_STACK_MAX_SIZE (1024*1024*100) + +struct extern_item { volatile value * v; mlsize_t count; }; + +/* Hash table to record already-marshaled objects and their positions */ + +struct object_position { value obj; uintnat pos; }; + +/* The hash table uses open addressing, linear probing, and a redundant + representation: + - a bitvector [present] records which entries of the table are occupied; + - an array [entries] records (object, position) pairs for the entries + that are occupied. + The bitvector is much smaller than the array (1/128th on 64-bit + platforms, 1/64th on 32-bit platforms), so it has better locality, + making it faster to determine that an object is not in the table. + Also, it makes it faster to empty or initialize a table: only the + [present] bitvector needs to be filled with zeros, the [entries] + array can be left uninitialized. +*/ + +struct position_table { + int shift; + mlsize_t size; /* size == 1 << (wordsize - shift) */ + mlsize_t mask; /* mask == size - 1 */ + mlsize_t threshold; /* threshold == a fixed fraction of size */ + uintnat * present; /* [Bitvect_size(size)] */ + struct object_position * entries; /* [size] */ +}; + +#define Bits_word (8 * sizeof(uintnat)) +#define Bitvect_size(n) (((n) + Bits_word - 1) / Bits_word) + +#define POS_TABLE_INIT_SIZE_LOG2 8 +#define POS_TABLE_INIT_SIZE (1 << POS_TABLE_INIT_SIZE_LOG2) + +struct caml_extern_state { + + uintnat obj_counter; /* Number of objects emitted so far */ + uintnat size_64; /* Size in words of 64-bit block for struct. */ + + /* Return point for error reporting (replaces raising OCaml + exceptions in the runtime version) */ + jmp_buf error_return; + + /* Stack for pending value to marshal */ + struct extern_item extern_stack_init[EXTERN_STACK_INIT_SIZE]; + struct extern_item * extern_stack; + struct extern_item * extern_stack_limit; + + /* Hash table to record already marshalled objects */ + uintnat pos_table_present_init[Bitvect_size(POS_TABLE_INIT_SIZE)]; + struct object_position pos_table_entries_init[POS_TABLE_INIT_SIZE]; + struct position_table pos_table; + + /* To buffer the output */ + + char * extern_ptr; + char * extern_limit; + + struct caml_output_block * extern_output_first; + struct caml_output_block * extern_output_block; +}; + +/* The extern state. The runtime keeps this per-domain in + Caml_state->extern_state; here it is a single global. */ + +static struct caml_extern_state * extern_state = NULL; + +/* Error reporting, replacing the exception raising of the runtime + version. All messages are string literals. */ + +static caml_extern_error extern_error_code = CAML_EXTERN_OK; +static const char * extern_error_msg = NULL; + +const char * caml_extern_error_message(void) +{ + return extern_error_msg; +} + +[[noreturn]] static void extern_raise(struct caml_extern_state* s, + caml_extern_error code, const char * msg) +{ + extern_error_code = code; + extern_error_msg = msg; + longjmp(s->error_return, 1); +} + +static void init_extern_stack(struct caml_extern_state* s) +{ + /* (Re)initialize the globals for next time around */ + s->extern_stack = s->extern_stack_init; + s->extern_stack_limit = s->extern_stack + EXTERN_STACK_INIT_SIZE; +} + +/* Returns NULL on out-of-memory (the runtime version raises). */ +static struct caml_extern_state* init_extern_state (void) +{ + struct caml_extern_state* s; + + if (extern_state != NULL) + return extern_state; + + s = (struct caml_extern_state *) malloc(sizeof(struct caml_extern_state)); + if (s == NULL) return NULL; + + s->obj_counter = 0; + s->size_64 = 0; + init_extern_stack(s); + + extern_state = s; + return s; +} + +void caml_free_extern_state (void) +{ + if (extern_state != NULL) { + free(extern_state); + extern_state = NULL; + } +} + +/* Forward declarations */ + +[[noreturn]] static void extern_out_of_memory(struct caml_extern_state* s); + +[[noreturn]] static +void extern_invalid_argument(struct caml_extern_state* s, + const char *msg); + +[[noreturn]] static void extern_stack_overflow(struct caml_extern_state* s); + +static void free_extern_output(struct caml_extern_state* s); + +static void extern_free_stack(struct caml_extern_state* s) +{ + /* Free the extern stack if needed */ + if (s->extern_stack != s->extern_stack_init) { + free(s->extern_stack); + init_extern_stack(s); + } +} + +static struct extern_item * extern_resize_stack(struct caml_extern_state* s, + const struct extern_item * sp) +{ + asize_t newsize = 2 * (s->extern_stack_limit - s->extern_stack); + asize_t sp_offset = sp - s->extern_stack; + struct extern_item * newstack; + + if (newsize >= EXTERN_STACK_MAX_SIZE) extern_stack_overflow(s); + newstack = + (struct extern_item *) calloc(newsize, sizeof(struct extern_item)); + if (newstack == NULL) extern_stack_overflow(s); + + /* Copy items from the old stack to the new stack */ + memcpy (newstack, s->extern_stack, + sizeof(struct extern_item) * sp_offset); + + /* Free the old stack if it is not the initial stack */ + if (s->extern_stack != s->extern_stack_init) + free(s->extern_stack); + + s->extern_stack = newstack; + s->extern_stack_limit = newstack + newsize; + return newstack + sp_offset; +} + +/* Multiplicative Fibonacci hashing + (Knuth, TAOCP vol 3, section 6.4, page 518). + HASH_FACTOR is (sqrt(5) - 1) / 2 * 2^wordsize. */ +#define HASH_FACTOR 11400714819323198486UL +#define Hash(v,shift) (((uintnat)(v) * HASH_FACTOR) >> (shift)) + +/* When the table becomes 2/3 full, its size is increased. */ +#define Threshold(sz) (((sz) * 2) / 3) + +/* Initialize the position table */ + +static void extern_init_position_table(struct caml_extern_state* s) +{ + s->pos_table.size = POS_TABLE_INIT_SIZE; + s->pos_table.shift = 8 * sizeof(value) - POS_TABLE_INIT_SIZE_LOG2; + s->pos_table.mask = POS_TABLE_INIT_SIZE - 1; + s->pos_table.threshold = Threshold(POS_TABLE_INIT_SIZE); + s->pos_table.present = s->pos_table_present_init; + s->pos_table.entries = s->pos_table_entries_init; + memset(s->pos_table_present_init, 0, + Bitvect_size(POS_TABLE_INIT_SIZE) * sizeof(uintnat)); +} + +/* Free the position table */ + +static void extern_free_position_table(struct caml_extern_state* s) +{ + if (s->pos_table.present != s->pos_table_present_init) { + free(s->pos_table.present); + free(s->pos_table.entries); + /* Protect against repeated calls to extern_free_position_table */ + s->pos_table.present = s->pos_table_present_init; + s->pos_table.entries = s->pos_table_entries_init; + } +} + +/* Accessing bitvectors */ + +static inline uintnat bitvect_test(uintnat * bv, uintnat i) +{ + return bv[i / Bits_word] & ((uintnat) 1 << (i & (Bits_word - 1))); +} + +static inline void bitvect_set(uintnat * bv, uintnat i) +{ + bv[i / Bits_word] |= ((uintnat) 1 << (i & (Bits_word - 1))); +} + +/* Grow the position table */ + +static void extern_resize_position_table(struct caml_extern_state *s) +{ + mlsize_t new_size, new_byte_size; + int new_shift; + uintnat * new_present; + struct object_position * new_entries; + uintnat h; + struct position_table old = s->pos_table; + + /* Grow the table quickly (x 8) up to 10^6 entries, + more slowly (x 2) afterwards. */ + if (old.size < 1000000) { + new_size = 8 * old.size; + new_shift = old.shift - 3; + } else { + new_size = 2 * old.size; + new_shift = old.shift - 1; + } + if (new_size == 0 + || caml_umul_overflow(new_size, sizeof(struct object_position), + &new_byte_size)) + extern_out_of_memory(s); + new_entries = (struct object_position *) malloc(new_byte_size); + if (new_entries == NULL) extern_out_of_memory(s); + new_present = + (uintnat *) calloc(Bitvect_size(new_size), sizeof(uintnat)); + if (new_present == NULL) { + free(new_entries); + extern_out_of_memory(s); + } + s->pos_table.size = new_size; + s->pos_table.shift = new_shift; + s->pos_table.mask = new_size - 1; + s->pos_table.threshold = Threshold(new_size); + s->pos_table.present = new_present; + s->pos_table.entries = new_entries; + + /* Insert every entry of the old table in the new table */ + for (uintnat i = 0; i < old.size; i++) { + if (! bitvect_test(old.present, i)) continue; + h = Hash(old.entries[i].obj, s->pos_table.shift); + while (bitvect_test(new_present, h)) { + h = (h + 1) & s->pos_table.mask; + } + bitvect_set(new_present, h); + new_entries[h] = old.entries[i]; + } + + /* Free the old tables if they are not the initial ones */ + if (old.present != s->pos_table_present_init) { + free(old.present); + free(old.entries); + } +} + +/* Determine whether the given object [obj] is in the hash table. + If so, set [*pos_out] to its position in the output and return 1. + If not, return 0. + Either way, set [*h_out] to the hash value appropriate for + [extern_record_location]. */ +static inline int extern_lookup_position(struct caml_extern_state *s, value obj, + uintnat * pos_out, uintnat * h_out) +{ + uintnat h = Hash(obj, s->pos_table.shift); + while (1) { + if (! bitvect_test(s->pos_table.present, h)) { + *h_out = h; + return 0; + } + if (s->pos_table.entries[h].obj == obj) { + *h_out = h; + *pos_out = s->pos_table.entries[h].pos; + return 1; + } + h = (h + 1) & s->pos_table.mask; + } +} + +/* Record the output position for the given object [obj]. */ +/* The [h] parameter is the index in the hash table where the object + must be inserted. It was determined during lookup. */ +static void extern_record_location(struct caml_extern_state* s, + value obj, uintnat h) +{ + bitvect_set(s->pos_table.present, h); + s->pos_table.entries[h].obj = obj; + s->pos_table.entries[h].pos = s->obj_counter; + s->obj_counter++; + if (s->obj_counter >= s->pos_table.threshold) + extern_resize_position_table(s); +} + +/* To buffer the output */ + +static void init_extern_output(struct caml_extern_state* s) +{ + s->extern_output_first = + (struct caml_output_block *) malloc(sizeof(struct caml_output_block)); + if (s->extern_output_first == NULL) + extern_raise(s, CAML_EXTERN_ERROR_OUT_OF_MEMORY, + "output_value: out of memory"); + s->extern_output_block = s->extern_output_first; + s->extern_output_block->next = NULL; + s->extern_ptr = s->extern_output_block->data; + s->extern_limit = s->extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK; +} + +static void close_extern_output(struct caml_extern_state* s) +{ + s->extern_output_block->end = s->extern_ptr; +} + +static void free_extern_output(struct caml_extern_state* s) +{ + for (struct caml_output_block *blk = s->extern_output_first, *nextblk; + blk != NULL; + blk = nextblk) { + nextblk = blk->next; + free(blk); + } + s->extern_output_first = NULL; + extern_free_stack(s); + extern_free_position_table(s); +} + +static void grow_extern_output(struct caml_extern_state *s, intnat required) +{ + struct caml_output_block * blk; + intnat extra; + + s->extern_output_block->end = s->extern_ptr; + if (required <= SIZE_EXTERN_OUTPUT_BLOCK / 2) + extra = 0; + else + extra = required; + blk = (struct caml_output_block *) + malloc(sizeof(struct caml_output_block) + extra); + if (blk == NULL) extern_out_of_memory(s); + s->extern_output_block->next = blk; + s->extern_output_block = blk; + s->extern_output_block->next = NULL; + s->extern_ptr = s->extern_output_block->data; + s->extern_limit = + s->extern_output_block->data + SIZE_EXTERN_OUTPUT_BLOCK + extra; +} + +static intnat extern_output_length(struct caml_extern_state* s) +{ + struct caml_output_block * blk; + intnat len; + + for (len = 0, blk = s->extern_output_first; blk != NULL; blk = blk->next) + len += blk->end - blk->data; + return len; +} + +/* Error raising, with cleanup */ + +static void extern_out_of_memory(struct caml_extern_state* s) +{ + free_extern_output(s); + extern_raise(s, CAML_EXTERN_ERROR_OUT_OF_MEMORY, + "output_value: out of memory"); +} + +static void extern_invalid_argument(struct caml_extern_state *s, + const char *msg) +{ + free_extern_output(s); + extern_raise(s, CAML_EXTERN_ERROR_INVALID_ARGUMENT, msg); +} + +static void extern_stack_overflow(struct caml_extern_state* s) +{ + free_extern_output(s); + extern_raise(s, CAML_EXTERN_ERROR_OUT_OF_MEMORY, + "output_value: stack overflow"); +} + +/* Conversion to big-endian */ + +#ifdef ARCH_BIG_ENDIAN +#define Htobe16(x) ((uint16_t) (x)) +#define Htobe32(x) ((uint32_t) (x)) +#define Htobe64(x) ((uint64_t) (x)) +#else +#define Htobe16(x) __builtin_bswap16((uint16_t) (x)) +#define Htobe32(x) __builtin_bswap32((uint32_t) (x)) +#define Htobe64(x) __builtin_bswap64((uint64_t) (x)) +#endif + +static inline void store16(char * dst, int n) +{ + uint16_t u = Htobe16(n); + memcpy(dst, &u, 2); +} + +static inline void store32(char * dst, intnat n) +{ + uint32_t u = Htobe32(n); + memcpy(dst, &u, 4); +} + +static inline void store64(char * dst, int64_t n) +{ + uint64_t u = Htobe64(n); + memcpy(dst, &u, 8); +} + +/* Write characters, integers, and blocks in the output buffer */ + +static inline void writebyte(struct caml_extern_state* s, int c) +{ + if (s->extern_ptr >= s->extern_limit) grow_extern_output(s, 1); + *s->extern_ptr++ = c; +} + +static void writeblock(struct caml_extern_state* s, const char * data, + intnat len) +{ + if (s->extern_ptr + len > s->extern_limit) grow_extern_output(s, len); + memcpy(s->extern_ptr, data, len); + s->extern_ptr += len; +} + +static inline void writeblock_float8(struct caml_extern_state* s, + const double * data, intnat ndoubles) +{ + /* Doubles have the same byte order as integers, so they can be + written natively; the CODE_DOUBLE*_NATIVE codes record which + endianness that is. (The runtime additionally handles mixed-endian + doubles here, which only exist on 32-bit ARM.) */ + writeblock(s, (const char *) data, ndoubles * 8); +} + +static void writecode8(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 2 > s->extern_limit) grow_extern_output(s, 2); + s->extern_ptr[0] = code; + s->extern_ptr[1] = val; + s->extern_ptr += 2; +} + +static void writecode16(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 3 > s->extern_limit) grow_extern_output(s, 3); + s->extern_ptr[0] = code; + store16(s->extern_ptr + 1, (int) val); + s->extern_ptr += 3; +} + +static void writecode32(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 5 > s->extern_limit) grow_extern_output(s, 5); + s->extern_ptr[0] = code; + store32(s->extern_ptr + 1, val); + s->extern_ptr += 5; +} + +static void writecode64(struct caml_extern_state* s, + int code, intnat val) +{ + if (s->extern_ptr + 9 > s->extern_limit) grow_extern_output(s, 9); + s->extern_ptr[0] = code; + store64(s->extern_ptr + 1, val); + s->extern_ptr += 9; +} + +/* Marshaling integers */ + +static inline void extern_int(struct caml_extern_state* s, intnat n) +{ + if (n >= 0 && n < 0x40) { + writebyte(s, PREFIX_SMALL_INT + n); + } else if (n >= -(1 << 7) && n < (1 << 7)) { + writecode8(s, CODE_INT8, n); + } else if (n >= -(1 << 15) && n < (1 << 15)) { + writecode16(s, CODE_INT16, n); + } else if (n < -((intnat)1 << 30) || n >= ((intnat)1 << 30)) { + writecode64(s, CODE_INT64, n); + } else { + writecode32(s, CODE_INT32, n); + } +} + +static inline void extern_null(struct caml_extern_state* s) +{ + writecode8(s, CODE_NULL, 0); +} + +/* Marshaling references to previously-marshaled blocks */ + +static inline void extern_shared_reference(struct caml_extern_state* s, + uintnat d) +{ + if (d < 0x100) { + writecode8(s, CODE_SHARED8, d); + } else if (d < 0x10000) { + writecode16(s, CODE_SHARED16, d); + } else if (d >= (uintnat)1 << 32) { + writecode64(s, CODE_SHARED64, d); + } else { + writecode32(s, CODE_SHARED32, d); + } +} + +/* Marshaling block headers */ + +static inline void extern_header(struct caml_extern_state* s, + mlsize_t sz, tag_t tag) +{ + if (tag < 16 && sz < 8) { + writebyte(s, PREFIX_SMALL_BLOCK + tag + (sz << 4)); + } else { + header_t hd = Make_header(sz, tag); + if (hd < (uintnat)1 << 32) + writecode32(s, CODE_BLOCK32, hd); + else + writecode64(s, CODE_BLOCK64, hd); + } +} + +/* Marshaling strings */ + +static inline void extern_string(struct caml_extern_state *s, + value v, mlsize_t len) +{ + if (len < 0x20) { + writebyte(s, PREFIX_SMALL_STRING + len); + } else if (len < 0x100) { + writecode8(s, CODE_STRING8, len); + } else { + if (len < (uintnat)1 << 32) + writecode32(s, CODE_STRING32, len); + else + writecode64(s, CODE_STRING64, len); + } + writeblock(s, String_val(v), len); +} + +/* Marshaling FP numbers */ + +static inline void extern_double(struct caml_extern_state* s, value v) +{ + writebyte(s, CODE_DOUBLE_NATIVE); + writeblock_float8(s, (double *) v, 1); +} + +/* Marshaling FP arrays */ + +static inline void extern_double_array(struct caml_extern_state* s, + value v, mlsize_t nfloats) +{ + if (nfloats < 0x100) { + writecode8(s, CODE_DOUBLE_ARRAY8_NATIVE, nfloats); + } else { + if (nfloats < (uintnat) 1 << 32) + writecode32(s, CODE_DOUBLE_ARRAY32_NATIVE, nfloats); + else + writecode64(s, CODE_DOUBLE_ARRAY64_NATIVE, nfloats); + } + writeblock_float8(s, (double *) v, nfloats); +} + +/* Marshal the given value in the output buffer */ + +static void extern_rec(struct caml_extern_state* s, value v) +{ + struct extern_item * sp; + uintnat h = 0; + uintnat pos = 0; + + /* for Double_tag and Double_array_tag */ + static_assert(sizeof(double) == 8, ""); + + extern_init_position_table(s); + sp = s->extern_stack; + + while(1) { + if (Is_null(v)) { + extern_null(s); + } else if (Is_long(v)) { + extern_int(s, Long_val(v)); + } + else { + header_t hd = Hd_val(v); + tag_t tag = Tag_hd(hd); + mlsize_t sz = Wosize_hd(hd); + if (Reserved_hd(hd) != 0) { + /* Nonzero reserved header bits indicate a mixed block. */ + extern_invalid_argument(s, "output_value: mixed block"); + break; + } + + if (tag == Forward_tag) { + value f = Forward_val (v); + if (Is_block (f) + && ( Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag + || Tag_val (f) == Forcing_tag + /* Double_tag check because of flat float arrays */ + || Tag_val (f) == Double_tag + )){ + /* Do not short-circuit the pointer. */ + }else{ + v = f; + continue; + } + } + /* Atoms are treated specially for two reasons: they are not allocated + in the externed block, and they are automatically shared. */ + if (sz == 0) { + extern_header(s, 0, tag); + goto next_item; + } + /* Check if object already seen */ + if (extern_lookup_position(s, v, &pos, &h)) { + extern_shared_reference(s, s->obj_counter - pos); + goto next_item; + } + /* Output the contents of the object */ + switch(tag) { + case String_tag: { + mlsize_t len = caml_string_length(v); + extern_string(s, v, len); + s->size_64 += 1 + (len + 8) / 8; + extern_record_location(s, v, h); + break; + } + case Double_tag: { + extern_double(s, v); + s->size_64 += 1 + 1; + extern_record_location(s, v, h); + break; + } + case Double_array_tag: { + /* sizeof(double) == sizeof(value), per the static_assert above */ + mlsize_t nfloats = Wosize_val(v); + extern_double_array(s, v, nfloats); + s->size_64 += 1 + nfloats; + extern_record_location(s, v, h); + break; + } + case Abstract_tag: + extern_invalid_argument(s, "output_value: abstract value (Abstract)"); + break; + case Infix_tag: + /* An infix pointer into a closure block; closures cannot be + marshalled (see Closure_tag below). */ + extern_invalid_argument(s, "output_value: functional value"); + break; + case Custom_tag: + /* Custom blocks (Int32, Int64, Nativeint, Bigarray, ...) cannot + be marshalled here: their serialization functions would need the + caml_serialize_* entry points, which are not provided. */ + extern_invalid_argument(s, "output_value: abstract value (Custom)"); + break; + case Closure_tag: + /* The runtime's code-fragment table is not available here, so + code pointers, and hence closures, cannot be marshalled. */ + extern_invalid_argument(s, "output_value: functional value"); + break; + case Cont_tag: + extern_invalid_argument(s, "output_value: continuation value"); + break; + default: { + extern_header(s, sz, tag); + s->size_64 += 1 + sz; + extern_record_location(s, v, h); + /* Remember that we still have to serialize fields 1 ... sz - 1 */ + if (sz > 1) { + sp++; + if (sp >= s->extern_stack_limit) + sp = extern_resize_stack(s, sp); + sp->v = &Field(v, 1); + sp->count = sz - 1; + } + /* Continue serialization with the first field */ + v = Field(v, 0); + continue; + } + } + } + next_item: + /* Pop one more item to marshal, if any */ + if (sp == s->extern_stack) { + /* We are done. Cleanup the stack and leave the function */ + extern_free_stack(s); + extern_free_position_table(s); + return; + } + v = *((sp->v)++); + if (--(sp->count) == 0) sp--; + } + /* Never reached as function leaves with return */ +} + +static intnat extern_value(struct caml_extern_state* s, value v, + /*out*/ char header[MAX_INTEXT_HEADER_SIZE], + /*out*/ int * header_len) +{ + intnat res_len; + /* Initializations */ + s->obj_counter = 0; + s->size_64 = 0; + /* Marshal the object */ + extern_rec(s, v); + /* Record end of output */ + close_extern_output(s); + /* Write the header */ + res_len = extern_output_length(s); + if (res_len >= ((intnat)1 << 32) || s->size_64 >= ((intnat)1 << 32)) { + /* The object is too big for the small header format. + Use the big header. */ + store32(header, Intext_magic_number_big); + store32(header + 4, 0); + store64(header + 8, res_len); + store64(header + 16, s->obj_counter); + store64(header + 24, s->size_64); + *header_len = 32; + return res_len; + } + /* Use the small header format. The field at offset 12 is the size in + words when read on a 32-bit platform; 32-bit readers are not + supported, so 0 is written instead. */ + store32(header, Intext_magic_number_small); + store32(header + 4, res_len); + store32(header + 8, s->obj_counter); + store32(header + 12, 0); + store32(header + 16, s->size_64); + *header_len = 20; + return res_len; +} + +/* The entry point */ + +caml_extern_error +caml_output_value_to_malloc(value v, + /*out*/ char ** buf, + /*out*/ intnat * len) +{ + char header[MAX_INTEXT_HEADER_SIZE]; + int header_len; + intnat data_len; + char * res; + struct caml_extern_state* s = init_extern_state (); + + if (s == NULL) { + extern_error_code = CAML_EXTERN_ERROR_OUT_OF_MEMORY; + extern_error_msg = "output_value: out of memory"; + return extern_error_code; + } + extern_error_msg = NULL; + if (setjmp(s->error_return) != 0) return extern_error_code; + + init_extern_output(s); + data_len = extern_value(s, v, header, &header_len); + res = (char *) malloc(header_len + data_len); + if (res == NULL) extern_out_of_memory(s); + *buf = res; + *len = header_len + data_len; + memcpy(res, header, header_len); + res += header_len; + for (struct caml_output_block *blk = s->extern_output_first, *nextblk; + blk != NULL; + blk = nextblk) { + intnat n = blk->end - blk->data; + memcpy(res, blk->data, n); + res += n; + nextblk = blk->next; + free(blk); + } + return CAML_EXTERN_OK; +} diff --git a/extern_standalone/extern_standalone_check_big.ml b/extern_standalone/extern_standalone_check_big.ml new file mode 100644 index 0000000000000..579c6a5800a06 --- /dev/null +++ b/extern_standalone/extern_standalone_check_big.ml @@ -0,0 +1,12 @@ +(* Reads the output of extern_standalone_test_big.c back with + Marshal.from_channel and checks it against the expected list. + + Usage: ocaml extern_standalone_check_big.ml actual_big.bin *) + +let ic = open_in_bin Sys.argv.(1) + +let () = + let expected = List.init 10000 (fun i -> "item" ^ string_of_int i) in + let v : string list = Marshal.from_channel ic in + if v <> expected then (prerr_endline "big mismatch"; exit 1); + print_endline "big readback OK" diff --git a/extern_standalone/extern_standalone_check_readback.ml b/extern_standalone/extern_standalone_check_readback.ml new file mode 100644 index 0000000000000..9832504115920 --- /dev/null +++ b/extern_standalone/extern_standalone_check_readback.ml @@ -0,0 +1,43 @@ +(* Reads the output of extern_standalone_test.c back with + Marshal.from_channel and checks each value, proving the standalone + output is consumable by the real OCaml runtime. + + Usage: ocaml extern_standalone_check_readback.ml actual.bin *) + +let ic = open_in_bin Sys.argv.(1) + +type t = A of int | B of int | C of int | D of string + +let idx = ref 0 + +let check : 'a. 'a -> unit = fun expected -> + incr idx; + let v = Marshal.from_channel ic in + if v <> expected then begin + Printf.eprintf "value %d mismatch\n" !idx; + exit 1 + end + +let () = + check 42; + let pair = (1, 2) in + check pair; + check "hello"; + check (pair, pair); + check 3.14; + check [| 1.5; 2.5; 3.5 |]; + check [1; 2; 3]; + check ""; + check (-5); + check (-1000); + check 100000; + check (1 lsl 40); + check (String.make 100 'x'); + check (String.make 300 'y'); + check (D "payload"); + check ([||] : int array); + check ([1; 2; 3], "mid", 2.25); + (match input_char ic with + | exception End_of_file -> () + | _ -> prerr_endline "trailing data"; exit 1); + print_endline "readback OK" diff --git a/extern_standalone/extern_standalone_compare.py b/extern_standalone/extern_standalone_compare.py new file mode 100644 index 0000000000000..2b78eb0977d36 --- /dev/null +++ b/extern_standalone/extern_standalone_compare.py @@ -0,0 +1,31 @@ +"""Compare two files of concatenated marshal blobs (e.g. the output of +extern_standalone_test.c against that of +extern_standalone_gen_expected.ml), ignoring the header field at offset +12 of each blob (size in words when read on a 32-bit platform), which +extern_standalone.c writes as 0. + +Usage: python3 extern_standalone_compare.py actual.bin expected.bin +""" +import sys + +def blobs(path): + data = open(path, 'rb').read() + i, out = 0, [] + while i < len(data): + magic = int.from_bytes(data[i:i+4], 'big') + assert magic == 0x8495A6BE, f"unexpected magic {magic:#x} at {i}" + datalen = int.from_bytes(data[i+4:i+8], 'big') + out.append(bytearray(data[i:i+20+datalen])) + i += 20 + datalen + assert i == len(data) + return out + +a, b = blobs(sys.argv[1]), blobs(sys.argv[2]) +assert len(a) == len(b), f"blob counts differ: {len(a)} vs {len(b)}" +for n, (x, y) in enumerate(zip(a, b)): + x[12:16] = b'\0\0\0\0' + y[12:16] = b'\0\0\0\0' + if x != y: + print(f"blob {n} differs") + sys.exit(1) +print(f"OK: {len(a)} blobs identical modulo the 32-bit size field") diff --git a/extern_standalone/extern_standalone_gen_expected.ml b/extern_standalone/extern_standalone_gen_expected.ml new file mode 100644 index 0000000000000..a632cce0df94d --- /dev/null +++ b/extern_standalone/extern_standalone_gen_expected.ml @@ -0,0 +1,35 @@ +(* Generates the expected marshalled bytes for extern_standalone_test.c, + using the real Marshal module. Values must match, in order, those in + extern_standalone_test.c. + + Usage: ocaml extern_standalone_gen_expected.ml expected.bin + then compare against the test output with + extern_standalone_compare.py. *) + +let out = open_out_bin Sys.argv.(1) + +let dump v = output_string out (Marshal.to_string v []) + +(* [D _] is the fourth non-constant constructor, so it has tag 3 *) +type t = A of int | B of int | C of int | D of string + +let () = + dump 42; + let pair = (1, 2) in + dump pair; + dump "hello"; + dump (pair, pair); + dump 3.14; + dump [| 1.5; 2.5; 3.5 |]; + dump [1; 2; 3]; + dump ""; + dump (-5); + dump (-1000); + dump 100000; + dump (1 lsl 40); + dump (String.make 100 'x'); + dump (String.make 300 'y'); + dump (D "payload"); + dump [||]; + dump ([1; 2; 3], "mid", 2.25); + close_out out diff --git a/extern_standalone/extern_standalone_gen_expected_big.ml b/extern_standalone/extern_standalone_gen_expected_big.ml new file mode 100644 index 0000000000000..ac7f23dd0b476 --- /dev/null +++ b/extern_standalone/extern_standalone_gen_expected_big.ml @@ -0,0 +1,11 @@ +(* Generates the expected marshalled bytes for + extern_standalone_test_big.c, using the real Marshal module. + + Usage: ocaml extern_standalone_gen_expected_big.ml expected_big.bin *) + +let out = open_out_bin Sys.argv.(1) + +let () = + let l = List.init 10000 (fun i -> "item" ^ string_of_int i) in + output_string out (Marshal.to_string l []); + close_out out diff --git a/extern_standalone/extern_standalone_test.c b/extern_standalone/extern_standalone_test.c new file mode 100644 index 0000000000000..6e97ea629bc56 --- /dev/null +++ b/extern_standalone/extern_standalone_test.c @@ -0,0 +1,219 @@ +/* Test harness for extern_standalone.c (and for extern_standalone.cpp, + by linking this file against the C++ build instead). + + Build: cc -std=c11 -Wall -Wextra extern_standalone.c \ + extern_standalone_test.c -o test_extern + + Constructs OCaml values by hand (native-code OxCaml representation) + and marshals them, writing the concatenated results to the file given + as argv[1]; then exercises the error paths, which are self-checking. + The dumped values are intended to be compared against the output of + extern_standalone_gen_expected.ml (the same values marshalled by the + real Marshal module) using extern_standalone_compare.py: they match + byte-for-byte except for the 32-bit size field at bytes 12-15 of each + marshal header, which is written as 0 here. Reading the output back + with extern_standalone_check_readback.ml must also yield the original + values. See extern_standalone_test_big.c for a stress test. */ + +#include +#include +#include +#include + +typedef intptr_t intnat; +typedef uintptr_t uintnat; +typedef intnat value; + +typedef enum { + CAML_EXTERN_OK = 0, + CAML_EXTERN_ERROR_OUT_OF_MEMORY = 1, + CAML_EXTERN_ERROR_INVALID_ARGUMENT = 2 +} caml_extern_error; + +extern caml_extern_error caml_output_value_to_malloc(value v, char ** buf, + intnat * len); +extern const char * caml_extern_error_message(void); + +/* Value construction. Header: 8 reserved bits (zero here), 46 size bits, + 2 colour bits (NOT_MARKABLE), 8 tag bits. */ + +#define TAG_CLOSURE 247 +#define TAG_ABSTRACT 251 +#define TAG_STRING 252 +#define TAG_DOUBLE 253 +#define TAG_DOUBLE_ARRAY 254 +#define TAG_CUSTOM 255 + +static value mk_long(long n) { return ((value) n << 1) | 1; } + +static value mk_block(unsigned tag, size_t wosize) +{ + uintnat * p = malloc((wosize + 1) * sizeof(value)); + if (p == NULL) abort(); + p[0] = ((uintnat) wosize << 10) | (3u << 8) | tag; + return (value) (p + 1); +} + +static void set_field(value b, size_t i, value f) +{ + ((value *) b)[i] = f; +} + +static value mk_string(const char * str) +{ + size_t len = strlen(str); + size_t wosize = (len + sizeof(value)) / sizeof(value); + size_t bosize = wosize * sizeof(value); + value b = mk_block(TAG_STRING, wosize); + char * data = (char *) b; + memset(data, 0, bosize); + memcpy(data, str, len); + data[bosize - 1] = (char) (bosize - 1 - len); + return b; +} + +static value mk_double(double d) +{ + value b = mk_block(TAG_DOUBLE, 1); + memcpy((void *) b, &d, 8); + return b; +} + +static value mk_double_array(const double * d, size_t n) +{ + value b = mk_block(TAG_DOUBLE_ARRAY, n); + memcpy((void *) b, d, n * 8); + return b; +} + +static value mk_list(const long * elts, size_t n) +{ + value l = mk_long(0); /* [] */ + for (size_t i = n; i > 0; i--) { + value cell = mk_block(0, 2); + set_field(cell, 0, mk_long(elts[i - 1])); + set_field(cell, 1, l); + l = cell; + } + return l; +} + +static FILE * out; + +static void dump(value v) +{ + char * buf; + intnat len; + caml_extern_error err = caml_output_value_to_malloc(v, &buf, &len); + if (err != CAML_EXTERN_OK) { + fprintf(stderr, "unexpected error %d: %s\n", (int) err, + caml_extern_error_message()); + exit(2); + } + fwrite(buf, 1, len, out); + free(buf); +} + +int main(int argc, char ** argv) +{ + if (argc != 2) { fprintf(stderr, "usage: %s OUTFILE\n", argv[0]); return 2; } + out = fopen(argv[1], "wb"); + if (out == NULL) { perror("fopen"); return 2; } + + /* Same values, in the same order, as gen_expected.ml */ + dump(mk_long(42)); + + value pair = mk_block(0, 2); + set_field(pair, 0, mk_long(1)); + set_field(pair, 1, mk_long(2)); + dump(pair); + + dump(mk_string("hello")); + + value shared = mk_block(0, 2); + set_field(shared, 0, pair); + set_field(shared, 1, pair); + dump(shared); + + dump(mk_double(3.14)); + + double floats[3] = { 1.5, 2.5, 3.5 }; + dump(mk_double_array(floats, 3)); + + long ints[3] = { 1, 2, 3 }; + dump(mk_list(ints, 3)); + + dump(mk_string("")); + dump(mk_long(-5)); + dump(mk_long(-1000)); + dump(mk_long(100000)); + dump(mk_long(1L << 40)); + + char buf100[101], buf300[301]; + memset(buf100, 'x', 100); buf100[100] = '\0'; + memset(buf300, 'y', 300); buf300[300] = '\0'; + dump(mk_string(buf100)); + dump(mk_string(buf300)); + + /* A variant with a non-zero tag and an atom (empty block) */ + value variant = mk_block(3, 1); + set_field(variant, 0, mk_string("payload")); + dump(variant); + dump(mk_block(0, 0)); + + /* Nested structure exercising the extern stack */ + value nested = mk_block(0, 3); + set_field(nested, 0, mk_list(ints, 3)); + set_field(nested, 1, mk_string("mid")); + set_field(nested, 2, mk_double(2.25)); + dump(nested); + + fclose(out); + + /* Error paths, not compared against the OCaml output */ + + caml_extern_error err; + + value abstract = mk_block(TAG_ABSTRACT, 1); + set_field(abstract, 0, mk_long(0)); + char * buf; + intnat len; + err = caml_output_value_to_malloc(abstract, &buf, &len); + if (err != CAML_EXTERN_ERROR_INVALID_ARGUMENT + || strcmp(caml_extern_error_message(), + "output_value: abstract value (Abstract)") != 0) { + fprintf(stderr, "expected abstract error, got %d: %s\n", (int) err, + caml_extern_error_message()); + return 2; + } + + /* Custom blocks are now rejected */ + value custom = mk_block(TAG_CUSTOM, 2); + set_field(custom, 0, (value) &main); /* would be the ops pointer */ + set_field(custom, 1, mk_long(0)); + err = caml_output_value_to_malloc(custom, &buf, &len); + if (err != CAML_EXTERN_ERROR_INVALID_ARGUMENT + || strcmp(caml_extern_error_message(), + "output_value: abstract value (Custom)") != 0) { + fprintf(stderr, "expected custom error, got %d: %s\n", (int) err, + caml_extern_error_message()); + return 2; + } + + /* Closures are always rejected */ + value closure = mk_block(TAG_CLOSURE, 3); + set_field(closure, 0, (value) &main); + set_field(closure, 1, (value) ((1ULL << 56) + (1ULL << 55) + (2 << 1) + 1)); + set_field(closure, 2, mk_long(7)); + err = caml_output_value_to_malloc(closure, &buf, &len); + if (err != CAML_EXTERN_ERROR_INVALID_ARGUMENT + || strcmp(caml_extern_error_message(), + "output_value: functional value") != 0) { + fprintf(stderr, "expected functional-value error, got %d: %s\n", + (int) err, caml_extern_error_message()); + return 2; + } + + printf("error-path tests passed\n"); + return 0; +} diff --git a/extern_standalone/extern_standalone_test_big.c b/extern_standalone/extern_standalone_test_big.c new file mode 100644 index 0000000000000..7a01cec5cac16 --- /dev/null +++ b/extern_standalone/extern_standalone_test_big.c @@ -0,0 +1,91 @@ +/* Stress test for extern_standalone.c (or extern_standalone.cpp): + marshals a list of 10000 distinct strings, exercising position table + resize (>170 shared objects), output block growth (>8100 bytes) and + extern stack resize (list longer than 256 elements). + + Build: cc -std=c11 -Wall -Wextra extern_standalone.c \ + extern_standalone_test_big.c -o test_big + (also worth running with -fsanitize=address). Writes the marshalled + list to the file given as argv[1]; compare it against the output of + extern_standalone_gen_expected_big.ml using + extern_standalone_compare.py, and read it back with + extern_standalone_check_big.ml. */ + +#include +#include +#include +#include + +typedef intptr_t intnat; +typedef uintptr_t uintnat; +typedef intnat value; + +typedef enum { + CAML_EXTERN_OK = 0, + CAML_EXTERN_ERROR_OUT_OF_MEMORY = 1, + CAML_EXTERN_ERROR_INVALID_ARGUMENT = 2 +} caml_extern_error; + +extern caml_extern_error caml_output_value_to_malloc(value v, char ** buf, + intnat * len); +extern const char * caml_extern_error_message(void); + +static value mk_long(long n) { return ((value) n << 1) | 1; } + +static value mk_block(unsigned tag, size_t wosize) +{ + uintnat * p = malloc((wosize + 1) * sizeof(value)); + if (p == NULL) abort(); + p[0] = ((uintnat) wosize << 10) | (3u << 8) | tag; + return (value) (p + 1); +} + +static void set_field(value b, size_t i, value f) +{ + ((value *) b)[i] = f; +} + +static value mk_string(const char * str) +{ + size_t len = strlen(str); + size_t wosize = (len + sizeof(value)) / sizeof(value); + size_t bosize = wosize * sizeof(value); + value b = mk_block(252, wosize); + char * data = (char *) b; + memset(data, 0, bosize); + memcpy(data, str, len); + data[bosize - 1] = (char) (bosize - 1 - len); + return b; +} + +#define N 10000 + +int main(int argc, char ** argv) +{ + if (argc != 2) { fprintf(stderr, "usage: %s OUTFILE\n", argv[0]); return 2; } + FILE * out = fopen(argv[1], "wb"); + if (out == NULL) { perror("fopen"); return 2; } + + /* A list of N distinct strings "item0" ... "item9999" */ + value l = mk_long(0); + for (long i = N - 1; i >= 0; i--) { + char name[32]; + snprintf(name, sizeof name, "item%ld", i); + value cell = mk_block(0, 2); + set_field(cell, 0, mk_string(name)); + set_field(cell, 1, l); + l = cell; + } + + char * buf; + intnat len; + caml_extern_error err = caml_output_value_to_malloc(l, &buf, &len); + if (err != CAML_EXTERN_OK) { + fprintf(stderr, "error %d: %s\n", (int) err, caml_extern_error_message()); + return 2; + } + fwrite(buf, 1, len, out); + free(buf); + fclose(out); + return 0; +} diff --git a/extern_standalone/lldb_external_printer/README.md b/extern_standalone/lldb_external_printer/README.md new file mode 100644 index 0000000000000..cafbb02b55f26 --- /dev/null +++ b/extern_standalone/lldb_external_printer/README.md @@ -0,0 +1,82 @@ +# External pretty-printer for OxCaml values in lldb + +lldb can hand an OCaml value to a user-provided executable for +pretty-printing. The value is *marshalled out of the debugged process* by +lldb itself (`OxCamlMarshal.cpp`, an adaptation of the runtime's `extern.c` +whose memory reads go through the debugger), then piped to the executable, +which demarshals it with the ordinary `Marshal` module and prints whatever +rendering it likes. + +## Protocol + +The executable is run once per value: + +- `argv.(1)`: the OCaml type name from the debug info, with the layout + annotation stripped (`"Env.t @ value"` → `"Env.t"`). +- stdin: the value in `Marshal` wire format (read it with + `Marshal.from_channel`; open stdin in binary mode first). +- If the type is recognized: print the rendering on stdout and exit 0. + Everything written to stdout becomes the summary lldb displays. +- Otherwise: exit nonzero. lldb falls back to its built-in OCaml + formatter. stderr is discarded by lldb. + +lldb kills the printer if it takes more than 10 seconds. + +## Limitations + +Values that cannot be marshalled fall back to the built-in formatter +automatically: closures, continuations, custom blocks (`Int32.t`, `Int64.t`, +`Nativeint.t`, `Bigarray`, ...), abstract and mixed blocks, unboxed +primitives (`float#`, `int64#`, ...), values optimized into DWARF implicit +pointers, and any value whose object graph contains unreadable memory. +The marshalled output is capped (64 MiB) so that a corrupt value cannot +wedge the debugger. + +Marshal is not type-safe: the printer must be linked against exactly the +type definitions the debuggee uses, and must only demarshal at the type +named in `argv.(1)`. + +## Building the example + +```sh +./build.sh # uses /Users/mark/dev/oxcaml2/_install/bin/ocamlopt +``` + +This produces `test_program` (the debuggee) and `printer` (the external +pretty-printer, which recognizes `Test_types.point` and `Test_types.shape`). + +## Using it + +The recommended route is the OxCaml plugin setting, which keeps the +built-in formatter as a fallback: + +``` +(lldb) settings set plugin.oxcaml.display.external-summary-executable \ + /path/to/lldb_external_printer/printer +(lldb) b Test_program.process_point +(lldb) run +(lldb) frame variable +``` + +Put the `settings set` line in `~/.lldbinit` to make it permanent. + +To see what lldb sends the printer (including the exact type name passed as +`argv.(1)` — adjust `printer.ml`'s matching to taste): + +``` +(lldb) log enable oxcaml formatting +``` + +There is also a generic, language-independent mechanism: + +``` +(lldb) type summary add ocaml_value --summary-executable /path/to/printer +``` + +This registers the executable through lldb's ordinary type-summary +machinery (it works for any language; for OCaml values the input is the +marshalled value, for other languages the value's raw bytes). Note that a +summary added this way lives in the "default" category, which takes +precedence over the OxCaml plugin's category — so if the printer rejects a +type, lldb shows the plain value rather than falling back to the built-in +OCaml formatter. Prefer the plugin setting for everyday use. diff --git a/extern_standalone/lldb_external_printer/build.sh b/extern_standalone/lldb_external_printer/build.sh new file mode 100755 index 0000000000000..f377ddd8923c8 --- /dev/null +++ b/extern_standalone/lldb_external_printer/build.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# Build the example debuggee and the external pretty-printer. +set -e +OCAMLOPT=${OCAMLOPT:-/Users/mark/dev/oxcaml2/_install/bin/ocamlopt} +cd "$(dirname "$0")" + +"$OCAMLOPT" -g -c test_types.ml +"$OCAMLOPT" -g -o test_program test_types.cmx test_program.ml +"$OCAMLOPT" -o printer test_types.cmx printer.ml + +echo "Built: test_program (debuggee) and printer (external pretty-printer)" diff --git a/extern_standalone/lldb_external_printer/printer b/extern_standalone/lldb_external_printer/printer new file mode 100755 index 0000000000000000000000000000000000000000..2b3b1020166652463195221ab387ddd9f1baaa64 GIT binary patch literal 1284840 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 z%0AiBu{C?U`5Vzq=ACD4Ls@&CE&C50feiHHq!N`gr#Sb8d0jdASii#F;m!!^lCzxR zPPJ{$?P1ja7t-(<>-FbScP{&Ig|J z_Yk!81hERDSgq$6ywnNth9b^TFu(U_@7ZC9KHI7 zeeX2iB{%Hx24CX(XM+oF*wN2?bpzwQJIVFxjJltV-I{K`x|RDq(}rHMCw=IRbzD!V z361p?%Z8h@PrP1j8vYsN3rw1-_V!$7Uh@81?n~SU+?Q-O@2{BsyC-k@*VLq`+kFpI zqy9Bta0<4OV41)9 z!OM!9&wVHVh6;Z3_^se~?(Y1l75wJ$TfuKcPv4DK^1F@SBm6c|X1B_bhpvL(Jbo+q zePca)jAxJW>@l7_Hg)sh$ERlfCI5y;UpaT`^IWfb<-DoCkR=+ZA>MvdyKJ~u` zKQVROYv)dVoB#jecg<_(O}*>2VN>7Xdev*gr~Ym5lT#1z`yFM*@@^m3J9+;l{}sF+ z^y-MIgI^svwg0Q5rVe;@^wfESADenJzqD5_n412|*r~U0J&^Y2^538K=P>pMFEg4S zy3lMUR^Ebl9eEIdcSZ7!_1M*u`Xn3C<;B?7-~YM)`iURropsOE{C=6&_a|IG&h_J5 z|8-6A^*gxlcP+ms^7`)M`dqHh<+|kdsy-#Z-E+fC{%7+468|sp|1tj`^ItId!yASS z{^*9JlQ&HL!{DkLPCfbQsUPw0N;R632Aa+9|Geb-4_8jO{vzspiS}Niz3aICnCp+Z zZb)eN=@Ybj5AEGUdyn(~xYh1oY4_tBP8s~g4W|y?M|&>XbJN~L+Pm`(4L3(ytG$Ndz1eO?IqJ*3hhmyy^H?|?e(U;RN9+Ldzbt} z?KOg*26$_Lx82u;gP#S1ZM<})_Gw-Ru4?VLSsRO46MlYfvv0F!iZ6h#tG^d{$rwj2 zZ1zLcbj!!F7C8i3ZpAJfy72`oU%;y~jTHy4J9f?oJ6=mUslS`wWFS7!=irrBA(utq zl^*1>1MsBx@F6xLm$jmMIJ|Nzyi)l`W5l{WZPuc(jWne9C5?oU2=oxL|q{Z?FlQ^^ENrnwvbs@#xvOif03 zBs!1YAwwbargt(~Q5B?(`yn?AaLZ~RPJVEl(XJNIuPep{oi_`#}mW^l#}CbomxCwGL2}}-4{g-Vu$2!yx?E$cp;6Y+BFHgUeZ1z|C)nKfLkTy zenQToMc?)ewaQ+J|KSesLN+-0i>+t)B6RPnyXs&JyW!*~OG1U%%X7_?j&|T_`DbH` zcFE>DsBY;hKYf<()WoMTnSS|^J^lEkf0${+%JA{&TiFv9c|9HKgT7zHw|kHaO7Yc} z@_jOSYYOv|S7%lkp^Pickn&G?(Sv=d=>wG8kTaC#miJ$iv$Ur%jJ)JU4WM|EGf%5$d}zjto%$9ADpO4haH*Tp%}gTR)& zRYC2s+QxpXHuvJOO*74%ks(HGvt(e-w5bEuPWcfg`_J47YaBb7^yWl)xcUUTSE4*D zU-ThknF-^IR)K9H*5BJqvdrvKn?HOPU|67L%K(5)c)WPI#LWcxKmTp9>Mg*W={#glkdSJcwO@+_yUqKnHF^pNh=7V{`_%9dVDe z&J|hX9@McH+oED|)-Jx5_<*!<&S7%ikke`b=LhM%V!+=x+_{nSJ)%0#NNarp{c_g( z=F5#0I&aQ|Cj4?b_GPZeDE5vzYgoI!`RrxUzK8|HGSl{W#Wzu>*17Mig}dyvUe>kN zXYIGw`uZo1Uc=!57A{z8IGZ)x2)!=sm2IuzYY$)piFR&mL|5F5tvn>!Pg~D`&sxL2 z1D(_Kz1DEc*R~&HE%PaQxd|OcK8dU(?5!#6+tL|Me1GtV#i7#FBX->|zTfpOGdSnD zHI~n;5j<8t(QW9LiUE15i=SZAB{$kr^e@4tJMt2x#=F~m`a%=~$Cq_L0Ok{TrW2aPq)&Z{&Hti1Jp|!a$$ygyDudb^KjNn%0 zRcnh_`7sXN4gH0T2ku%v{Yr2LSQ9_HU2xSo zKQ8*~!2Sd9>qGc&4`6mGe7use9ps!Y{RgS*9q8cU1yi7}lcBTa(AzTTZYi+~lS0s8 z%jW`r+i)xz{tn~rPQ$D48Nb2v6Y+J$#}{O=K6+zkGRTL``FXNw$q$zaUCF{HoXwd$ zIplm9gnevqFKmpw6RwvM16U0Wn!(&wLx=SJI`FMJZaemK?FCU+ z(zh~K4i3!XTgNV@n4VeCyA%0$9iP~&1pjVLmrsoRUCh1HhdkD=`d34pWv67WE&{L0 z4~`l&RIykGiN#vzy*vOOun#A;2%629rcF0by2sGbedb9p~7g$CmdvX#jh6<}P)wroLIx#PUC(`~&n= z_7h^0mn+}sTIiALCqK%y zcN>)24Y7CA3tba0m2GcmUNP~mUT8y#m0w$XPYUC*QU-Lk7C5%{%&_RJfgGkiFtsit z_HeT8zYp==$NIJ9C9fqfsSeTFt*p@{&}5aVQC?y2AemnZ@g%d6z2=Pik1krO@5`a1 z&8ly!fekO!iY2+8`)2z06!Z9=H}j@^=ny%p$Xk_j-c!J;5jb5BoVL(j8S=v{;B-IV z+`u=@W}mKF#{FGgIw)&t?764zj}-<6J}M+Kd7AvsGtzn|2!IEx*P8X1we} zoa3c=3F0T$ztgAF8agwNM~6=oFMBL|dJFWt`(C0nbX|u>ZA&sn?WW9bVrJhU?raVE zZVPnO(EcJLy`z%rdisXGvF`BE+94ez|)LiRPjDqT(@n zhx|L&M5cf?SaPf%7%INIk=)(8e=a+^=<2}mHSj@)_O-D8t``+!lKyJeiz1riEV1kj26dhV?QX-D z##)Iz1ie=q(j(J_=d4lrWCbTZ>&r92hkOQ`s#yc|tmB*UnQ6^+x9d226og+{>K|ov z=2+*1q@C?UQaFdIH!@}_vSuG-&c5jM{m|)?&XaY&zOf<&5I0lPi9M z43*6pRh)C>`L@$KC(F02^5ndH&d6dc8RWRo+^)^7tq3!RZNQUtbJ%(IxSkO&@6|Kx zOeSR;c_!ITds-g@e4N1S_P z+s1XAZ{ys1xqrb3HaPd_|BdhCgLm$cof^@J>$$%Lyma`>z;66yNEH1X+Vi{kf5ijh z2WjE2m5UtQW={X^-j+x=x)wea`y;qz%fOd{&zFGLQ^D_x(VwP-+J{WO9=t!H4kfzQ zo!-g!x7VR}h5dr-v2Q%f&!T^G`UO{W-8sRvGdjHo?e(Nx@@X&du#Q~8#>IoX){pqH zat#TO2Xg%^Yv@2P?9!}>Ci*SB?aDXwft_#Y8Swo!;1T&d`2NqfZ|8vTPM;F-Jp`X_ zTKuD^@ZWQ|_(AD2(!aD8{QPT=B;BXhn7jx=?{k$iCESzv9`%2MWP5_5JDI6_Y03HIKAbj9s@V3zzx|*EnFxa z5X^G$qM?6qAlGL&_tAdA{=$(E+AyBgR5|(F%#LmqgI13C2#@UtG7un9R;IIO*PP4}6jTbR2SnM3_wYt5Z4 z@BKIS4$-DozLOlIe`mdKLr!{mfNjrtOmsB9m#tNM**vx!(~4Z8I-fd)KJy=rw^2+R zTb1{qCEc>){TuIVwQi7y^T12>-SH1Oe4-w|P(AWPVS*gkJ!WTVmwaLG<+5Y!PrR3F zX~B`0oh1c!%#LK&DahVVpK2{z2>nBDCl8h-qmTO+TQ<9eF;z0Q-i*nfwBuS3*GB1WZA&p2gd3{bszX1@_!9F z{t{$5$@n4Kn}x0q{#o|wbnGaaUq|16io9rf=D_iBesQgQ%sDtv-Z8zC;3nQ9Ocyyflsy!ckkGc+qHA=5En9B z&yXeeO-~9*rrYZ_V*G-lTQ5U{+7{Q2ZFeK<;R8uWw%7=N3@^@#Hhp03Y~_8U`_ZvY z@IIZ@J`MP9bQvRSznvbHOcT7ObEWtxv?f;1SUl1RI6G~r%Nr=Cu5x?|>)|Q0YJ8So zVF~2~d)c2Q|6cuB=gN(|kI)~rwSR~atEFDm{ck^lw*a%yIzPE4j`;Gt$UCA3Wj(ys znSEa59bI=!vg}uuf3K*=qG#H;NGmB*_RKkNgpuF zOfH(;)41#m>J8*?&+(m_Qsnby4sd*ey}`LQd}@2}v!1=MbLF$I`$Jn~TVp($&o>La ztG9rEO%?w6o?9{pG*uY$>*M;R^foW`o&o-791gwP$~urwL-e^G-M5}K(sUx4$9qQy zo`DX$l(tW#1N&J!$J!_1==G7zH94vDN%O$|*Og9x+u2X7T!6{gKBvRORIY~om%3iN zmow|Z!AAOC&mMl!mL_8Jkoz{aVz1qXO~lFL`7+l|9#74=!Pze0=d^m(?0f7vEaCcL zU{>E}LR9xJe2fkb{OVnWqqHU#B_p5ktk9J=3RykVfpsgewtTqgg+BC0`OzFcY%u2f z2TG#3W=2QNN4Bo6x*m2JvD2xeJMA*-U7=FL3>e_-E#%y5V;qtNMF;%g`i4)DeerQE z<;<5^6=rA_{k80d++(X@eIK#WS+xA!lY)zS9myqN46d!1PQ9WdvcVZf&t}8u!7quQ zo1crH$xml+*!c#!_c8a73$WS!Sw?>r(Fe<(hs|<7vRmx~6QYam>KUq}zxVK7@77SJ z)_LD&QgqF?u8_uaC-3!6WxC!!P;R}~_cwR@Ub3Mx#_K;tM@64J(Y_&vE(tFrSL;9P zLe>bhKz>P!&VxIC<|Lor#r-*_0z5e%U;P`ua{sWqps=rFKaCtlNSE{V&t8q=&0OI;OMsD zcs}FIMOL%s#BDTxg*~SdIOZ<0;dovg4uW+haJ1e7$3<~C7V$oD9*m!tM^(RII3)h9 zRX=qf%l7Z=)oIcBC(}j*za%#0c=npNfKQaQk5S@_dB7)~Z&m;w;MA}Q_*ii2f=^ob zRq8qdpLF0O|5k?lTd!XSd?M798;8&FY!lsa@L2Qe(Y!*>K+cVx$BW4qMovKdoU)I3 z$SvjZlK(JPysL&Bz+Q3yx03@nL=Irj!fmV5$pO5Evsqt&2526I3orLGR{WB@H8%#p zQQox?BjVtmc&n42V>M;8R(=xr?s`t2$XVl@FG#&#lteSE+yy53H!xdaJzM5mgsu|uC_e*R8|Haci z3)5GV8*CSI6|!XHQ%(*VwY3#LX8xL>KOVmE=3(!B!Ug|J3L2E30>3oi5&FI|PNRPI z3HB)Ho9I;X73r&IU3r8~dARp7F3Dikl(*y{WFRm8!|GYSXrisy$@2wHeqlhzE~X!e zcrf-|`%I}_y3V+3_p8;c`qBFAK3n}FS&JiR>U*iCo{K+v?MMs<1-x) z6b{u0hw3`n_6F{Nr-g>0IQ9+RYf3D8qW2n??m25Q&xuj5_v|sPa|cydcireKc(vlz z1gGibG7%3ps8_yc@w>a~q4mgt);NyS2l28(4W+szFm5FO?_#+ANT;~ z`f2Ar>fXw?`F=ZgLHU+Gu;}O!eZiz3ofCBCWnX;B{gCy(Kt))L!|DnB-m+>jaR$kpSE0cGozf)!i-xl+o;@}4JQ~5!hV~ZSgS>*Fxp-(0mviqeUgr`&!1Nez#&D2*` zU9h(I>M`)GHSXRWMjjb;?}|jnn(Xya%_1KRfb!pK9SxCSx&(duZmJ=0&zA2tOI0 z@KEK{uKFvSwfbkAX7%rL{QY_K8tkQhvtWx((>#S0*+tc5-F!^$g zwXK(NxIHBfvpY|-@+ow|AnSCik1x^3B?ZNydgONH_e}=ZN)ML?unq1iOvNXT%p)2( zM*a`}cRCbD=faC-?jHS(_*-50s8 z1a`OcZ!o`S^8e7OwH41$*Sr_zUZ?(%KsNIy84t$O+HF5c<>$K1>Ae4_sS2W6c8t>#+&>%+RQr(fQM z#CZXWLbE=nhPK-cW4QVQ9Ol+RKO7kJ1qK?=SLmq4)UmP${s{ERugTkD;Z?s}YtF9G zoI$q>$%U#Mozkb?XIx>%U%vLd;ACiTZ`$qyJ^B-TtvB}pbk^P@{Gny3seu4CN0sqZ ziC%jxA8K#(=rv|aMFLlm|u4KT5I?9Ecz-quV5YPeG26sWc`RH?1A2$@;312`R|?YUa`N+A)?_p_lUul(RLD^9$tLuHjjjU#@}9 zc~1F3_M=Yol4scWZ6~oU;)C!_VkKoaQF|JX`m=}rqffJeZ^yTtn_A(!OMc8eD)!{Z@LJs; zh~FQudFNK1oyFcXr+)P@LLb$)-_o}h@a1}^kHhn=KJKKCg89mI(sgPpp5lEYcs$c7 z_l8~WzbN+*^{H$+^ceYfhb<=$3`_nkC$7|bhMX)PlH}wIooC3&jd3~I?>s|JZj8&x z7w~KiaVQTcXMTGJZSe-ZPpbvK=HwbS1%oVAh0 z^MAyC-NCqJqt;#)`+S0<{Ut8~@0q7$1^>YRJ&$As|H%L2gR?Dt&IL|`Bgon&cG>Tq zXX@x|vY%c_oPgp7WFr>*Yw?XmvA^Di3?$u3c4FC(wRQ)hi#2`QmmFinlRy1XSB_`t zZ?X}7iX2r54Um0eaEJT`*cyn7Q9X)BBNlZv`$1OMtV3>dWo-A5_qh5AGlUG4?!eDO zpCn)CU%DW=^)7GT(fVNPUaj||^+9*LZL>O-E_jP&vpV|B&?E5(E?Z^;_dh1zQKy?e zTjNO&Z)QBz&?VW}k7YA>_GHd*r@Xape_0s(Ps&@@=#jtU+M1*4YmR{8M&oPF zBOijDPZ;{h^Ydt5IFiIU+4}Bp3E%0Pp?tH4z96@R4VSU0nDQ!jD50EFf1c`Rz3idS zD!=G0_gp`)TJ$;RccY`Va(4GN&hRec?C$a8S@)PrSM6m^s>!iQy_SDqx|!2az!=KN zc|IALvfM}s%yy*&=G^O#PPx~Jq7Uy|3vWg~-l({hwN{*pe>vZ8Ec~K#qw2|`kBP9K z25zhXH;y+4Ud;hxmENxXSd%UID~IVo3-+bJUNWV}bO%bQ-#I(?z*Q5$)d}Ei349P< z^`f22M}4TLd?`HVL1>8L7>AHMK+gqhJ)ho}zJnu*UoG_*v56jkYykaGnR4RbKfo6j z`O5rF^%W0&S-P+ln^W;F53#+arf0hsxm^C~NU!=;vhNpAPZ2nFGT&=1+<)ur(tD)y zh%cO|&u=`^nK_wr5#}HdU5x!hbv+>2vMx8O{Blp3M(hFjz*ESk<*CG|Adfclv*M6h zC+bV3;=`?)e+t0zHzgc%)5F2yDmOu3c%FVpr-}6PZ*J{n3~!=+ z$}zcHRuzY&M|x%Pu zL1XRJ2e$*81FYfqsb76ooYejFnR$XAXLRI&$L)R60)>YUv|9b4pYJlBWbmsT*}fe8 zWjgvxn_`0~r@G20E8kKZahr-4>SPRUDgMoWFBj#B_GWyIOb~;|%f_fZc9J2K1EL8T z@v3*rcO7KkPUpAgzG~=62zermJW^hj8Z554W3+F6RTNnm-2;CnWO99<-@06gRKC18=TG>ZSS>Y)gtJ{4Dft1eUsjMhTFUSPj?%^ zK8;3D&wg!AkG^K+Mt{xxyvF+f^}WT>*X}i=vsw4jJB6>R3tB&IHn={Ey-(%H*V~Ul zqeCVBF-wSVe(&zwXe;YLboT86W2ZN-wqh^xs;_fz>vS`#Lp)3G$9Jx2^>$9$*Gzt>s@U6-xQJI5XlIR@QCb`yO!B-uHfVo*3ypee_Kn z?%q574?S#D1MsQi-p~7+c=sW(Ym)1v zBkWNeTY{b}+_c7@uldpUk_$cID!%hmcQOCR@?klC6Mc^yj2~99qes5KjPGDYY{F-3WNU(*d+Rop?+zZa zP6viJ_B1w!XtRlPas2P2A6ZX|)fbG6`8P+ep)F*YU^V9;$@emu_7_oaB2Ijt`Yt?9eS)`B=h%;q_8B*6 z&DWJ!@hcm-uD{zqW*F&%(RRRR6Nh3SI&(QTN6+;(T(G7JbS8v_{Ua z7j0}jWdG;I?>*?KI*%Za_KlMkJ)<&(`|sL?yt>?|u8!_*>C7x;4f=TI$@nkab3XyE#=nc+3OigBvp z*`AYYEB?$kP2jDkU)z_Sq@!up_(Sfw#mLy!y!1Oe=mn0QFS?15Nk*Sb!S>J_+e0e+ zpbz}O9pA%oL8!4C|8!!{L(I1ozqgq9y&>%1z;4yPJ|4gK7vlFO5Wj~Euos>e#wO;( z9=8u6evf#Tbop?A+nT@H`a9>n?aD+3Dl{^;H@OEzb*|sA|1RIPpK(2dJ;B4?bjgQl zJR8RSn$O&GUF_e;WW0sUvlrZ7gl(eV=*RO^4cql)NdSq9A z693*$xGtjnWb|_%y3=%Yr_r3b=Ak}ULOn}Zv#Mv!|G4Mo({7Xdhf&1}6=FlEM$mL1+CRsx>iOC;k zu%APFTlsg}ang!;jktN%mo>yU#n6VAFQeZ>Y&)~ZFk)>(RHtB84$R7clf4(=SaP=f zOZeuN=k9dxtFqTa1^i^k3K#yXli|OtCFp&_ymi^ZrR?XM4o*up*o#k{TnW!~@c;6+ z9j%M7J6m*2Ha_%_2y|F-fa>R5&gIjo-vED-!9n|s9O)xzVfpPPN663cHS^WV`u5a1 zH1)gk?)M$T6}kWS$57jC4B`tX8bc+xn(Og@=?6x_6NfK(G!N~}1Nd)%7kVe0!sfcM zk^EH08hbMEE!B5#+w+J1(lvh%#ph4B<;-D#Ib6gX`r$1d3L}MGrcRvwoepQmqwiFT`3AliD9YJ+xz}nVd3vp_#_@dA;AB9lhRbT(-tEJHlI+ z=J>V-a)@!Cjo)%w^4m4IPfW{y&sZ)qxEEXv=%D_cwi}6iO7w|IKP(Jlzd6 z{tnMt^vGJ~mbd`>y%9@>W)%eudp`{{$LX_EuW;L`Ti;0MOy<9gy2r=shMw&3QFk(R z`^>$hq1SsOHk7(2^DkSZ6*CSkwq<-f-qygLYT*y_<2iiWE`ykL-REN86Z{SK`sqGV z4(XiGZzuG_%FVE6g6vhEu#0vd9d5;}grK7h#_!J#-gyYQ&#nDM=z|N~p~Ej4mY#=f z*#Mqm8^C@B4TA0jw_Sz|#u;b2&Zpg0?rXWb#U$3^*$HH^iznT_if7i;3FXb8I>^@d~Gn8C1>cfh79~N={ zApT89X0pChebemvHd%VHeQs|Z->_CGYr}gF^;vEI;+)`m%KfA8siYnU7Sp&s*4W`) z-x+%*<8tt5%JKTrdQPxDq0b|aSMJ?&f_Ej98*#jHS?30CPAGTk@yeB+8=OVCMBM7q zEz!9~^PQi0R{RR_e6#bJ+sXnnScM%pTkkqMhj+n~F=11iku|?`! z-is;Mbx;25vTl9QoEx;Cr8acdA#Lshj__};?dP>8sDDJferukA*}2`?JCpl=WZum~ zYwFdHvnk&O-oK|l&==vsF0TJk9C-MWqhnc}@x4PGZQ!Qr{5{vlf|-M>M&g*5w?pW3 ziSy>E?ffmW>Re!C=^N^ID|Pzg@LS6@?=1M~dF=_{_Yrk>%`5QR6Ti3SkNNs`$RF=XK9mv!Gy^&Izw zhH;+f(4KnPo66~vMe~=GkY5J+d~ZoCnOHMyBORWtOIGD3E$#5I@7_B17hOSTYUi1r zrJ^VD*&n#dh3p00T#!Uetj=|kz1;}kcfL&vnVXGYy=9OS%hI14^4~qzih0|Al@(Ln zkpI(jg9h<1UiLTIGU*ZDx8wIdRy#+XD;zLF%!PFEhWtyTZkI*Ghe!Kb>ds1NBksUNF-b|2r;2+x07+YP&{QYbEKG!?)+)3MWc_7;dpAQZI4Xklb-kQsgPaGQ(K?o^*>rs zHt)%sWK&DWF8pBfw3NuC`ih9zc#{{|ide7NGgx=%J+poM7vcl;!T-rcy}5loF&6Y2 zTxl>i3=0+li|Xf>RFw8!cT@dcO{7ftRF69r+=!hWurq|W3iU7y`;JErGzrJ;LZ(eQ1kAPQXsN{$AKxC*93&7hqQJ3mD z0If@`CnH|Zfuril2)n7LysMrJs~-9k^=!Izd9Ina&jgP3*v^#83S8aD{EpJS;s(g^ zKU~ivr(eh!P2P@m%qjE0UPF8{#JYOfL#(<6VOQAV8q_g^oMYEe{viEBXl&SBKHNT+ z%*eFbCI2Bl#heae3Z_kW5A4`R+igQG40%1sbEdIfa?MqBkFI))epq-tb~rgnGs78- zwM}q{*Yn67cSJpI zRad`i6uxiCc50^+IH{dCpl6=N(?@?Zk8$sF&)tgr-{~4`?PG~x%hX(yvX&#{*HIbe ziCIn?_3q5=?ab|Xb8tsC^YOMd7n#hdVy&{nA5*`|M_k#=|KJYQBY2f4=XM;fWujxi z71=6NZO*{|>a-b2vDH%DTyyCNMp`;76>3AF>{t)5*)q;z!O`wj?I)@KL zM_2*g+(O@;XYD<6F>4*#eyn&bhxS-&_3Gilc|W!HrAtR&jb1Y%$=IZR<-m*8*Y0c0 ziq&JiW!4c#I-jxD#n=6Z!-JL7Rm(UH-b=pzUpL@e#upW$uZ5J8U#f6E^C#InUv>q5 z41I5tcndV^i~Q03@OLRbOa74bu+aEFIN8x7FSgqPRrq|1;+t9mD=x@;zE@ z#N*amyYS48L2+W%rDNJ>>)O7z51DgEXE<aIM)^*Tzvd}iJNF=lgnkDQCr>D*t8XR zr=cG!w(T|Mh!~L#Z5PQe#M}^j+(bK(ONq&V$8ZfXKc{qy9bzKXIvTJ zN$d0e&A;V)?*hg*_oT~x#b*Cx_+zrG@uotbXAsV%4TY1<&21M!tIlDqQeUy3y%5yX zm=d*O(efwPZ4S`47VdQ|-FgPF8p7{G@J+F-f91W^-*wP4;;*z8PT|=$+D~3kySZ>- z@}LyjkF4{@w3oRzaRsjsZ=9OU^(G@U1>0ipkQq|nd|q#g@A^9*RDS>D$6X=c)}aCK zNk(iN<=e5<$;PRYDki(S@UF43NUA@*xHw&-+XTEAi(^{h89FgCHL zR-eodpRtepw#G@`!25kU>*_yb?&IjgHM~%;EnT2@-2N|w7|u0$gTL~cwbGf~;J(wp-EGAA)BfLEUx{NTAIL_FHYCJFd!VZ;h!5l zrn65lD8myk3s42YDdmycbM73-M#J*Uj1wN9>U` zS9hNr+%rrvZ(3M$_1jyz=4#W4@bB-%uQ{~-{a$9MjkbVm|18$p_kr!^IBfp{Y)2AP zT8M0(lK|UHV0*}wvvi<2c>8lB*+=Kf>S#J|&8jkY7V*iR00Y`k4qS%nZ%%JHW-{f7Mx3j|S zLyJSc>wmP%_s8Tg?S!lQl4BcKKSMot;}NIyTSL9#FGu z52*al@`GEl{(M`8sAQc!hmTr(qA_8uuAu#Ad3GByC@s*7NutgCumA7Pm0MW17EZ8k za_Jj>u(`;k(46nu+C`(gKR-PGXx^$ls&&@)c0PeA-^%CW3co=g+klJg6_e1dZ5_of z^9gk%(gUYI^37HY&l#)MoDbSs1RXCr9BBoA_o*Gp9yWck^+@a6VrXc5{d>x6nMG^= zM6qz{m-N=}gO{7)c)1(Ad|q@?_M`;790Xq8=FVE0ZDwxo4_=NZCe6p1_w;qve9m{) z{1o?~rLVB&uVu|YZ>{;9qt<*OYrgf4QPD#1Ddenq;?U$TEX!(p-4{#?zuYG?fUFzB zFduWu9BU10ABEtO2=7whZNt!I?Rm>R+}=7~eoJ6o8He?gtd*|sfOTsEtTiuf?6cK- zXl{l6zb}1%^yV(wvoVi4j)xnqC%}z877p5WTL(wxBag~-ALkcM#~F8GJ(cnC zU)QZ3(ZB;&^+1p4i9St!winG{cRWgmcRYkΠ54$AysZEgxPzemQXU3u7U<4)NtR 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
M74X`uClux2Q1; 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

(1JF-L+}5c_P_l75nL% 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

    Jw|yiHSj|QZuq}pqrvwX_@sg3$1|>GeK)8F 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 w#?9h+1dVYF`IEtcwsx$ee%M>IgqB)QIX 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
    6h!+#f%mj)$1Po$+Un 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