Commit 8c3f6c72c0

Jacob Young <jacobly0@users.noreply.github.com>
2024-08-27 05:37:03
Dwarf: fix and test string format
1 parent 93cb44c
ci/x86_64-linux-debug.sh
@@ -64,7 +64,7 @@ stage3-debug/bin/zig build \
 
 stage3-debug/bin/zig build test docs \
   --maxrss 21000000000 \
-  -Dlldb=$HOME/deps/lldb-zig/Debug-62538077d/bin/lldb \
+  -Dlldb=$HOME/deps/lldb-zig/Debug-70b8227f1/bin/lldb \
   -fqemu \
   -fwasmtime \
   -Dstatic-llvm \
ci/x86_64-linux-release.sh
@@ -64,7 +64,7 @@ stage3-release/bin/zig build \
 
 stage3-release/bin/zig build test docs \
   --maxrss 21000000000 \
-  -Dlldb=$HOME/deps/lldb-zig/Release-62538077d/bin/lldb \
+  -Dlldb=$HOME/deps/lldb-zig/Release-70b8227f1/bin/lldb \
   -fqemu \
   -fwasmtime \
   -Dstatic-llvm \
src/arch/wasm/CodeGen.zig
@@ -3357,7 +3357,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
             .vector_type => {
                 assert(determineSimdStoreStrategy(ty, zcu, func.target.*) == .direct);
                 var buf: [16]u8 = undefined;
-                val.writeToMemory(ty, pt, &buf) catch unreachable;
+                val.writeToMemory(pt, &buf) catch unreachable;
                 return func.storeSimdImmd(buf);
             },
             .struct_type => {
src/codegen/llvm.zig
@@ -9412,7 +9412,7 @@ pub const FuncGen = struct {
             // repeating byte pattern, for example, `@as(u64, 0)` has a
             // repeating byte pattern of 0 bytes. In such case, the memset
             // intrinsic can be used.
-            if (try elem_val.hasRepeatedByteRepr(elem_ty, pt)) |byte_val| {
+            if (try elem_val.hasRepeatedByteRepr(pt)) |byte_val| {
                 const fill_byte = try o.builder.intValue(.i8, byte_val);
                 const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
                 if (intrinsic_len0_traps) {
src/link/Dwarf.zig
@@ -17,13 +17,21 @@ debug_loclists: DebugLocLists,
 debug_rnglists: DebugRngLists,
 debug_str: StringSection,
 
-pub const UpdateError =
+pub const UpdateError = error{
+    ReinterpretDeclRef,
+    IllDefinedMemoryLayout,
+    Unimplemented,
+    OutOfMemory,
+    EndOfStream,
+    Overflow,
+    Underflow,
+    UnexpectedEndOfFile,
+} ||
     std.fs.File.OpenError ||
     std.fs.File.SetEndPosError ||
     std.fs.File.CopyRangeError ||
     std.fs.File.PReadError ||
-    std.fs.File.PWriteError ||
-    error{ EndOfStream, Overflow, Underflow, UnexpectedEndOfFile };
+    std.fs.File.PWriteError;
 
 pub const FlushError =
     UpdateError ||
@@ -1401,7 +1409,7 @@ pub const WipNav = struct {
             else => Type.fromInterned(loaded_enum.tag_ty).intInfo(zcu).signedness,
         };
         if (loaded_enum.values.len > 0) {
-            var big_int_space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
+            var big_int_space: Value.BigIntSpace = undefined;
             const big_int = ip.indexToKey(loaded_enum.values.get(ip)[field_index]).int.storage.toBigInt(&big_int_space);
             const bits = @max(1, big_int.bitCountTwosCompForSignedness(signedness));
             if (bits <= 64) {
@@ -1429,9 +1437,12 @@ pub const WipNav = struct {
                 }
             } else {
                 try wip_nav.abbrevCode(abbrev_code.block);
-                const bytes = Type.fromInterned(loaded_enum.tag_ty).abiSize(wip_nav.pt.zcu);
+                const bytes = Type.fromInterned(loaded_enum.tag_ty).abiSize(zcu);
                 try uleb128(diw, bytes);
-                big_int.writeTwosComplement(try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)), wip_nav.dwarf.endian);
+                big_int.writeTwosComplement(
+                    try wip_nav.debug_info.addManyAsSlice(wip_nav.dwarf.gpa, @intCast(bytes)),
+                    wip_nav.dwarf.endian,
+                );
             }
         } else switch (signedness) {
             .signed => {
@@ -2566,8 +2577,17 @@ fn updateType(
         .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
             .One, .Many, .C => {
                 const ptr_child_type = Type.fromInterned(ptr_type.child);
-                try wip_nav.abbrevCode(.ptr_type);
+                try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type);
                 try wip_nav.strp(name);
+                if (ptr_type.sentinel != .none) {
+                    const bytes = ptr_child_type.abiSize(zcu);
+                    try uleb128(diw, bytes);
+                    const mem = try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, @intCast(bytes));
+                    Value.fromInterned(ptr_type.sentinel).writeToMemory(pt, mem) catch |err| switch (err) {
+                        error.IllDefinedMemoryLayout => @memset(mem, 0),
+                        else => |e| return e,
+                    };
+                }
                 try uleb128(diw, ptr_type.flags.alignment.toByteUnits() orelse
                     ptr_child_type.abiAlignment(zcu).toByteUnits().?);
                 try diw.writeByte(@intFromEnum(ptr_type.flags.address_space));
@@ -2609,16 +2629,34 @@ fn updateType(
                 try uleb128(diw, @intFromEnum(AbbrevCode.null));
             },
         },
-        inline .array_type, .vector_type => |array_type, ty_tag| {
-            try wip_nav.abbrevCode(.array_type);
+        .array_type => |array_type| {
+            const array_child_type = Type.fromInterned(array_type.child);
+            try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type);
             try wip_nav.strp(name);
-            try wip_nav.refType(Type.fromInterned(array_type.child));
-            try diw.writeByte(@intFromBool(ty_tag == .vector_type));
+            if (array_type.sentinel != .none) {
+                const bytes = array_child_type.abiSize(zcu);
+                try uleb128(diw, bytes);
+                const mem = try wip_nav.debug_info.addManyAsSlice(dwarf.gpa, @intCast(bytes));
+                Value.fromInterned(array_type.sentinel).writeToMemory(pt, mem) catch |err| switch (err) {
+                    error.IllDefinedMemoryLayout => @memset(mem, 0),
+                    else => |e| return e,
+                };
+            }
+            try wip_nav.refType(array_child_type);
             try wip_nav.abbrevCode(.array_index);
             try wip_nav.refType(Type.usize);
             try uleb128(diw, array_type.len);
             try uleb128(diw, @intFromEnum(AbbrevCode.null));
         },
+        .vector_type => |vector_type| {
+            try wip_nav.abbrevCode(.vector_type);
+            try wip_nav.strp(name);
+            try wip_nav.refType(Type.fromInterned(vector_type.child));
+            try wip_nav.abbrevCode(.array_index);
+            try wip_nav.refType(Type.usize);
+            try uleb128(diw, vector_type.len);
+            try uleb128(diw, @intFromEnum(AbbrevCode.null));
+        },
         .opt_type => |opt_child_type_index| {
             const opt_child_type = Type.fromInterned(opt_child_type_index);
             try wip_nav.abbrevCode(.union_type);
@@ -2660,7 +2698,7 @@ fn updateType(
                         .error_set => {
                             try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{
                                 .signedness = .unsigned,
-                                .bits = pt.zcu.errorSetBits(),
+                                .bits = zcu.errorSetBits(),
                             } })));
                             try uleb128(diw, 0);
                         },
@@ -2729,7 +2767,7 @@ fn updateType(
                     try wip_nav.strp("is_error");
                     try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{
                         .signedness = .unsigned,
-                        .bits = pt.zcu.errorSetBits(),
+                        .bits = zcu.errorSetBits(),
                     } })));
                     try uleb128(diw, error_union_error_set_offset);
 
@@ -2892,7 +2930,7 @@ fn updateType(
             try wip_nav.strp(name);
             try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{
                 .signedness = .unsigned,
-                .bits = pt.zcu.errorSetBits(),
+                .bits = zcu.errorSetBits(),
             } })));
             for (0..error_set_type.names.len) |field_index| {
                 const field_name = error_set_type.names.get(ip)[field_index];
@@ -3204,7 +3242,8 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
 }
 
 pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
-    const ip = &pt.zcu.intern_pool;
+    const zcu = pt.zcu;
+    const ip = &zcu.intern_pool;
     if (dwarf.types.get(.anyerror_type)) |entry| {
         var wip_nav: WipNav = .{
             .dwarf = dwarf,
@@ -3228,7 +3267,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
         try wip_nav.strp("anyerror");
         try wip_nav.refType(Type.fromInterned(try pt.intern(.{ .int_type = .{
             .signedness = .unsigned,
-            .bits = pt.zcu.errorSetBits(),
+            .bits = zcu.errorSetBits(),
         } })));
         for (global_error_set_names, 1..) |name, value| {
             try wip_nav.abbrevCode(.unsigned_enum_field);
@@ -3455,7 +3494,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
             uleb128(header.fixedWriter(), DW.FORM.line_strp) catch unreachable;
             uleb128(header.fixedWriter(), mod_info.files.count()) catch unreachable;
             for (mod_info.files.keys()) |file_index| {
-                const file = pt.zcu.fileByIndex(file_index);
+                const file = zcu.fileByIndex(file_index);
                 unit.cross_section_relocs.appendAssumeCapacity(.{
                     .source_off = @intCast(header.items.len),
                     .target_sec = .debug_line_str,
@@ -3602,9 +3641,12 @@ const AbbrevCode = enum {
     numeric_type,
     inferred_error_set_type,
     ptr_type,
+    ptr_sentinel_type,
     is_const,
     is_volatile,
     array_type,
+    array_sentinel_type,
+    vector_type,
     array_index,
     nullary_func_type,
     func_type,
@@ -3913,6 +3955,16 @@ const AbbrevCode = enum {
                 .{ .type, .ref_addr },
             },
         },
+        .ptr_sentinel_type = .{
+            .tag = .pointer_type,
+            .attrs = &.{
+                .{ .name, .strp },
+                .{ .ZIG_sentinel, .block },
+                .{ .alignment, .udata },
+                .{ .address_class, .data1 },
+                .{ .type, .ref_addr },
+            },
+        },
         .is_const = .{
             .tag = .const_type,
             .attrs = &.{
@@ -3931,7 +3983,24 @@ const AbbrevCode = enum {
             .attrs = &.{
                 .{ .name, .strp },
                 .{ .type, .ref_addr },
-                .{ .GNU_vector, .flag },
+            },
+        },
+        .array_sentinel_type = .{
+            .tag = .array_type,
+            .children = true,
+            .attrs = &.{
+                .{ .name, .strp },
+                .{ .ZIG_sentinel, .block },
+                .{ .type, .ref_addr },
+            },
+        },
+        .vector_type = .{
+            .tag = .array_type,
+            .children = true,
+            .attrs = &.{
+                .{ .name, .strp },
+                .{ .type, .ref_addr },
+                .{ .GNU_vector, .flag_present },
             },
         },
         .array_index = .{
@@ -4132,6 +4201,7 @@ const Dwarf = @This();
 const InternPool = @import("../InternPool.zig");
 const Module = @import("../Package.zig").Module;
 const Type = @import("../Type.zig");
+const Value = @import("../Value.zig");
 const Zcu = @import("../Zcu.zig");
 const Zir = std.zig.Zir;
 const assert = std.debug.assert;
src/link.zig
@@ -589,7 +589,8 @@ pub const File = struct {
         fs.File.WriteFileError ||
         fs.File.OpenError ||
         std.process.Child.SpawnError ||
-        fs.Dir.CopyFileError;
+        fs.Dir.CopyFileError ||
+        FlushDebugInfoError;
 
     /// Commit pending changes and write headers. Takes into account final output mode
     /// and `use_lld`, not only `effectiveOutputMode`.
src/Value.zig
@@ -192,11 +192,12 @@ pub fn toBigIntAdvanced(
     zcu: *Zcu,
     tid: strat.Tid(),
 ) Zcu.CompileError!BigIntConst {
+    const ip = &zcu.intern_pool;
     return switch (val.toIntern()) {
         .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
         .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
         .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
-        else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {
+        else => switch (ip.indexToKey(val.toIntern())) {
             .int => |int| switch (int.storage) {
                 .u64, .i64, .big_int => int.storage.toBigInt(space),
                 .lazy_align, .lazy_size => |ty| {
@@ -214,6 +215,7 @@ pub fn toBigIntAdvanced(
                 &space.limbs,
                 (try val.getUnsignedIntInner(strat, zcu, tid)).?,
             ).toConst(),
+            .err => |err| BigIntMutable.init(&space.limbs, ip.getErrorValueIfExists(err.name).?).toConst(),
             else => unreachable,
         },
     };
@@ -326,15 +328,11 @@ pub fn toBool(val: Value) bool {
     };
 }
 
-fn ptrHasIntAddr(val: Value, zcu: *Zcu) bool {
-    return zcu.intern_pool.getBackingAddrTag(val.toIntern()).? == .int;
-}
-
 /// Write a Value's contents to `buffer`.
 ///
 /// Asserts that buffer.len >= ty.abiSize(). The buffer is allowed to extend past
 /// the end of the value in memory.
-pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) error{
+pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{
     ReinterpretDeclRef,
     IllDefinedMemoryLayout,
     Unimplemented,
@@ -343,19 +341,25 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
     const zcu = pt.zcu;
     const target = zcu.getTarget();
     const endian = target.cpu.arch.endian();
+    const ip = &zcu.intern_pool;
+    const ty = val.typeOf(zcu);
     if (val.isUndef(zcu)) {
         const size: usize = @intCast(ty.abiSize(zcu));
         @memset(buffer[0..size], 0xaa);
         return;
     }
-    const ip = &zcu.intern_pool;
     switch (ty.zigTypeTag(zcu)) {
         .Void => {},
         .Bool => {
             buffer[0] = @intFromBool(val.toBool());
         },
-        .Int, .Enum => {
-            const int_info = ty.intInfo(zcu);
+        .Int, .Enum, .ErrorSet, .Pointer => |tag| {
+            const int_ty = if (tag == .Pointer) int_ty: {
+                if (ty.isSlice(zcu)) return error.IllDefinedMemoryLayout;
+                if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef;
+                break :int_ty Type.usize;
+            } else ty;
+            const int_info = int_ty.intInfo(zcu);
             const bits = int_info.bits;
             const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
 
@@ -379,7 +383,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
             var buf_off: usize = 0;
             while (elem_i < len) : (elem_i += 1) {
                 const elem_val = try val.elemValue(pt, elem_i);
-                try elem_val.writeToMemory(elem_ty, pt, buffer[buf_off..]);
+                try elem_val.writeToMemory(pt, buffer[buf_off..]);
                 buf_off += elem_size;
             }
         },
@@ -403,8 +407,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
                         .elems => |elems| elems[field_index],
                         .repeated_elem => |elem| elem,
                     });
-                    const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
-                    try writeToMemory(field_val, field_ty, pt, buffer[off..]);
+                    try writeToMemory(field_val, pt, buffer[off..]);
                 },
                 .@"packed" => {
                     const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8;
@@ -412,22 +415,6 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
                 },
             }
         },
-        .ErrorSet => {
-            const bits = zcu.errorSetBits();
-            const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
-
-            const name = switch (ip.indexToKey(val.toIntern())) {
-                .err => |err| err.name,
-                .error_union => |error_union| error_union.val.err_name,
-                else => unreachable,
-            };
-            var bigint_buffer: BigIntSpace = undefined;
-            const bigint = BigIntMutable.init(
-                &bigint_buffer.limbs,
-                ip.getErrorValueIfExists(name).?,
-            ).toConst();
-            bigint.writeTwosComplement(buffer[0..byte_count], endian);
-        },
         .Union => switch (ty.containerLayout(zcu)) {
             .auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already
             .@"extern" => {
@@ -437,11 +424,11 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
                     const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
                     const field_val = try val.fieldValue(pt, field_index);
                     const byte_count: usize = @intCast(field_type.abiSize(zcu));
-                    return writeToMemory(field_val, field_type, pt, buffer[0..byte_count]);
+                    return writeToMemory(field_val, pt, buffer[0..byte_count]);
                 } else {
                     const backing_ty = try ty.unionBackingType(pt);
                     const byte_count: usize = @intCast(backing_ty.abiSize(zcu));
-                    return writeToMemory(val.unionValue(zcu), backing_ty, pt, buffer[0..byte_count]);
+                    return writeToMemory(val.unionValue(zcu), pt, buffer[0..byte_count]);
                 }
             },
             .@"packed" => {
@@ -450,19 +437,13 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
                 return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0);
             },
         },
-        .Pointer => {
-            if (ty.isSlice(zcu)) return error.IllDefinedMemoryLayout;
-            if (!val.ptrHasIntAddr(zcu)) return error.ReinterpretDeclRef;
-            return val.writeToMemory(Type.usize, pt, buffer);
-        },
         .Optional => {
             if (!ty.isPtrLikeOptional(zcu)) return error.IllDefinedMemoryLayout;
-            const child = ty.optionalChild(zcu);
             const opt_val = val.optionalValue(zcu);
             if (opt_val) |some| {
-                return some.writeToMemory(child, pt, buffer);
+                return some.writeToMemory(pt, buffer);
             } else {
-                return writeToMemory(try pt.intValue(Type.usize, 0), Type.usize, pt, buffer);
+                return writeToMemory(try pt.intValue(Type.usize, 0), pt, buffer);
             }
         },
         else => return error.Unimplemented,
@@ -582,7 +563,7 @@ pub fn writeToPackedMemory(
         },
         .Pointer => {
             assert(!ty.isSlice(zcu)); // No well defined layout.
-            if (!val.ptrHasIntAddr(zcu)) return error.ReinterpretDeclRef;
+            if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef;
             return val.writeToPackedMemory(Type.usize, pt, buffer, bit_offset);
         },
         .Optional => {
@@ -3658,14 +3639,15 @@ pub fn mulAddScalar(
 
 /// If the value is represented in-memory as a series of bytes that all
 /// have the same value, return that byte value, otherwise null.
-pub fn hasRepeatedByteRepr(val: Value, ty: Type, pt: Zcu.PerThread) !?u8 {
+pub fn hasRepeatedByteRepr(val: Value, pt: Zcu.PerThread) !?u8 {
     const zcu = pt.zcu;
+    const ty = val.typeOf(zcu);
     const abi_size = std.math.cast(usize, ty.abiSize(zcu)) orelse return null;
     assert(abi_size >= 1);
     const byte_buffer = try zcu.gpa.alloc(u8, abi_size);
     defer zcu.gpa.free(byte_buffer);
 
-    writeToMemory(val, ty, pt, byte_buffer) catch |err| switch (err) {
+    writeToMemory(val, pt, byte_buffer) catch |err| switch (err) {
         error.OutOfMemory => return error.OutOfMemory,
         error.ReinterpretDeclRef => return null,
         // TODO: The writeToMemory function was originally created for the purpose
test/src/Debugger.zig
@@ -305,6 +305,82 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
             \\1 breakpoints deleted; 0 breakpoint locations disabled.
         },
     );
+    db.addLldbTest(
+        "strings",
+        target,
+        &.{
+            .{
+                .path = "strings.zig",
+                .source =
+                \\const Strings = struct {
+                \\    c_ptr: [*c]const u8 = "c_ptr\x07\x08\t",
+                \\    many_ptr: [*:0]const u8 = "many_ptr\n\x0b\x0c",
+                \\    ptr_array: *const [12:0]u8 = "ptr_array\x00\r\x1b",
+                \\    slice: [:0]const u8 = "slice\"\'\\\x00",
+                \\};
+                \\fn testStrings(strings: Strings) void {
+                \\    _ = strings;
+                \\}
+                \\pub fn main() void {
+                \\    testStrings(.{});
+                \\}
+                \\
+                ,
+            },
+        },
+        \\breakpoint set --file strings.zig --source-pattern-regexp '_ = strings;'
+        \\process launch
+        \\frame variable --show-types strings.slice
+        \\frame variable --show-types --format character strings.slice
+        \\frame variable --show-types --format c-string strings
+        \\breakpoint delete --force 1
+    ,
+        &.{
+            \\(lldb) frame variable --show-types strings.slice
+            \\([:0]const u8) strings.slice = len=9 {
+            \\  (u8) [0] = 115
+            \\  (u8) [1] = 108
+            \\  (u8) [2] = 105
+            \\  (u8) [3] = 99
+            \\  (u8) [4] = 101
+            \\  (u8) [5] = 34
+            \\  (u8) [6] = 39
+            \\  (u8) [7] = 92
+            \\  (u8) [8] = 0
+            \\}
+            \\(lldb) frame variable --show-types --format character strings.slice
+            \\([:0]const u8) strings.slice = len=9 {
+            \\  (u8) [0] = 's'
+            \\  (u8) [1] = 'l'
+            \\  (u8) [2] = 'i'
+            \\  (u8) [3] = 'c'
+            \\  (u8) [4] = 'e'
+            \\  (u8) [5] = '\"'
+            \\  (u8) [6] = '\''
+            \\  (u8) [7] = '\\'
+            \\  (u8) [8] = '\x00'
+            \\}
+            \\(lldb) frame variable --show-types --format c-string strings
+            \\(root.strings.Strings) strings = {
+            \\  ([*c]const u8) c_ptr = "c_ptr\x07\x08\t"
+            \\  ([*:0]const u8) many_ptr = "many_ptr\n\x0b\x0c"
+            \\  (*const [12:0]u8) ptr_array = "ptr_array\x00\r\x1b"
+            \\  ([:0]const u8) slice = "slice\"\'\\\x00" len=9 {
+            \\    (u8) [0] = "s"
+            \\    (u8) [1] = "l"
+            \\    (u8) [2] = "i"
+            \\    (u8) [3] = "c"
+            \\    (u8) [4] = "e"
+            \\    (u8) [5] = "\""
+            \\    (u8) [6] = "\'"
+            \\    (u8) [7] = "\\"
+            \\    (u8) [8] = "\x00"
+            \\  }
+            \\}
+            \\(lldb) breakpoint delete --force 1
+            \\1 breakpoints deleted; 0 breakpoint locations disabled.
+        },
+    );
     db.addLldbTest(
         "enums",
         target,