authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-18 12:41:37-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-18 12:41:37-08:00
log7775e46e8179fd1f4e27ca45fc211ac2e23a6969
treef4b479b4deb3ad2b3c0440f936107adffa81b80c
parent3cafb9655a754743da695af41ef635b79d066127
parent247e4ac3cc18a1a29bc180873b7b9f946f515212
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18983 from jacobly0/dwarf-rewrite

dwarf: optimize dwarf parsing for speed

5 files changed, 765 insertions(+), 777 deletions(-)

lib/std/dwarf.zig+683-703
...@@ -1,12 +1,9 @@...@@ -1,12 +1,9 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std.zig");2const std = @import("std.zig");
3const debug = std.debug;3const debug = std.debug;
4const fs = std.fs;
5const io = std.io;
6const mem = std.mem;4const mem = std.mem;
7const math = std.math;5const math = std.math;
8const leb = @import("leb128.zig");6const assert = debug.assert;
9const assert = std.debug.assert;
10const native_endian = builtin.cpu.arch.endian();7const native_endian = builtin.cpu.arch.endian();
118
12pub const TAG = @import("dwarf/TAG.zig");9pub const TAG = @import("dwarf/TAG.zig");
...@@ -167,8 +164,8 @@ const Func = struct {...@@ -167,8 +164,8 @@ const Func = struct {
167164
168pub const CompileUnit = struct {165pub const CompileUnit = struct {
169 version: u16,166 version: u16,
170 is_64: bool,167 format: Format,
171 die: *Die,168 die: Die,
172 pc_range: ?PcRange,169 pc_range: ?PcRange,
173170
174 str_offsets_base: usize,171 str_offsets_base: usize,
...@@ -178,101 +175,88 @@ pub const CompileUnit = struct {...@@ -178,101 +175,88 @@ pub const CompileUnit = struct {
178 frame_base: ?*const FormValue,175 frame_base: ?*const FormValue,
179};176};
180177
181const AbbrevTable = std.ArrayList(AbbrevTableEntry);178const Abbrev = struct {
182179 code: u64,
183const AbbrevTableHeader = struct {
184 // offset from .debug_abbrev
185 offset: u64,
186 table: AbbrevTable,
187
188 fn deinit(header: *AbbrevTableHeader) void {
189 for (header.table.items) |*entry| {
190 entry.deinit();
191 }
192 header.table.deinit();
193 }
194};
195
196const AbbrevTableEntry = struct {
197 has_children: bool,
198 abbrev_code: u64,
199 tag_id: u64,180 tag_id: u64,
200 attrs: std.ArrayList(AbbrevAttr),181 has_children: bool,
182 attrs: []Attr,
201183
202 fn deinit(entry: *AbbrevTableEntry) void {184 fn deinit(abbrev: *Abbrev, allocator: mem.Allocator) void {
203 entry.attrs.deinit();185 allocator.free(abbrev.attrs);
186 abbrev.* = undefined;
204 }187 }
205};
206188
207const AbbrevAttr = struct {189 const Attr = struct {
208 attr_id: u64,190 id: u64,
209 form_id: u64,191 form_id: u64,
210 /// Only valid if form_id is .implicit_const192 /// Only valid if form_id is .implicit_const
211 payload: i64,193 payload: i64,
212};194 };
213195
214pub const FormValue = union(enum) {196 const Table = struct {
215 Address: u64,197 // offset from .debug_abbrev
216 AddrOffset: usize,198 offset: u64,
217 Block: []u8,199 abbrevs: []Abbrev,
218 Const: Constant,200
219 ExprLoc: []u8,201 fn deinit(table: *Table, allocator: mem.Allocator) void {
220 Flag: bool,202 for (table.abbrevs) |*abbrev| {
221 SecOffset: u64,203 abbrev.deinit(allocator);
222 Ref: u64,204 }
223 RefAddr: u64,205 allocator.free(table.abbrevs);
224 String: []const u8,206 table.* = undefined;
225 StrPtr: u64,
226 StrOffset: usize,
227 LineStrPtr: u64,
228 LocListOffset: u64,
229 RangeListOffset: u64,
230 data16: [16]u8,
231
232 fn getString(fv: FormValue, di: DwarfInfo) ![]const u8 {
233 switch (fv) {
234 .String => |s| return s,
235 .StrPtr => |off| return di.getString(off),
236 .LineStrPtr => |off| return di.getLineString(off),
237 else => return badDwarf(),
238 }207 }
239 }
240208
241 fn getUInt(fv: FormValue, comptime U: type) !U {209 fn get(table: *const Table, abbrev_code: u64) ?*const Abbrev {
242 switch (fv) {210 return for (table.abbrevs) |*abbrev| {
243 .Const => |c| {211 if (abbrev.code == abbrev_code) break abbrev;
244 const int = try c.asUnsignedLe();212 } else null;
245 return math.cast(U, int) orelse return badDwarf();
246 },
247 .SecOffset => |x| return math.cast(U, x) orelse return badDwarf(),
248 else => return badDwarf(),
249 }213 }
250 }214 };
215};
251216
252 fn getData16(fv: FormValue) ![16]u8 {217pub const FormValue = union(enum) {
218 addr: u64,
219 addrx: usize,
220 block: []const u8,
221 udata: u64,
222 data16: *const [16]u8,
223 sdata: i64,
224 exprloc: []const u8,
225 flag: bool,
226 sec_offset: u64,
227 ref: u64,
228 ref_addr: u64,
229 string: [:0]const u8,
230 strp: u64,
231 strx: usize,
232 line_strp: u64,
233 loclistx: u64,
234 rnglistx: u64,
235
236 fn getString(fv: FormValue, di: DwarfInfo) ![:0]const u8 {
253 switch (fv) {237 switch (fv) {
254 .data16 => |d| return d,238 .string => |s| return s,
239 .strp => |off| return di.getString(off),
240 .line_strp => |off| return di.getLineString(off),
255 else => return badDwarf(),241 else => return badDwarf(),
256 }242 }
257 }243 }
258};
259
260const Constant = struct {
261 payload: u64,
262 signed: bool,
263244
264 fn asUnsignedLe(self: Constant) !u64 {245 fn getUInt(fv: FormValue, comptime U: type) !U {
265 if (self.signed) return badDwarf();246 return switch (fv) {
266 return self.payload;247 inline .udata,
248 .sdata,
249 .sec_offset,
250 => |c| math.cast(U, c) orelse badDwarf(),
251 else => badDwarf(),
252 };
267 }253 }
268};254};
269255
270const Die = struct {256const Die = struct {
271 // Arena for Die's Attr's and FormValue's.
272 arena: std.heap.ArenaAllocator,
273 tag_id: u64,257 tag_id: u64,
274 has_children: bool,258 has_children: bool,
275 attrs: std.ArrayListUnmanaged(Attr) = .{},259 attrs: []Attr,
276260
277 const Attr = struct {261 const Attr = struct {
278 id: u64,262 id: u64,
...@@ -280,12 +264,12 @@ const Die = struct {...@@ -280,12 +264,12 @@ const Die = struct {
280 };264 };
281265
282 fn deinit(self: *Die, allocator: mem.Allocator) void {266 fn deinit(self: *Die, allocator: mem.Allocator) void {
283 self.arena.deinit();267 allocator.free(self.attrs);
284 self.attrs.deinit(allocator);268 self.* = undefined;
285 }269 }
286270
287 fn getAttr(self: *const Die, id: u64) ?*const FormValue {271 fn getAttr(self: *const Die, id: u64) ?*const FormValue {
288 for (self.attrs.items) |*attr| {272 for (self.attrs) |*attr| {
289 if (attr.id == id) return &attr.value;273 if (attr.id == id) return &attr.value;
290 }274 }
291 return null;275 return null;
...@@ -299,8 +283,8 @@ const Die = struct {...@@ -299,8 +283,8 @@ const Die = struct {
299 ) error{ InvalidDebugInfo, MissingDebugInfo }!u64 {283 ) error{ InvalidDebugInfo, MissingDebugInfo }!u64 {
300 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;284 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
301 return switch (form_value.*) {285 return switch (form_value.*) {
302 FormValue.Address => |value| value,286 .addr => |value| value,
303 FormValue.AddrOffset => |index| di.readDebugAddr(compile_unit, index),287 .addrx => |index| di.readDebugAddr(compile_unit, index),
304 else => error.InvalidDebugInfo,288 else => error.InvalidDebugInfo,
305 };289 };
306 }290 }
...@@ -313,7 +297,7 @@ const Die = struct {...@@ -313,7 +297,7 @@ const Die = struct {
313 fn getAttrUnsignedLe(self: *const Die, id: u64) !u64 {297 fn getAttrUnsignedLe(self: *const Die, id: u64) !u64 {
314 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;298 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
315 return switch (form_value.*) {299 return switch (form_value.*) {
316 FormValue.Const => |value| value.asUnsignedLe(),300 .Const => |value| value.asUnsignedLe(),
317 else => error.InvalidDebugInfo,301 else => error.InvalidDebugInfo,
318 };302 };
319 }303 }
...@@ -321,7 +305,7 @@ const Die = struct {...@@ -321,7 +305,7 @@ const Die = struct {
321 fn getAttrRef(self: *const Die, id: u64) !u64 {305 fn getAttrRef(self: *const Die, id: u64) !u64 {
322 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;306 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
323 return switch (form_value.*) {307 return switch (form_value.*) {
324 FormValue.Ref => |value| value,308 .ref => |value| value,
325 else => error.InvalidDebugInfo,309 else => error.InvalidDebugInfo,
326 };310 };
327 }311 }
...@@ -335,24 +319,27 @@ const Die = struct {...@@ -335,24 +319,27 @@ const Die = struct {
335 ) error{ InvalidDebugInfo, MissingDebugInfo }![]const u8 {319 ) error{ InvalidDebugInfo, MissingDebugInfo }![]const u8 {
336 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;320 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
337 switch (form_value.*) {321 switch (form_value.*) {
338 FormValue.String => |value| return value,322 .string => |value| return value,
339 FormValue.StrPtr => |offset| return di.getString(offset),323 .strp => |offset| return di.getString(offset),
340 FormValue.StrOffset => |index| {324 .strx => |index| {
341 const debug_str_offsets = di.section(.debug_str_offsets) orelse return badDwarf();325 const debug_str_offsets = di.section(.debug_str_offsets) orelse return badDwarf();
342 if (compile_unit.str_offsets_base == 0) return badDwarf();326 if (compile_unit.str_offsets_base == 0) return badDwarf();
343 if (compile_unit.is_64) {327 switch (compile_unit.format) {
344 const byte_offset = compile_unit.str_offsets_base + 8 * index;328 .@"32" => {
345 if (byte_offset + 8 > debug_str_offsets.len) return badDwarf();329 const byte_offset = compile_unit.str_offsets_base + 4 * index;
346 const offset = mem.readInt(u64, debug_str_offsets[byte_offset..][0..8], di.endian);330 if (byte_offset + 4 > debug_str_offsets.len) return badDwarf();
347 return getStringGeneric(opt_str, offset);331 const offset = mem.readInt(u32, debug_str_offsets[byte_offset..][0..4], di.endian);
348 } else {332 return getStringGeneric(opt_str, offset);
349 const byte_offset = compile_unit.str_offsets_base + 4 * index;333 },
350 if (byte_offset + 4 > debug_str_offsets.len) return badDwarf();334 .@"64" => {
351 const offset = mem.readInt(u32, debug_str_offsets[byte_offset..][0..4], di.endian);335 const byte_offset = compile_unit.str_offsets_base + 8 * index;
352 return getStringGeneric(opt_str, offset);336 if (byte_offset + 8 > debug_str_offsets.len) return badDwarf();
337 const offset = mem.readInt(u64, debug_str_offsets[byte_offset..][0..8], di.endian);
338 return getStringGeneric(opt_str, offset);
339 },
353 }340 }
354 },341 },
355 FormValue.LineStrPtr => |offset| return di.getLineString(offset),342 .line_strp => |offset| return di.getLineString(offset),
356 else => return badDwarf(),343 else => return badDwarf(),
357 }344 }
358 }345 }
...@@ -458,7 +445,7 @@ const LineNumberProgram = struct {...@@ -458,7 +445,7 @@ const LineNumberProgram = struct {
458 if (file_entry.dir_index >= self.include_dirs.len) return badDwarf();445 if (file_entry.dir_index >= self.include_dirs.len) return badDwarf();
459 const dir_name = self.include_dirs[file_entry.dir_index].path;446 const dir_name = self.include_dirs[file_entry.dir_index].path;
460447
461 const file_name = try fs.path.join(allocator, &[_][]const u8{448 const file_name = try std.fs.path.join(allocator, &[_][]const u8{
462 dir_name, file_entry.path,449 dir_name, file_entry.path,
463 });450 });
464451
...@@ -481,168 +468,97 @@ const LineNumberProgram = struct {...@@ -481,168 +468,97 @@ const LineNumberProgram = struct {
481 }468 }
482};469};
483470
484fn readUnitLength(in_stream: anytype, endian: std.builtin.Endian, is_64: *bool) !u64 {471const UnitHeader = struct {
485 const first_32_bits = try in_stream.readInt(u32, endian);472 format: Format,
486 is_64.* = (first_32_bits == 0xffffffff);473 header_length: u4,
487 if (is_64.*) {474 unit_length: u64,
488 return in_stream.readInt(u64, endian);475};
489 } else {476fn readUnitHeader(fbr: *FixedBufferReader) !UnitHeader {
490 if (first_32_bits >= 0xfffffff0) return badDwarf();477 return switch (try fbr.readInt(u32)) {
491 // TODO this cast should not be needed478 0...0xfffffff0 - 1 => |unit_length| .{
492 return @as(u64, first_32_bits);479 .format = .@"32",
493 }480 .header_length = 4,
494}481 .unit_length = unit_length,
495
496// TODO the nosuspends here are workarounds
497fn readAllocBytes(allocator: mem.Allocator, in_stream: anytype, size: usize) ![]u8 {
498 const buf = try allocator.alloc(u8, size);
499 errdefer allocator.free(buf);
500 if ((try nosuspend in_stream.read(buf)) < size) return error.EndOfFile;
501 return buf;
502}
503
504// TODO the nosuspends here are workarounds
505fn readAddress(in_stream: anytype, endian: std.builtin.Endian, is_64: bool) !u64 {
506 return nosuspend if (is_64)
507 try in_stream.readInt(u64, endian)
508 else
509 @as(u64, try in_stream.readInt(u32, endian));
510}
511
512fn parseFormValueBlockLen(allocator: mem.Allocator, in_stream: anytype, size: usize) !FormValue {
513 const buf = try readAllocBytes(allocator, in_stream, size);
514 return FormValue{ .Block = buf };
515}
516
517// TODO the nosuspends here are workarounds
518fn parseFormValueBlock(allocator: mem.Allocator, in_stream: anytype, endian: std.builtin.Endian, size: usize) !FormValue {
519 const block_len = try nosuspend in_stream.readVarInt(usize, endian, size);
520 return parseFormValueBlockLen(allocator, in_stream, block_len);
521}
522
523fn parseFormValueConstant(in_stream: anytype, signed: bool, endian: std.builtin.Endian, comptime size: i32) !FormValue {
524 // TODO: Please forgive me, I've worked around zig not properly spilling some intermediate values here.
525 // `nosuspend` should be removed from all the function calls once it is fixed.
526 return FormValue{
527 .Const = Constant{
528 .signed = signed,
529 .payload = switch (size) {
530 1 => try nosuspend in_stream.readInt(u8, endian),
531 2 => try nosuspend in_stream.readInt(u16, endian),
532 4 => try nosuspend in_stream.readInt(u32, endian),
533 8 => try nosuspend in_stream.readInt(u64, endian),
534 -1 => blk: {
535 if (signed) {
536 const x = try nosuspend leb.readILEB128(i64, in_stream);
537 break :blk @as(u64, @bitCast(x));
538 } else {
539 const x = try nosuspend leb.readULEB128(u64, in_stream);
540 break :blk x;
541 }
542 },
543 else => @compileError("Invalid size"),
544 },
545 },482 },
546 };483 0xfffffff0...0xffffffff - 1 => badDwarf(),
547}484 0xffffffff => .{
548485 .format = .@"64",
549// TODO the nosuspends here are workarounds486 .header_length = 12,
550fn parseFormValueRef(in_stream: anytype, endian: std.builtin.Endian, size: i32) !FormValue {487 .unit_length = try fbr.readInt(u64),
551 return FormValue{
552 .Ref = switch (size) {
553 1 => try nosuspend in_stream.readInt(u8, endian),
554 2 => try nosuspend in_stream.readInt(u16, endian),
555 4 => try nosuspend in_stream.readInt(u32, endian),
556 8 => try nosuspend in_stream.readInt(u64, endian),
557 -1 => try nosuspend leb.readULEB128(u64, in_stream),
558 else => unreachable,
559 },488 },
560 };489 };
561}490}
562491
563// TODO the nosuspends here are workarounds492fn parseFormValue(
564fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, endian: std.builtin.Endian, is_64: bool) anyerror!FormValue {493 fbr: *FixedBufferReader,
494 form_id: u64,
495 format: Format,
496 implicit_const: ?i64,
497) anyerror!FormValue {
565 return switch (form_id) {498 return switch (form_id) {
566 FORM.addr => FormValue{ .Address = try readAddress(in_stream, endian, @sizeOf(usize) == 8) },499 FORM.addr => .{ .addr = try fbr.readAddress(switch (@bitSizeOf(usize)) {
567 FORM.addrx1 => return FormValue{ .AddrOffset = try in_stream.readInt(u8, endian) },500 32 => .@"32",
568 FORM.addrx2 => return FormValue{ .AddrOffset = try in_stream.readInt(u16, endian) },501 64 => .@"64",
569 FORM.addrx3 => return FormValue{ .AddrOffset = try in_stream.readInt(u24, endian) },502 else => @compileError("unsupported @sizeOf(usize)"),
570 FORM.addrx4 => return FormValue{ .AddrOffset = try in_stream.readInt(u32, endian) },503 }) },
571 FORM.addrx => return FormValue{ .AddrOffset = try nosuspend leb.readULEB128(usize, in_stream) },504 FORM.addrx1 => .{ .addrx = try fbr.readInt(u8) },
572505 FORM.addrx2 => .{ .addrx = try fbr.readInt(u16) },
573 FORM.block1 => parseFormValueBlock(allocator, in_stream, endian, 1),506 FORM.addrx3 => .{ .addrx = try fbr.readInt(u24) },
574 FORM.block2 => parseFormValueBlock(allocator, in_stream, endian, 2),507 FORM.addrx4 => .{ .addrx = try fbr.readInt(u32) },
575 FORM.block4 => parseFormValueBlock(allocator, in_stream, endian, 4),508 FORM.addrx => .{ .addrx = try fbr.readUleb128(usize) },
576 FORM.block => {509
577 const block_len = try nosuspend leb.readULEB128(usize, in_stream);510 FORM.block1,
578 return parseFormValueBlockLen(allocator, in_stream, block_len);511 FORM.block2,
579 },512 FORM.block4,
580 FORM.data1 => parseFormValueConstant(in_stream, false, endian, 1),513 FORM.block,
581 FORM.data2 => parseFormValueConstant(in_stream, false, endian, 2),514 => .{ .block = try fbr.readBytes(switch (form_id) {
582 FORM.data4 => parseFormValueConstant(in_stream, false, endian, 4),515 FORM.block1 => try fbr.readInt(u8),
583 FORM.data8 => parseFormValueConstant(in_stream, false, endian, 8),516 FORM.block2 => try fbr.readInt(u16),
584 FORM.data16 => {517 FORM.block4 => try fbr.readInt(u32),
585 var buf: [16]u8 = undefined;518 FORM.block => try fbr.readUleb128(usize),
586 if ((try nosuspend in_stream.readAll(&buf)) < 16) return error.EndOfFile;519 else => unreachable,
587 return FormValue{ .data16 = buf };520 }) },
588 },521
589 FORM.udata, FORM.sdata => {522 FORM.data1 => .{ .udata = try fbr.readInt(u8) },
590 const signed = form_id == FORM.sdata;523 FORM.data2 => .{ .udata = try fbr.readInt(u16) },
591 return parseFormValueConstant(in_stream, signed, endian, -1);524 FORM.data4 => .{ .udata = try fbr.readInt(u32) },
592 },525 FORM.data8 => .{ .udata = try fbr.readInt(u64) },
593 FORM.exprloc => {526 FORM.data16 => .{ .data16 = (try fbr.readBytes(16))[0..16] },
594 const size = try nosuspend leb.readULEB128(usize, in_stream);527 FORM.udata => .{ .udata = try fbr.readUleb128(u64) },
595 const buf = try readAllocBytes(allocator, in_stream, size);528 FORM.sdata => .{ .sdata = try fbr.readIleb128(i64) },
596 return FormValue{ .ExprLoc = buf };529 FORM.exprloc => .{ .exprloc = try fbr.readBytes(try fbr.readUleb128(usize)) },
597 },530 FORM.flag => .{ .flag = (try fbr.readByte()) != 0 },
598 FORM.flag => FormValue{ .Flag = (try nosuspend in_stream.readByte()) != 0 },531 FORM.flag_present => .{ .flag = true },
599 FORM.flag_present => FormValue{ .Flag = true },532 FORM.sec_offset => .{ .sec_offset = try fbr.readAddress(format) },
600 FORM.sec_offset => FormValue{ .SecOffset = try readAddress(in_stream, endian, is_64) },533
601534 FORM.ref1 => .{ .ref = try fbr.readInt(u8) },
602 FORM.ref1 => parseFormValueRef(in_stream, endian, 1),535 FORM.ref2 => .{ .ref = try fbr.readInt(u16) },
603 FORM.ref2 => parseFormValueRef(in_stream, endian, 2),536 FORM.ref4 => .{ .ref = try fbr.readInt(u32) },
604 FORM.ref4 => parseFormValueRef(in_stream, endian, 4),537 FORM.ref8 => .{ .ref = try fbr.readInt(u64) },
605 FORM.ref8 => parseFormValueRef(in_stream, endian, 8),538 FORM.ref_udata => .{ .ref = try fbr.readUleb128(u64) },
606 FORM.ref_udata => parseFormValueRef(in_stream, endian, -1),539
607540 FORM.ref_addr => .{ .ref_addr = try fbr.readAddress(format) },
608 FORM.ref_addr => FormValue{ .RefAddr = try readAddress(in_stream, endian, is_64) },541 FORM.ref_sig8 => .{ .ref = try fbr.readInt(u64) },
609 FORM.ref_sig8 => FormValue{ .Ref = try nosuspend in_stream.readInt(u64, endian) },542
610543 FORM.string => .{ .string = try fbr.readBytesTo(0) },
611 FORM.string => FormValue{ .String = try in_stream.readUntilDelimiterAlloc(allocator, 0, math.maxInt(usize)) },544 FORM.strp => .{ .strp = try fbr.readAddress(format) },
612 FORM.strp => FormValue{ .StrPtr = try readAddress(in_stream, endian, is_64) },545 FORM.strx1 => .{ .strx = try fbr.readInt(u8) },
613 FORM.strx1 => return FormValue{ .StrOffset = try in_stream.readInt(u8, endian) },546 FORM.strx2 => .{ .strx = try fbr.readInt(u16) },
614 FORM.strx2 => return FormValue{ .StrOffset = try in_stream.readInt(u16, endian) },547 FORM.strx3 => .{ .strx = try fbr.readInt(u24) },
615 FORM.strx3 => return FormValue{ .StrOffset = try in_stream.readInt(u24, endian) },548 FORM.strx4 => .{ .strx = try fbr.readInt(u32) },
616 FORM.strx4 => return FormValue{ .StrOffset = try in_stream.readInt(u32, endian) },549 FORM.strx => .{ .strx = try fbr.readUleb128(usize) },
617 FORM.strx => return FormValue{ .StrOffset = try nosuspend leb.readULEB128(usize, in_stream) },550 FORM.line_strp => .{ .line_strp = try fbr.readAddress(format) },
618 FORM.line_strp => FormValue{ .LineStrPtr = try readAddress(in_stream, endian, is_64) },551 FORM.indirect => parseFormValue(fbr, try fbr.readUleb128(u64), format, implicit_const),
619 FORM.indirect => {552 FORM.implicit_const => .{ .sdata = implicit_const orelse return badDwarf() },
620 const child_form_id = try nosuspend leb.readULEB128(u64, in_stream);553 FORM.loclistx => .{ .loclistx = try fbr.readUleb128(u64) },
621 if (true) {554 FORM.rnglistx => .{ .rnglistx = try fbr.readUleb128(u64) },
622 return parseFormValue(allocator, in_stream, child_form_id, endian, is_64);
623 }
624 const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, endian, is_64));
625 const frame = try allocator.create(F);
626 defer allocator.destroy(frame);
627 return await @asyncCall(frame, {}, parseFormValue, .{ allocator, in_stream, child_form_id, endian, is_64 });
628 },
629 FORM.implicit_const => FormValue{ .Const = Constant{ .signed = true, .payload = undefined } },
630 FORM.loclistx => return FormValue{ .LocListOffset = try nosuspend leb.readULEB128(u64, in_stream) },
631 FORM.rnglistx => return FormValue{ .RangeListOffset = try nosuspend leb.readULEB128(u64, in_stream) },
632 else => {555 else => {
633 //std.debug.print("unrecognized form id: {x}\n", .{form_id});556 //debug.print("unrecognized form id: {x}\n", .{form_id});
634 return badDwarf();557 return badDwarf();
635 },558 },
636 };559 };
637}560}
638561
639fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry {
640 for (abbrev_table.items) |*table_entry| {
641 if (table_entry.abbrev_code == abbrev_code) return table_entry;
642 }
643 return null;
644}
645
646pub const DwarfSection = enum {562pub const DwarfSection = enum {
647 debug_info,563 debug_info,
648 debug_abbrev,564 debug_abbrev,
...@@ -690,7 +606,7 @@ pub const DwarfInfo = struct {...@@ -690,7 +606,7 @@ pub const DwarfInfo = struct {
690 is_macho: bool,606 is_macho: bool,
691607
692 // Filled later by the initializer608 // Filled later by the initializer
693 abbrev_table_list: std.ArrayListUnmanaged(AbbrevTableHeader) = .{},609 abbrev_table_list: std.ArrayListUnmanaged(Abbrev.Table) = .{},
694 compile_unit_list: std.ArrayListUnmanaged(CompileUnit) = .{},610 compile_unit_list: std.ArrayListUnmanaged(CompileUnit) = .{},
695 func_list: std.ArrayListUnmanaged(Func) = .{},611 func_list: std.ArrayListUnmanaged(Func) = .{},
696612
...@@ -713,17 +629,17 @@ pub const DwarfInfo = struct {...@@ -713,17 +629,17 @@ pub const DwarfInfo = struct {
713 if (opt_section) |s| if (s.owned) allocator.free(s.data);629 if (opt_section) |s| if (s.owned) allocator.free(s.data);
714 }630 }
715 for (di.abbrev_table_list.items) |*abbrev| {631 for (di.abbrev_table_list.items) |*abbrev| {
716 abbrev.deinit();632 abbrev.deinit(allocator);
717 }633 }
718 di.abbrev_table_list.deinit(allocator);634 di.abbrev_table_list.deinit(allocator);
719 for (di.compile_unit_list.items) |*cu| {635 for (di.compile_unit_list.items) |*cu| {
720 cu.die.deinit(allocator);636 cu.die.deinit(allocator);
721 allocator.destroy(cu.die);
722 }637 }
723 di.compile_unit_list.deinit(allocator);638 di.compile_unit_list.deinit(allocator);
724 di.func_list.deinit(allocator);639 di.func_list.deinit(allocator);
725 di.cie_map.deinit(allocator);640 di.cie_map.deinit(allocator);
726 di.fde_list.deinit(allocator);641 di.fde_list.deinit(allocator);
642 di.* = undefined;
727 }643 }
728644
729 pub fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 {645 pub fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 {
...@@ -739,102 +655,125 @@ pub const DwarfInfo = struct {...@@ -739,102 +655,125 @@ pub const DwarfInfo = struct {
739 }655 }
740656
741 fn scanAllFunctions(di: *DwarfInfo, allocator: mem.Allocator) !void {657 fn scanAllFunctions(di: *DwarfInfo, allocator: mem.Allocator) !void {
742 var stream = io.fixedBufferStream(di.section(.debug_info).?);658 var fbr: FixedBufferReader = .{ .buf = di.section(.debug_info).?, .endian = di.endian };
743 const in = stream.reader();
744 const seekable = stream.seekableStream();
745 var this_unit_offset: u64 = 0;659 var this_unit_offset: u64 = 0;
746660
747 var tmp_arena = std.heap.ArenaAllocator.init(allocator);661 while (this_unit_offset < fbr.buf.len) {
748 defer tmp_arena.deinit();662 try fbr.seekTo(this_unit_offset);
749 const arena = tmp_arena.allocator();
750663
751 while (this_unit_offset < try seekable.getEndPos()) {664 const unit_header = try readUnitHeader(&fbr);
752 try seekable.seekTo(this_unit_offset);665 if (unit_header.unit_length == 0) return;
666 const next_offset = unit_header.header_length + unit_header.unit_length;
753667
754 var is_64: bool = undefined;668 const version = try fbr.readInt(u16);
755 const unit_length = try readUnitLength(in, di.endian, &is_64);
756 if (unit_length == 0) return;
757 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
758
759 const version = try in.readInt(u16, di.endian);
760 if (version < 2 or version > 5) return badDwarf();669 if (version < 2 or version > 5) return badDwarf();
761670
762 var address_size: u8 = undefined;671 var address_size: u8 = undefined;
763 var debug_abbrev_offset: u64 = undefined;672 var debug_abbrev_offset: u64 = undefined;
764 if (version >= 5) {673 if (version >= 5) {
765 const unit_type = try in.readInt(u8, di.endian);674 const unit_type = try fbr.readInt(u8);
766 if (unit_type != UT.compile) return badDwarf();675 if (unit_type != UT.compile) return badDwarf();
767 address_size = try in.readByte();676 address_size = try fbr.readByte();
768 debug_abbrev_offset = if (is_64)677 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
769 try in.readInt(u64, di.endian)
770 else
771 try in.readInt(u32, di.endian);
772 } else {678 } else {
773 debug_abbrev_offset = if (is_64)679 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
774 try in.readInt(u64, di.endian)680 address_size = try fbr.readByte();
775 else
776 try in.readInt(u32, di.endian);
777 address_size = try in.readByte();
778 }681 }
779 if (address_size != @sizeOf(usize)) return badDwarf();682 if (address_size != @sizeOf(usize)) return badDwarf();
780683
781 const compile_unit_pos = try seekable.getPos();
782 const abbrev_table = try di.getAbbrevTable(allocator, debug_abbrev_offset);684 const abbrev_table = try di.getAbbrevTable(allocator, debug_abbrev_offset);
783685
784 try seekable.seekTo(compile_unit_pos);686 var max_attrs: usize = 0;
687 var zig_padding_abbrev_code: u7 = 0;
688 for (abbrev_table.abbrevs) |abbrev| {
689 max_attrs = @max(max_attrs, abbrev.attrs.len);
690 if (math.cast(u7, abbrev.code)) |code| {
691 if (abbrev.tag_id == TAG.ZIG_padding and
692 !abbrev.has_children and
693 abbrev.attrs.len == 0)
694 {
695 zig_padding_abbrev_code = code;
696 }
697 }
698 }
699 const attrs_buf = try allocator.alloc(Die.Attr, max_attrs * 3);
700 defer allocator.free(attrs_buf);
701 var attrs_bufs: [3][]Die.Attr = undefined;
702 for (&attrs_bufs, 0..) |*buf, index| buf.* = attrs_buf[index * max_attrs ..][0..max_attrs];
785703
786 const next_unit_pos = this_unit_offset + next_offset;704 const next_unit_pos = this_unit_offset + next_offset;
787705
788 var compile_unit: CompileUnit = undefined;706 var compile_unit: CompileUnit = .{
707 .version = version,
708 .format = unit_header.format,
709 .die = undefined,
710 .pc_range = null,
789711
790 while ((try seekable.getPos()) < next_unit_pos) {712 .str_offsets_base = 0,
791 var die_obj = (try di.parseDie(arena, in, abbrev_table, is_64)) orelse continue;713 .addr_base = 0,
792 const after_die_offset = try seekable.getPos();714 .rnglists_base = 0,
715 .loclists_base = 0,
716 .frame_base = null,
717 };
718
719 while (true) {
720 fbr.pos = mem.indexOfNonePos(u8, fbr.buf, fbr.pos, &.{
721 zig_padding_abbrev_code, 0,
722 }) orelse fbr.buf.len;
723 if (fbr.pos >= next_unit_pos) break;
724 var die_obj = (try parseDie(
725 &fbr,
726 attrs_bufs[0],
727 abbrev_table,
728 unit_header.format,
729 )) orelse continue;
793730
794 switch (die_obj.tag_id) {731 switch (die_obj.tag_id) {
795 TAG.compile_unit => {732 TAG.compile_unit => {
796 compile_unit = .{733 compile_unit.die = die_obj;
797 .version = version,734 compile_unit.die.attrs = attrs_bufs[1][0..die_obj.attrs.len];
798 .is_64 = is_64,735 @memcpy(compile_unit.die.attrs, die_obj.attrs);
799 .die = &die_obj,736
800 .pc_range = null,737 compile_unit.str_offsets_base = if (die_obj.getAttr(AT.str_offsets_base)) |fv| try fv.getUInt(usize) else 0;
801738 compile_unit.addr_base = if (die_obj.getAttr(AT.addr_base)) |fv| try fv.getUInt(usize) else 0;
802 .str_offsets_base = if (die_obj.getAttr(AT.str_offsets_base)) |fv| try fv.getUInt(usize) else 0,739 compile_unit.rnglists_base = if (die_obj.getAttr(AT.rnglists_base)) |fv| try fv.getUInt(usize) else 0;
803 .addr_base = if (die_obj.getAttr(AT.addr_base)) |fv| try fv.getUInt(usize) else 0,740 compile_unit.loclists_base = if (die_obj.getAttr(AT.loclists_base)) |fv| try fv.getUInt(usize) else 0;
804 .rnglists_base = if (die_obj.getAttr(AT.rnglists_base)) |fv| try fv.getUInt(usize) else 0,741 compile_unit.frame_base = die_obj.getAttr(AT.frame_base);
805 .loclists_base = if (die_obj.getAttr(AT.loclists_base)) |fv| try fv.getUInt(usize) else 0,
806 .frame_base = die_obj.getAttr(AT.frame_base),
807 };
808 },742 },
809 TAG.subprogram, TAG.inlined_subroutine, TAG.subroutine, TAG.entry_point => {743 TAG.subprogram, TAG.inlined_subroutine, TAG.subroutine, TAG.entry_point => {
810 const fn_name = x: {744 const fn_name = x: {
811 var depth: i32 = 3;
812 var this_die_obj = die_obj;745 var this_die_obj = die_obj;
813 // Prevent endless loops746 // Prevent endless loops
814 while (depth > 0) : (depth -= 1) {747 for (0..3) |_| {
815 if (this_die_obj.getAttr(AT.name)) |_| {748 if (this_die_obj.getAttr(AT.name)) |_| {
816 break :x try this_die_obj.getAttrString(di, AT.name, di.section(.debug_str), compile_unit);749 break :x try this_die_obj.getAttrString(di, AT.name, di.section(.debug_str), compile_unit);
817 } else if (this_die_obj.getAttr(AT.abstract_origin)) |_| {750 } else if (this_die_obj.getAttr(AT.abstract_origin)) |_| {
751 const after_die_offset = fbr.pos;
752 defer fbr.pos = after_die_offset;
753
818 // Follow the DIE it points to and repeat754 // Follow the DIE it points to and repeat
819 const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin);755 const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin);
820 if (ref_offset > next_offset) return badDwarf();756 if (ref_offset > next_offset) return badDwarf();
821 try seekable.seekTo(this_unit_offset + ref_offset);757 try fbr.seekTo(this_unit_offset + ref_offset);
822 this_die_obj = (try di.parseDie(758 this_die_obj = (try parseDie(
823 arena,759 &fbr,
824 in,760 attrs_bufs[2],
825 abbrev_table,761 abbrev_table,
826 is_64,762 unit_header.format,
827 )) orelse return badDwarf();763 )) orelse return badDwarf();
828 } else if (this_die_obj.getAttr(AT.specification)) |_| {764 } else if (this_die_obj.getAttr(AT.specification)) |_| {
765 const after_die_offset = fbr.pos;
766 defer fbr.pos = after_die_offset;
767
829 // Follow the DIE it points to and repeat768 // Follow the DIE it points to and repeat
830 const ref_offset = try this_die_obj.getAttrRef(AT.specification);769 const ref_offset = try this_die_obj.getAttrRef(AT.specification);
831 if (ref_offset > next_offset) return badDwarf();770 if (ref_offset > next_offset) return badDwarf();
832 try seekable.seekTo(this_unit_offset + ref_offset);771 try fbr.seekTo(this_unit_offset + ref_offset);
833 this_die_obj = (try di.parseDie(772 this_die_obj = (try parseDie(
834 arena,773 &fbr,
835 in,774 attrs_bufs[2],
836 abbrev_table,775 abbrev_table,
837 is_64,776 unit_header.format,
838 )) orelse return badDwarf();777 )) orelse return badDwarf();
839 } else {778 } else {
840 break :x null;779 break :x null;
...@@ -847,15 +786,12 @@ pub const DwarfInfo = struct {...@@ -847,15 +786,12 @@ pub const DwarfInfo = struct {
847 var range_added = if (die_obj.getAttrAddr(di, AT.low_pc, compile_unit)) |low_pc| blk: {786 var range_added = if (die_obj.getAttrAddr(di, AT.low_pc, compile_unit)) |low_pc| blk: {
848 if (die_obj.getAttr(AT.high_pc)) |high_pc_value| {787 if (die_obj.getAttr(AT.high_pc)) |high_pc_value| {
849 const pc_end = switch (high_pc_value.*) {788 const pc_end = switch (high_pc_value.*) {
850 FormValue.Address => |value| value,789 .addr => |value| value,
851 FormValue.Const => |value| b: {790 .udata => |offset| low_pc + offset,
852 const offset = try value.asUnsignedLe();
853 break :b (low_pc + offset);
854 },
855 else => return badDwarf(),791 else => return badDwarf(),
856 };792 };
857793
858 try di.func_list.append(allocator, Func{794 try di.func_list.append(allocator, .{
859 .name = fn_name,795 .name = fn_name,
860 .pc_range = .{796 .pc_range = .{
861 .start = low_pc,797 .start = low_pc,
...@@ -880,7 +816,7 @@ pub const DwarfInfo = struct {...@@ -880,7 +816,7 @@ pub const DwarfInfo = struct {
880816
881 while (try iter.next()) |range| {817 while (try iter.next()) |range| {
882 range_added = true;818 range_added = true;
883 try di.func_list.append(allocator, Func{819 try di.func_list.append(allocator, .{
884 .name = fn_name,820 .name = fn_name,
885 .pc_range = .{821 .pc_range = .{
886 .start = range.start_addr,822 .start = range.start_addr,
...@@ -891,7 +827,7 @@ pub const DwarfInfo = struct {...@@ -891,7 +827,7 @@ pub const DwarfInfo = struct {
891 }827 }
892828
893 if (fn_name != null and !range_added) {829 if (fn_name != null and !range_added) {
894 try di.func_list.append(allocator, Func{830 try di.func_list.append(allocator, .{
895 .name = fn_name,831 .name = fn_name,
896 .pc_range = null,832 .pc_range = null,
897 });833 });
...@@ -899,8 +835,6 @@ pub const DwarfInfo = struct {...@@ -899,8 +835,6 @@ pub const DwarfInfo = struct {
899 },835 },
900 else => {},836 else => {},
901 }837 }
902
903 try seekable.seekTo(after_die_offset);
904 }838 }
905839
906 this_unit_offset += next_offset;840 this_unit_offset += next_offset;
...@@ -908,56 +842,57 @@ pub const DwarfInfo = struct {...@@ -908,56 +842,57 @@ pub const DwarfInfo = struct {
908 }842 }
909843
910 fn scanAllCompileUnits(di: *DwarfInfo, allocator: mem.Allocator) !void {844 fn scanAllCompileUnits(di: *DwarfInfo, allocator: mem.Allocator) !void {
911 var stream = io.fixedBufferStream(di.section(.debug_info).?);845 var fbr: FixedBufferReader = .{ .buf = di.section(.debug_info).?, .endian = di.endian };
912 const in = stream.reader();
913 const seekable = stream.seekableStream();
914 var this_unit_offset: u64 = 0;846 var this_unit_offset: u64 = 0;
915847
916 while (this_unit_offset < try seekable.getEndPos()) {848 var attrs_buf = std.ArrayList(Die.Attr).init(allocator);
917 try seekable.seekTo(this_unit_offset);849 defer attrs_buf.deinit();
850
851 while (this_unit_offset < fbr.buf.len) {
852 try fbr.seekTo(this_unit_offset);
918853
919 var is_64: bool = undefined;854 const unit_header = try readUnitHeader(&fbr);
920 const unit_length = try readUnitLength(in, di.endian, &is_64);855 if (unit_header.unit_length == 0) return;
921 if (unit_length == 0) return;856 const next_offset = unit_header.header_length + unit_header.unit_length;
922 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
923857
924 const version = try in.readInt(u16, di.endian);858 const version = try fbr.readInt(u16);
925 if (version < 2 or version > 5) return badDwarf();859 if (version < 2 or version > 5) return badDwarf();
926860
927 var address_size: u8 = undefined;861 var address_size: u8 = undefined;
928 var debug_abbrev_offset: u64 = undefined;862 var debug_abbrev_offset: u64 = undefined;
929 if (version >= 5) {863 if (version >= 5) {
930 const unit_type = try in.readInt(u8, di.endian);864 const unit_type = try fbr.readInt(u8);
931 if (unit_type != UT.compile) return badDwarf();865 if (unit_type != UT.compile) return badDwarf();
932 address_size = try in.readByte();866 address_size = try fbr.readByte();
933 debug_abbrev_offset = if (is_64)867 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
934 try in.readInt(u64, di.endian)
935 else
936 try in.readInt(u32, di.endian);
937 } else {868 } else {
938 debug_abbrev_offset = if (is_64)869 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
939 try in.readInt(u64, di.endian)870 address_size = try fbr.readByte();
940 else
941 try in.readInt(u32, di.endian);
942 address_size = try in.readByte();
943 }871 }
944 if (address_size != @sizeOf(usize)) return badDwarf();872 if (address_size != @sizeOf(usize)) return badDwarf();
945873
946 const compile_unit_pos = try seekable.getPos();
947 const abbrev_table = try di.getAbbrevTable(allocator, debug_abbrev_offset);874 const abbrev_table = try di.getAbbrevTable(allocator, debug_abbrev_offset);
948875
949 try seekable.seekTo(compile_unit_pos);876 var max_attrs: usize = 0;
877 for (abbrev_table.abbrevs) |abbrev| {
878 max_attrs = @max(max_attrs, abbrev.attrs.len);
879 }
880 try attrs_buf.resize(max_attrs);
950881
951 const compile_unit_die = try allocator.create(Die);882 var compile_unit_die = (try parseDie(
952 errdefer allocator.destroy(compile_unit_die);883 &fbr,
953 compile_unit_die.* = (try di.parseDie(allocator, in, abbrev_table, is_64)) orelse884 attrs_buf.items,
954 return badDwarf();885 abbrev_table,
886 unit_header.format,
887 )) orelse return badDwarf();
955888
956 if (compile_unit_die.tag_id != TAG.compile_unit) return badDwarf();889 if (compile_unit_die.tag_id != TAG.compile_unit) return badDwarf();
957890
891 compile_unit_die.attrs = try allocator.dupe(Die.Attr, compile_unit_die.attrs);
892
958 var compile_unit: CompileUnit = .{893 var compile_unit: CompileUnit = .{
959 .version = version,894 .version = version,
960 .is_64 = is_64,895 .format = unit_header.format,
961 .pc_range = null,896 .pc_range = null,
962 .die = compile_unit_die,897 .die = compile_unit_die,
963 .str_offsets_base = if (compile_unit_die.getAttr(AT.str_offsets_base)) |fv| try fv.getUInt(usize) else 0,898 .str_offsets_base = if (compile_unit_die.getAttr(AT.str_offsets_base)) |fv| try fv.getUInt(usize) else 0,
...@@ -971,11 +906,8 @@ pub const DwarfInfo = struct {...@@ -971,11 +906,8 @@ pub const DwarfInfo = struct {
971 if (compile_unit_die.getAttrAddr(di, AT.low_pc, compile_unit)) |low_pc| {906 if (compile_unit_die.getAttrAddr(di, AT.low_pc, compile_unit)) |low_pc| {
972 if (compile_unit_die.getAttr(AT.high_pc)) |high_pc_value| {907 if (compile_unit_die.getAttr(AT.high_pc)) |high_pc_value| {
973 const pc_end = switch (high_pc_value.*) {908 const pc_end = switch (high_pc_value.*) {
974 FormValue.Address => |value| value,909 .addr => |value| value,
975 FormValue.Const => |value| b: {910 .udata => |offset| low_pc + offset,
976 const offset = try value.asUnsignedLe();
977 break :b (low_pc + offset);
978 },
979 else => return badDwarf(),911 else => return badDwarf(),
980 };912 };
981 break :x PcRange{913 break :x PcRange{
...@@ -1002,40 +934,39 @@ pub const DwarfInfo = struct {...@@ -1002,40 +934,39 @@ pub const DwarfInfo = struct {
1002 section_type: DwarfSection,934 section_type: DwarfSection,
1003 di: *const DwarfInfo,935 di: *const DwarfInfo,
1004 compile_unit: *const CompileUnit,936 compile_unit: *const CompileUnit,
1005 stream: io.FixedBufferStream([]const u8),937 fbr: FixedBufferReader,
1006938
1007 pub fn init(ranges_value: *const FormValue, di: *const DwarfInfo, compile_unit: *const CompileUnit) !@This() {939 pub fn init(ranges_value: *const FormValue, di: *const DwarfInfo, compile_unit: *const CompileUnit) !@This() {
1008 const section_type = if (compile_unit.version >= 5) DwarfSection.debug_rnglists else DwarfSection.debug_ranges;940 const section_type = if (compile_unit.version >= 5) DwarfSection.debug_rnglists else DwarfSection.debug_ranges;
1009 const debug_ranges = di.section(section_type) orelse return error.MissingDebugInfo;941 const debug_ranges = di.section(section_type) orelse return error.MissingDebugInfo;
1010942
1011 const ranges_offset = switch (ranges_value.*) {943 const ranges_offset = switch (ranges_value.*) {
1012 .SecOffset => |off| off,944 .sec_offset, .udata => |off| off,
1013 .Const => |c| try c.asUnsignedLe(),945 .rnglistx => |idx| off: {
1014 .RangeListOffset => |idx| off: {946 switch (compile_unit.format) {
1015 if (compile_unit.is_64) {947 .@"32" => {
1016 const offset_loc = @as(usize, @intCast(compile_unit.rnglists_base + 8 * idx));948 const offset_loc = @as(usize, @intCast(compile_unit.rnglists_base + 4 * idx));
1017 if (offset_loc + 8 > debug_ranges.len) return badDwarf();949 if (offset_loc + 4 > debug_ranges.len) return badDwarf();
1018 const offset = mem.readInt(u64, debug_ranges[offset_loc..][0..8], di.endian);950 const offset = mem.readInt(u32, debug_ranges[offset_loc..][0..4], di.endian);
1019 break :off compile_unit.rnglists_base + offset;951 break :off compile_unit.rnglists_base + offset;
1020 } else {952 },
1021 const offset_loc = @as(usize, @intCast(compile_unit.rnglists_base + 4 * idx));953 .@"64" => {
1022 if (offset_loc + 4 > debug_ranges.len) return badDwarf();954 const offset_loc = @as(usize, @intCast(compile_unit.rnglists_base + 8 * idx));
1023 const offset = mem.readInt(u32, debug_ranges[offset_loc..][0..4], di.endian);955 if (offset_loc + 8 > debug_ranges.len) return badDwarf();
1024 break :off compile_unit.rnglists_base + offset;956 const offset = mem.readInt(u64, debug_ranges[offset_loc..][0..8], di.endian);
957 break :off compile_unit.rnglists_base + offset;
958 },
1025 }959 }
1026 },960 },
1027 else => return badDwarf(),961 else => return badDwarf(),
1028 };962 };
1029963
1030 var stream = io.fixedBufferStream(debug_ranges);
1031 try stream.seekTo(ranges_offset);
1032
1033 // All the addresses in the list are relative to the value964 // All the addresses in the list are relative to the value
1034 // specified by DW_AT.low_pc or to some other value encoded965 // specified by DW_AT.low_pc or to some other value encoded
1035 // in the list itself.966 // in the list itself.
1036 // If no starting value is specified use zero.967 // If no starting value is specified use zero.
1037 const base_address = compile_unit.die.getAttrAddr(di, AT.low_pc, compile_unit.*) catch |err| switch (err) {968 const base_address = compile_unit.die.getAttrAddr(di, AT.low_pc, compile_unit.*) catch |err| switch (err) {
1038 error.MissingDebugInfo => @as(u64, 0), // TODO https://github.com/ziglang/zig/issues/11135969 error.MissingDebugInfo => 0,
1039 else => return err,970 else => return err,
1040 };971 };
1041972
...@@ -1044,28 +975,31 @@ pub const DwarfInfo = struct {...@@ -1044,28 +975,31 @@ pub const DwarfInfo = struct {
1044 .section_type = section_type,975 .section_type = section_type,
1045 .di = di,976 .di = di,
1046 .compile_unit = compile_unit,977 .compile_unit = compile_unit,
1047 .stream = stream,978 .fbr = .{
979 .buf = debug_ranges,
980 .pos = math.cast(usize, ranges_offset) orelse return badDwarf(),
981 .endian = di.endian,
982 },
1048 };983 };
1049 }984 }
1050985
1051 // Returns the next range in the list, or null if the end was reached.986 // Returns the next range in the list, or null if the end was reached.
1052 pub fn next(self: *@This()) !?struct { start_addr: u64, end_addr: u64 } {987 pub fn next(self: *@This()) !?struct { start_addr: u64, end_addr: u64 } {
1053 const in = self.stream.reader();
1054 switch (self.section_type) {988 switch (self.section_type) {
1055 .debug_rnglists => {989 .debug_rnglists => {
1056 const kind = try in.readByte();990 const kind = try self.fbr.readByte();
1057 switch (kind) {991 switch (kind) {
1058 RLE.end_of_list => return null,992 RLE.end_of_list => return null,
1059 RLE.base_addressx => {993 RLE.base_addressx => {
1060 const index = try leb.readULEB128(usize, in);994 const index = try self.fbr.readUleb128(usize);
1061 self.base_address = try self.di.readDebugAddr(self.compile_unit.*, index);995 self.base_address = try self.di.readDebugAddr(self.compile_unit.*, index);
1062 return try self.next();996 return try self.next();
1063 },997 },
1064 RLE.startx_endx => {998 RLE.startx_endx => {
1065 const start_index = try leb.readULEB128(usize, in);999 const start_index = try self.fbr.readUleb128(usize);
1066 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);1000 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);
10671001
1068 const end_index = try leb.readULEB128(usize, in);1002 const end_index = try self.fbr.readUleb128(usize);
1069 const end_addr = try self.di.readDebugAddr(self.compile_unit.*, end_index);1003 const end_addr = try self.di.readDebugAddr(self.compile_unit.*, end_index);
10701004
1071 return .{1005 return .{
...@@ -1074,10 +1008,10 @@ pub const DwarfInfo = struct {...@@ -1074,10 +1008,10 @@ pub const DwarfInfo = struct {
1074 };1008 };
1075 },1009 },
1076 RLE.startx_length => {1010 RLE.startx_length => {
1077 const start_index = try leb.readULEB128(usize, in);1011 const start_index = try self.fbr.readUleb128(usize);
1078 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);1012 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);
10791013
1080 const len = try leb.readULEB128(usize, in);1014 const len = try self.fbr.readUleb128(usize);
1081 const end_addr = start_addr + len;1015 const end_addr = start_addr + len;
10821016
1083 return .{1017 return .{
...@@ -1086,8 +1020,8 @@ pub const DwarfInfo = struct {...@@ -1086,8 +1020,8 @@ pub const DwarfInfo = struct {
1086 };1020 };
1087 },1021 },
1088 RLE.offset_pair => {1022 RLE.offset_pair => {
1089 const start_addr = try leb.readULEB128(usize, in);1023 const start_addr = try self.fbr.readUleb128(usize);
1090 const end_addr = try leb.readULEB128(usize, in);1024 const end_addr = try self.fbr.readUleb128(usize);
10911025
1092 // This is the only kind that uses the base address1026 // This is the only kind that uses the base address
1093 return .{1027 return .{
...@@ -1096,12 +1030,12 @@ pub const DwarfInfo = struct {...@@ -1096,12 +1030,12 @@ pub const DwarfInfo = struct {
1096 };1030 };
1097 },1031 },
1098 RLE.base_address => {1032 RLE.base_address => {
1099 self.base_address = try in.readInt(usize, self.di.endian);1033 self.base_address = try self.fbr.readInt(usize);
1100 return try self.next();1034 return try self.next();
1101 },1035 },
1102 RLE.start_end => {1036 RLE.start_end => {
1103 const start_addr = try in.readInt(usize, self.di.endian);1037 const start_addr = try self.fbr.readInt(usize);
1104 const end_addr = try in.readInt(usize, self.di.endian);1038 const end_addr = try self.fbr.readInt(usize);
11051039
1106 return .{1040 return .{
1107 .start_addr = start_addr,1041 .start_addr = start_addr,
...@@ -1109,8 +1043,8 @@ pub const DwarfInfo = struct {...@@ -1109,8 +1043,8 @@ pub const DwarfInfo = struct {
1109 };1043 };
1110 },1044 },
1111 RLE.start_length => {1045 RLE.start_length => {
1112 const start_addr = try in.readInt(usize, self.di.endian);1046 const start_addr = try self.fbr.readInt(usize);
1113 const len = try leb.readULEB128(usize, in);1047 const len = try self.fbr.readUleb128(usize);
1114 const end_addr = start_addr + len;1048 const end_addr = start_addr + len;
11151049
1116 return .{1050 return .{
...@@ -1122,8 +1056,8 @@ pub const DwarfInfo = struct {...@@ -1122,8 +1056,8 @@ pub const DwarfInfo = struct {
1122 }1056 }
1123 },1057 },
1124 .debug_ranges => {1058 .debug_ranges => {
1125 const start_addr = try in.readInt(usize, self.di.endian);1059 const start_addr = try self.fbr.readInt(usize);
1126 const end_addr = try in.readInt(usize, self.di.endian);1060 const end_addr = try self.fbr.readInt(usize);
1127 if (start_addr == 0 and end_addr == 0) return null;1061 if (start_addr == 0 and end_addr == 0) return null;
11281062
1129 // This entry selects a new value for the base address1063 // This entry selects a new value for the base address
...@@ -1160,93 +1094,96 @@ pub const DwarfInfo = struct {...@@ -1160,93 +1094,96 @@ pub const DwarfInfo = struct {
11601094
1161 /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,1095 /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
1162 /// seeks in the stream and parses it.1096 /// seeks in the stream and parses it.
1163 fn getAbbrevTable(di: *DwarfInfo, allocator: mem.Allocator, abbrev_offset: u64) !*const AbbrevTable {1097 fn getAbbrevTable(di: *DwarfInfo, allocator: mem.Allocator, abbrev_offset: u64) !*const Abbrev.Table {
1164 for (di.abbrev_table_list.items) |*header| {1098 for (di.abbrev_table_list.items) |*table| {
1165 if (header.offset == abbrev_offset) {1099 if (table.offset == abbrev_offset) {
1166 return &header.table;1100 return table;
1167 }1101 }
1168 }1102 }
1169 try di.abbrev_table_list.append(allocator, AbbrevTableHeader{1103 try di.abbrev_table_list.append(
1170 .offset = abbrev_offset,1104 allocator,
1171 .table = try di.parseAbbrevTable(allocator, abbrev_offset),1105 try di.parseAbbrevTable(allocator, abbrev_offset),
1172 });1106 );
1173 return &di.abbrev_table_list.items[di.abbrev_table_list.items.len - 1].table;1107 return &di.abbrev_table_list.items[di.abbrev_table_list.items.len - 1];
1174 }1108 }
11751109
1176 fn parseAbbrevTable(di: *DwarfInfo, allocator: mem.Allocator, offset: u64) !AbbrevTable {1110 fn parseAbbrevTable(di: *DwarfInfo, allocator: mem.Allocator, offset: u64) !Abbrev.Table {
1177 var stream = io.fixedBufferStream(di.section(.debug_abbrev).?);1111 var fbr: FixedBufferReader = .{
1178 const in = stream.reader();1112 .buf = di.section(.debug_abbrev).?,
1179 const seekable = stream.seekableStream();1113 .pos = math.cast(usize, offset) orelse return badDwarf(),
1114 .endian = di.endian,
1115 };
11801116
1181 try seekable.seekTo(offset);1117 var abbrevs = std.ArrayList(Abbrev).init(allocator);
1182 var result = AbbrevTable.init(allocator);1118 defer {
1183 errdefer {1119 for (abbrevs.items) |*abbrev| {
1184 for (result.items) |*entry| {1120 abbrev.deinit(allocator);
1185 entry.attrs.deinit();
1186 }1121 }
1187 result.deinit();1122 abbrevs.deinit();
1188 }1123 }
11891124
1125 var attrs = std.ArrayList(Abbrev.Attr).init(allocator);
1126 defer attrs.deinit();
1127
1190 while (true) {1128 while (true) {
1191 const abbrev_code = try leb.readULEB128(u64, in);1129 const code = try fbr.readUleb128(u64);
1192 if (abbrev_code == 0) return result;1130 if (code == 0) break;
1193 try result.append(AbbrevTableEntry{1131 const tag_id = try fbr.readUleb128(u64);
1194 .abbrev_code = abbrev_code,1132 const has_children = (try fbr.readByte()) == CHILDREN.yes;
1195 .tag_id = try leb.readULEB128(u64, in),
1196 .has_children = (try in.readByte()) == CHILDREN.yes,
1197 .attrs = std.ArrayList(AbbrevAttr).init(allocator),
1198 });
1199 const attrs = &result.items[result.items.len - 1].attrs;
12001133
1201 while (true) {1134 while (true) {
1202 const attr_id = try leb.readULEB128(u64, in);1135 const attr_id = try fbr.readUleb128(u64);
1203 const form_id = try leb.readULEB128(u64, in);1136 const form_id = try fbr.readUleb128(u64);
1204 if (attr_id == 0 and form_id == 0) break;1137 if (attr_id == 0 and form_id == 0) break;
1205 // DW_FORM_implicit_const stores its value immediately after the attribute pair :(1138 try attrs.append(.{
1206 const payload = if (form_id == FORM.implicit_const) try leb.readILEB128(i64, in) else undefined;1139 .id = attr_id,
1207 try attrs.append(AbbrevAttr{
1208 .attr_id = attr_id,
1209 .form_id = form_id,1140 .form_id = form_id,
1210 .payload = payload,1141 .payload = switch (form_id) {
1142 FORM.implicit_const => try fbr.readIleb128(i64),
1143 else => undefined,
1144 },
1211 });1145 });
1212 }1146 }
1147
1148 try abbrevs.append(.{
1149 .code = code,
1150 .tag_id = tag_id,
1151 .has_children = has_children,
1152 .attrs = try attrs.toOwnedSlice(),
1153 });
1213 }1154 }
1155
1156 return .{
1157 .offset = offset,
1158 .abbrevs = try abbrevs.toOwnedSlice(),
1159 };
1214 }1160 }
12151161
1216 fn parseDie(1162 fn parseDie(
1217 di: *DwarfInfo,1163 fbr: *FixedBufferReader,
1218 allocator: mem.Allocator,1164 attrs_buf: []Die.Attr,
1219 in_stream: anytype,1165 abbrev_table: *const Abbrev.Table,
1220 abbrev_table: *const AbbrevTable,1166 format: Format,
1221 is_64: bool,
1222 ) !?Die {1167 ) !?Die {
1223 const abbrev_code = try leb.readULEB128(u64, in_stream);1168 const abbrev_code = try fbr.readUleb128(u64);
1224 if (abbrev_code == 0) return null;1169 if (abbrev_code == 0) return null;
1225 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return badDwarf();1170 const table_entry = abbrev_table.get(abbrev_code) orelse return badDwarf();
12261171
1227 var result = Die{1172 const attrs = attrs_buf[0..table_entry.attrs.len];
1228 // Lives as long as the Die.1173 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = Die.Attr{
1229 .arena = std.heap.ArenaAllocator.init(allocator),1174 .id = attr.id,
1175 .value = try parseFormValue(
1176 fbr,
1177 attr.form_id,
1178 format,
1179 attr.payload,
1180 ),
1181 };
1182 return .{
1230 .tag_id = table_entry.tag_id,1183 .tag_id = table_entry.tag_id,
1231 .has_children = table_entry.has_children,1184 .has_children = table_entry.has_children,
1185 .attrs = attrs,
1232 };1186 };
1233 try result.attrs.resize(allocator, table_entry.attrs.items.len);
1234 for (table_entry.attrs.items, 0..) |attr, i| {
1235 result.attrs.items[i] = Die.Attr{
1236 .id = attr.attr_id,
1237 .value = try parseFormValue(
1238 result.arena.allocator(),
1239 in_stream,
1240 attr.form_id,
1241 di.endian,
1242 is_64,
1243 ),
1244 };
1245 if (attr.form_id == FORM.implicit_const) {
1246 result.attrs.items[i].value.Const.payload = @as(u64, @bitCast(attr.payload));
1247 }
1248 }
1249 return result;
1250 }1187 }
12511188
1252 pub fn getLineNumberInfo(1189 pub fn getLineNumberInfo(
...@@ -1255,50 +1192,47 @@ pub const DwarfInfo = struct {...@@ -1255,50 +1192,47 @@ pub const DwarfInfo = struct {
1255 compile_unit: CompileUnit,1192 compile_unit: CompileUnit,
1256 target_address: u64,1193 target_address: u64,
1257 ) !debug.LineInfo {1194 ) !debug.LineInfo {
1258 var stream = io.fixedBufferStream(di.section(.debug_line).?);
1259 const in = stream.reader();
1260 const seekable = stream.seekableStream();
1261
1262 const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT.comp_dir, di.section(.debug_line_str), compile_unit);1195 const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT.comp_dir, di.section(.debug_line_str), compile_unit);
1263 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);1196 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);
12641197
1265 try seekable.seekTo(line_info_offset);1198 var fbr: FixedBufferReader = .{ .buf = di.section(.debug_line).?, .endian = di.endian };
1199 try fbr.seekTo(line_info_offset);
12661200
1267 var is_64: bool = undefined;1201 const unit_header = try readUnitHeader(&fbr);
1268 const unit_length = try readUnitLength(in, di.endian, &is_64);1202 if (unit_header.unit_length == 0) return missingDwarf();
1269 if (unit_length == 0) {1203 const next_offset = unit_header.header_length + unit_header.unit_length;
1270 return missingDwarf();
1271 }
1272 const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
12731204
1274 const version = try in.readInt(u16, di.endian);1205 const version = try fbr.readInt(u16);
1275 if (version < 2) return badDwarf();1206 if (version < 2) return badDwarf();
12761207
1277 var addr_size: u8 = if (is_64) 8 else 4;1208 var addr_size: u8 = switch (unit_header.format) {
1209 .@"32" => 4,
1210 .@"64" => 8,
1211 };
1278 var seg_size: u8 = 0;1212 var seg_size: u8 = 0;
1279 if (version >= 5) {1213 if (version >= 5) {
1280 addr_size = try in.readByte();1214 addr_size = try fbr.readByte();
1281 seg_size = try in.readByte();1215 seg_size = try fbr.readByte();
1282 }1216 }
12831217
1284 const prologue_length = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian);1218 const prologue_length = try fbr.readAddress(unit_header.format);
1285 const prog_start_offset = (try seekable.getPos()) + prologue_length;1219 const prog_start_offset = fbr.pos + prologue_length;
12861220
1287 const minimum_instruction_length = try in.readByte();1221 const minimum_instruction_length = try fbr.readByte();
1288 if (minimum_instruction_length == 0) return badDwarf();1222 if (minimum_instruction_length == 0) return badDwarf();
12891223
1290 if (version >= 4) {1224 if (version >= 4) {
1291 // maximum_operations_per_instruction1225 // maximum_operations_per_instruction
1292 _ = try in.readByte();1226 _ = try fbr.readByte();
1293 }1227 }
12941228
1295 const default_is_stmt = (try in.readByte()) != 0;1229 const default_is_stmt = (try fbr.readByte()) != 0;
1296 const line_base = try in.readByteSigned();1230 const line_base = try fbr.readByteSigned();
12971231
1298 const line_range = try in.readByte();1232 const line_range = try fbr.readByte();
1299 if (line_range == 0) return badDwarf();1233 if (line_range == 0) return badDwarf();
13001234
1301 const opcode_base = try in.readByte();1235 const opcode_base = try fbr.readByte();
13021236
1303 const standard_opcode_lengths = try allocator.alloc(u8, opcode_base - 1);1237 const standard_opcode_lengths = try allocator.alloc(u8, opcode_base - 1);
1304 defer allocator.free(standard_opcode_lengths);1238 defer allocator.free(standard_opcode_lengths);
...@@ -1306,33 +1240,31 @@ pub const DwarfInfo = struct {...@@ -1306,33 +1240,31 @@ pub const DwarfInfo = struct {
1306 {1240 {
1307 var i: usize = 0;1241 var i: usize = 0;
1308 while (i < opcode_base - 1) : (i += 1) {1242 while (i < opcode_base - 1) : (i += 1) {
1309 standard_opcode_lengths[i] = try in.readByte();1243 standard_opcode_lengths[i] = try fbr.readByte();
1310 }1244 }
1311 }1245 }
13121246
1313 var tmp_arena = std.heap.ArenaAllocator.init(allocator);1247 var include_directories = std.ArrayList(FileEntry).init(allocator);
1314 defer tmp_arena.deinit();1248 defer include_directories.deinit();
1315 const arena = tmp_arena.allocator();1249 var file_entries = std.ArrayList(FileEntry).init(allocator);
13161250 defer file_entries.deinit();
1317 var include_directories = std.ArrayList(FileEntry).init(arena);
1318 var file_entries = std.ArrayList(FileEntry).init(arena);
13191251
1320 if (version < 5) {1252 if (version < 5) {
1321 try include_directories.append(.{ .path = compile_unit_cwd });1253 try include_directories.append(.{ .path = compile_unit_cwd });
13221254
1323 while (true) {1255 while (true) {
1324 const dir = try in.readUntilDelimiterAlloc(arena, 0, math.maxInt(usize));1256 const dir = try fbr.readBytesTo(0);
1325 if (dir.len == 0) break;1257 if (dir.len == 0) break;
1326 try include_directories.append(.{ .path = dir });1258 try include_directories.append(.{ .path = dir });
1327 }1259 }
13281260
1329 while (true) {1261 while (true) {
1330 const file_name = try in.readUntilDelimiterAlloc(arena, 0, math.maxInt(usize));1262 const file_name = try fbr.readBytesTo(0);
1331 if (file_name.len == 0) break;1263 if (file_name.len == 0) break;
1332 const dir_index = try leb.readULEB128(u32, in);1264 const dir_index = try fbr.readUleb128(u32);
1333 const mtime = try leb.readULEB128(u64, in);1265 const mtime = try fbr.readUleb128(u64);
1334 const size = try leb.readULEB128(u64, in);1266 const size = try fbr.readUleb128(u64);
1335 try file_entries.append(FileEntry{1267 try file_entries.append(.{
1336 .path = file_name,1268 .path = file_name,
1337 .dir_index = dir_index,1269 .dir_index = dir_index,
1338 .mtime = mtime,1270 .mtime = mtime,
...@@ -1346,16 +1278,16 @@ pub const DwarfInfo = struct {...@@ -1346,16 +1278,16 @@ pub const DwarfInfo = struct {
1346 };1278 };
1347 {1279 {
1348 var dir_ent_fmt_buf: [10]FileEntFmt = undefined;1280 var dir_ent_fmt_buf: [10]FileEntFmt = undefined;
1349 const directory_entry_format_count = try in.readByte();1281 const directory_entry_format_count = try fbr.readByte();
1350 if (directory_entry_format_count > dir_ent_fmt_buf.len) return badDwarf();1282 if (directory_entry_format_count > dir_ent_fmt_buf.len) return badDwarf();
1351 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |*ent_fmt| {1283 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |*ent_fmt| {
1352 ent_fmt.* = .{1284 ent_fmt.* = .{
1353 .content_type_code = try leb.readULEB128(u8, in),1285 .content_type_code = try fbr.readUleb128(u8),
1354 .form_code = try leb.readULEB128(u16, in),1286 .form_code = try fbr.readUleb128(u16),
1355 };1287 };
1356 }1288 }
13571289
1358 const directories_count = try leb.readULEB128(usize, in);1290 const directories_count = try fbr.readUleb128(usize);
1359 try include_directories.ensureUnusedCapacity(directories_count);1291 try include_directories.ensureUnusedCapacity(directories_count);
1360 {1292 {
1361 var i: usize = 0;1293 var i: usize = 0;
...@@ -1363,18 +1295,20 @@ pub const DwarfInfo = struct {...@@ -1363,18 +1295,20 @@ pub const DwarfInfo = struct {
1363 var e: FileEntry = .{ .path = &.{} };1295 var e: FileEntry = .{ .path = &.{} };
1364 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {1296 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {
1365 const form_value = try parseFormValue(1297 const form_value = try parseFormValue(
1366 arena,1298 &fbr,
1367 in,
1368 ent_fmt.form_code,1299 ent_fmt.form_code,
1369 di.endian,1300 unit_header.format,
1370 is_64,1301 null,
1371 );1302 );
1372 switch (ent_fmt.content_type_code) {1303 switch (ent_fmt.content_type_code) {
1373 LNCT.path => e.path = try form_value.getString(di.*),1304 LNCT.path => e.path = try form_value.getString(di.*),
1374 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1305 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
1375 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),1306 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),
1376 LNCT.size => e.size = try form_value.getUInt(u64),1307 LNCT.size => e.size = try form_value.getUInt(u64),
1377 LNCT.MD5 => e.md5 = try form_value.getData16(),1308 LNCT.MD5 => e.md5 = switch (form_value) {
1309 .data16 => |data16| data16.*,
1310 else => return badDwarf(),
1311 },
1378 else => continue,1312 else => continue,
1379 }1313 }
1380 }1314 }
...@@ -1384,16 +1318,16 @@ pub const DwarfInfo = struct {...@@ -1384,16 +1318,16 @@ pub const DwarfInfo = struct {
1384 }1318 }
13851319
1386 var file_ent_fmt_buf: [10]FileEntFmt = undefined;1320 var file_ent_fmt_buf: [10]FileEntFmt = undefined;
1387 const file_name_entry_format_count = try in.readByte();1321 const file_name_entry_format_count = try fbr.readByte();
1388 if (file_name_entry_format_count > file_ent_fmt_buf.len) return badDwarf();1322 if (file_name_entry_format_count > file_ent_fmt_buf.len) return badDwarf();
1389 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| {1323 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| {
1390 ent_fmt.* = .{1324 ent_fmt.* = .{
1391 .content_type_code = try leb.readULEB128(u8, in),1325 .content_type_code = try fbr.readUleb128(u8),
1392 .form_code = try leb.readULEB128(u16, in),1326 .form_code = try fbr.readUleb128(u16),
1393 };1327 };
1394 }1328 }
13951329
1396 const file_names_count = try leb.readULEB128(usize, in);1330 const file_names_count = try fbr.readUleb128(usize);
1397 try file_entries.ensureUnusedCapacity(file_names_count);1331 try file_entries.ensureUnusedCapacity(file_names_count);
1398 {1332 {
1399 var i: usize = 0;1333 var i: usize = 0;
...@@ -1401,18 +1335,20 @@ pub const DwarfInfo = struct {...@@ -1401,18 +1335,20 @@ pub const DwarfInfo = struct {
1401 var e: FileEntry = .{ .path = &.{} };1335 var e: FileEntry = .{ .path = &.{} };
1402 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {1336 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {
1403 const form_value = try parseFormValue(1337 const form_value = try parseFormValue(
1404 arena,1338 &fbr,
1405 in,
1406 ent_fmt.form_code,1339 ent_fmt.form_code,
1407 di.endian,1340 unit_header.format,
1408 is_64,1341 null,
1409 );1342 );
1410 switch (ent_fmt.content_type_code) {1343 switch (ent_fmt.content_type_code) {
1411 LNCT.path => e.path = try form_value.getString(di.*),1344 LNCT.path => e.path = try form_value.getString(di.*),
1412 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1345 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
1413 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),1346 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),
1414 LNCT.size => e.size = try form_value.getUInt(u64),1347 LNCT.size => e.size = try form_value.getUInt(u64),
1415 LNCT.MD5 => e.md5 = try form_value.getData16(),1348 LNCT.MD5 => e.md5 = switch (form_value) {
1349 .data16 => |data16| data16.*,
1350 else => return badDwarf(),
1351 },
1416 else => continue,1352 else => continue,
1417 }1353 }
1418 }1354 }
...@@ -1428,17 +1364,17 @@ pub const DwarfInfo = struct {...@@ -1428,17 +1364,17 @@ pub const DwarfInfo = struct {
1428 version,1364 version,
1429 );1365 );
14301366
1431 try seekable.seekTo(prog_start_offset);1367 try fbr.seekTo(prog_start_offset);
14321368
1433 const next_unit_pos = line_info_offset + next_offset;1369 const next_unit_pos = line_info_offset + next_offset;
14341370
1435 while ((try seekable.getPos()) < next_unit_pos) {1371 while (fbr.pos < next_unit_pos) {
1436 const opcode = try in.readByte();1372 const opcode = try fbr.readByte();
14371373
1438 if (opcode == LNS.extended_op) {1374 if (opcode == LNS.extended_op) {
1439 const op_size = try leb.readULEB128(u64, in);1375 const op_size = try fbr.readUleb128(u64);
1440 if (op_size < 1) return badDwarf();1376 if (op_size < 1) return badDwarf();
1441 const sub_op = try in.readByte();1377 const sub_op = try fbr.readByte();
1442 switch (sub_op) {1378 switch (sub_op) {
1443 LNE.end_sequence => {1379 LNE.end_sequence => {
1444 prog.end_sequence = true;1380 prog.end_sequence = true;
...@@ -1446,25 +1382,22 @@ pub const DwarfInfo = struct {...@@ -1446,25 +1382,22 @@ pub const DwarfInfo = struct {
1446 prog.reset();1382 prog.reset();
1447 },1383 },
1448 LNE.set_address => {1384 LNE.set_address => {
1449 const addr = try in.readInt(usize, di.endian);1385 const addr = try fbr.readInt(usize);
1450 prog.address = addr;1386 prog.address = addr;
1451 },1387 },
1452 LNE.define_file => {1388 LNE.define_file => {
1453 const path = try in.readUntilDelimiterAlloc(arena, 0, math.maxInt(usize));1389 const path = try fbr.readBytesTo(0);
1454 const dir_index = try leb.readULEB128(u32, in);1390 const dir_index = try fbr.readUleb128(u32);
1455 const mtime = try leb.readULEB128(u64, in);1391 const mtime = try fbr.readUleb128(u64);
1456 const size = try leb.readULEB128(u64, in);1392 const size = try fbr.readUleb128(u64);
1457 try file_entries.append(FileEntry{1393 try file_entries.append(.{
1458 .path = path,1394 .path = path,
1459 .dir_index = dir_index,1395 .dir_index = dir_index,
1460 .mtime = mtime,1396 .mtime = mtime,
1461 .size = size,1397 .size = size,
1462 });1398 });
1463 },1399 },
1464 else => {1400 else => try fbr.seekForward(op_size - 1),
1465 const fwd_amt = math.cast(isize, op_size - 1) orelse return badDwarf();
1466 try seekable.seekBy(fwd_amt);
1467 },
1468 }1401 }
1469 } else if (opcode >= opcode_base) {1402 } else if (opcode >= opcode_base) {
1470 // special opcodes1403 // special opcodes
...@@ -1482,19 +1415,19 @@ pub const DwarfInfo = struct {...@@ -1482,19 +1415,19 @@ pub const DwarfInfo = struct {
1482 prog.basic_block = false;1415 prog.basic_block = false;
1483 },1416 },
1484 LNS.advance_pc => {1417 LNS.advance_pc => {
1485 const arg = try leb.readULEB128(usize, in);1418 const arg = try fbr.readUleb128(usize);
1486 prog.address += arg * minimum_instruction_length;1419 prog.address += arg * minimum_instruction_length;
1487 },1420 },
1488 LNS.advance_line => {1421 LNS.advance_line => {
1489 const arg = try leb.readILEB128(i64, in);1422 const arg = try fbr.readIleb128(i64);
1490 prog.line += arg;1423 prog.line += arg;
1491 },1424 },
1492 LNS.set_file => {1425 LNS.set_file => {
1493 const arg = try leb.readULEB128(usize, in);1426 const arg = try fbr.readUleb128(usize);
1494 prog.file = arg;1427 prog.file = arg;
1495 },1428 },
1496 LNS.set_column => {1429 LNS.set_column => {
1497 const arg = try leb.readULEB128(u64, in);1430 const arg = try fbr.readUleb128(u64);
1498 prog.column = arg;1431 prog.column = arg;
1499 },1432 },
1500 LNS.negate_stmt => {1433 LNS.negate_stmt => {
...@@ -1508,14 +1441,13 @@ pub const DwarfInfo = struct {...@@ -1508,14 +1441,13 @@ pub const DwarfInfo = struct {
1508 prog.address += inc_addr;1441 prog.address += inc_addr;
1509 },1442 },
1510 LNS.fixed_advance_pc => {1443 LNS.fixed_advance_pc => {
1511 const arg = try in.readInt(u16, di.endian);1444 const arg = try fbr.readInt(u16);
1512 prog.address += arg;1445 prog.address += arg;
1513 },1446 },
1514 LNS.set_prologue_end => {},1447 LNS.set_prologue_end => {},
1515 else => {1448 else => {
1516 if (opcode - 1 >= standard_opcode_lengths.len) return badDwarf();1449 if (opcode - 1 >= standard_opcode_lengths.len) return badDwarf();
1517 const len_bytes = standard_opcode_lengths[opcode - 1];1450 try fbr.seekForward(standard_opcode_lengths[opcode - 1]);
1518 try seekable.seekBy(len_bytes);
1519 },1451 },
1520 }1452 }
1521 }1453 }
...@@ -1524,11 +1456,11 @@ pub const DwarfInfo = struct {...@@ -1524,11 +1456,11 @@ pub const DwarfInfo = struct {
1524 return missingDwarf();1456 return missingDwarf();
1525 }1457 }
15261458
1527 fn getString(di: DwarfInfo, offset: u64) ![]const u8 {1459 fn getString(di: DwarfInfo, offset: u64) ![:0]const u8 {
1528 return getStringGeneric(di.section(.debug_str), offset);1460 return getStringGeneric(di.section(.debug_str), offset);
1529 }1461 }
15301462
1531 fn getLineString(di: DwarfInfo, offset: u64) ![]const u8 {1463 fn getLineString(di: DwarfInfo, offset: u64) ![:0]const u8 {
1532 return getStringGeneric(di.section(.debug_line_str), offset);1464 return getStringGeneric(di.section(.debug_line_str), offset);
1533 }1465 }
15341466
...@@ -1564,38 +1496,37 @@ pub const DwarfInfo = struct {...@@ -1564,38 +1496,37 @@ pub const DwarfInfo = struct {
1564 /// of FDEs is built for binary searching during unwinding.1496 /// of FDEs is built for binary searching during unwinding.
1565 pub fn scanAllUnwindInfo(di: *DwarfInfo, allocator: mem.Allocator, base_address: usize) !void {1497 pub fn scanAllUnwindInfo(di: *DwarfInfo, allocator: mem.Allocator, base_address: usize) !void {
1566 if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: {1498 if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: {
1567 var stream = io.fixedBufferStream(eh_frame_hdr);1499 var fbr: FixedBufferReader = .{ .buf = eh_frame_hdr, .endian = native_endian };
1568 const reader = stream.reader();
15691500
1570 const version = try reader.readByte();1501 const version = try fbr.readByte();
1571 if (version != 1) break :blk;1502 if (version != 1) break :blk;
15721503
1573 const eh_frame_ptr_enc = try reader.readByte();1504 const eh_frame_ptr_enc = try fbr.readByte();
1574 if (eh_frame_ptr_enc == EH.PE.omit) break :blk;1505 if (eh_frame_ptr_enc == EH.PE.omit) break :blk;
1575 const fde_count_enc = try reader.readByte();1506 const fde_count_enc = try fbr.readByte();
1576 if (fde_count_enc == EH.PE.omit) break :blk;1507 if (fde_count_enc == EH.PE.omit) break :blk;
1577 const table_enc = try reader.readByte();1508 const table_enc = try fbr.readByte();
1578 if (table_enc == EH.PE.omit) break :blk;1509 if (table_enc == EH.PE.omit) break :blk;
15791510
1580 const eh_frame_ptr = std.math.cast(usize, try readEhPointer(reader, eh_frame_ptr_enc, @sizeOf(usize), .{1511 const eh_frame_ptr = math.cast(usize, try readEhPointer(&fbr, eh_frame_ptr_enc, @sizeOf(usize), .{
1581 .pc_rel_base = @intFromPtr(&eh_frame_hdr[stream.pos]),1512 .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
1582 .follow_indirect = true,1513 .follow_indirect = true,
1583 }, builtin.cpu.arch.endian()) orelse return badDwarf()) orelse return badDwarf();1514 }) orelse return badDwarf()) orelse return badDwarf();
15841515
1585 const fde_count = std.math.cast(usize, try readEhPointer(reader, fde_count_enc, @sizeOf(usize), .{1516 const fde_count = math.cast(usize, try readEhPointer(&fbr, fde_count_enc, @sizeOf(usize), .{
1586 .pc_rel_base = @intFromPtr(&eh_frame_hdr[stream.pos]),1517 .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
1587 .follow_indirect = true,1518 .follow_indirect = true,
1588 }, builtin.cpu.arch.endian()) orelse return badDwarf()) orelse return badDwarf();1519 }) orelse return badDwarf()) orelse return badDwarf();
15891520
1590 const entry_size = try ExceptionFrameHeader.entrySize(table_enc);1521 const entry_size = try ExceptionFrameHeader.entrySize(table_enc);
1591 const entries_len = fde_count * entry_size;1522 const entries_len = fde_count * entry_size;
1592 if (entries_len > eh_frame_hdr.len - stream.pos) return badDwarf();1523 if (entries_len > eh_frame_hdr.len - fbr.pos) return badDwarf();
15931524
1594 di.eh_frame_hdr = .{1525 di.eh_frame_hdr = .{
1595 .eh_frame_ptr = eh_frame_ptr,1526 .eh_frame_ptr = eh_frame_ptr,
1596 .table_enc = table_enc,1527 .table_enc = table_enc,
1597 .fde_count = fde_count,1528 .fde_count = fde_count,
1598 .entries = eh_frame_hdr[stream.pos..][0..entries_len],1529 .entries = eh_frame_hdr[fbr.pos..][0..entries_len],
1599 };1530 };
16001531
1601 // No need to scan .eh_frame, we have a binary search table already1532 // No need to scan .eh_frame, we have a binary search table already
...@@ -1605,16 +1536,16 @@ pub const DwarfInfo = struct {...@@ -1605,16 +1536,16 @@ pub const DwarfInfo = struct {
1605 const frame_sections = [2]DwarfSection{ .eh_frame, .debug_frame };1536 const frame_sections = [2]DwarfSection{ .eh_frame, .debug_frame };
1606 for (frame_sections) |frame_section| {1537 for (frame_sections) |frame_section| {
1607 if (di.section(frame_section)) |section_data| {1538 if (di.section(frame_section)) |section_data| {
1608 var stream = io.fixedBufferStream(section_data);1539 var fbr: FixedBufferReader = .{ .buf = section_data, .endian = di.endian };
1609 while (stream.pos < stream.buffer.len) {1540 while (fbr.pos < fbr.buf.len) {
1610 const entry_header = try EntryHeader.read(&stream, frame_section, di.endian);1541 const entry_header = try EntryHeader.read(&fbr, frame_section);
1611 switch (entry_header.type) {1542 switch (entry_header.type) {
1612 .cie => {1543 .cie => {
1613 const cie = try CommonInformationEntry.parse(1544 const cie = try CommonInformationEntry.parse(
1614 entry_header.entry_bytes,1545 entry_header.entry_bytes,
1615 di.sectionVirtualOffset(frame_section, base_address).?,1546 di.sectionVirtualOffset(frame_section, base_address).?,
1616 true,1547 true,
1617 entry_header.is_64,1548 entry_header.format,
1618 frame_section,1549 frame_section,
1619 entry_header.length_offset,1550 entry_header.length_offset,
1620 @sizeOf(usize),1551 @sizeOf(usize),
...@@ -1638,7 +1569,7 @@ pub const DwarfInfo = struct {...@@ -1638,7 +1569,7 @@ pub const DwarfInfo = struct {
1638 }1569 }
1639 }1570 }
16401571
1641 std.mem.sortUnstable(FrameDescriptionEntry, di.fde_list.items, {}, struct {1572 mem.sortUnstable(FrameDescriptionEntry, di.fde_list.items, {}, struct {
1642 fn lessThan(ctx: void, a: FrameDescriptionEntry, b: FrameDescriptionEntry) bool {1573 fn lessThan(ctx: void, a: FrameDescriptionEntry, b: FrameDescriptionEntry) bool {
1643 _ = ctx;1574 _ = ctx;
1644 return a.pc_begin < b.pc_begin;1575 return a.pc_begin < b.pc_begin;
...@@ -1668,27 +1599,31 @@ pub const DwarfInfo = struct {...@@ -1668,27 +1599,31 @@ pub const DwarfInfo = struct {
1668 const frame_section = di.section(dwarf_section) orelse return error.MissingFDE;1599 const frame_section = di.section(dwarf_section) orelse return error.MissingFDE;
1669 if (fde_offset >= frame_section.len) return error.MissingFDE;1600 if (fde_offset >= frame_section.len) return error.MissingFDE;
16701601
1671 var stream = io.fixedBufferStream(frame_section);1602 var fbr: FixedBufferReader = .{
1672 try stream.seekTo(fde_offset);1603 .buf = frame_section,
1604 .pos = fde_offset,
1605 .endian = di.endian,
1606 };
16731607
1674 const fde_entry_header = try EntryHeader.read(&stream, dwarf_section, di.endian);1608 const fde_entry_header = try EntryHeader.read(&fbr, dwarf_section);
1675 if (fde_entry_header.type != .fde) return error.MissingFDE;1609 if (fde_entry_header.type != .fde) return error.MissingFDE;
16761610
1677 const cie_offset = fde_entry_header.type.fde;1611 const cie_offset = fde_entry_header.type.fde;
1678 try stream.seekTo(cie_offset);1612 try fbr.seekTo(cie_offset);
16791613
1680 const cie_entry_header = try EntryHeader.read(&stream, dwarf_section, builtin.cpu.arch.endian());1614 fbr.endian = native_endian;
1615 const cie_entry_header = try EntryHeader.read(&fbr, dwarf_section);
1681 if (cie_entry_header.type != .cie) return badDwarf();1616 if (cie_entry_header.type != .cie) return badDwarf();
16821617
1683 cie = try CommonInformationEntry.parse(1618 cie = try CommonInformationEntry.parse(
1684 cie_entry_header.entry_bytes,1619 cie_entry_header.entry_bytes,
1685 0,1620 0,
1686 true,1621 true,
1687 cie_entry_header.is_64,1622 cie_entry_header.format,
1688 dwarf_section,1623 dwarf_section,
1689 cie_entry_header.length_offset,1624 cie_entry_header.length_offset,
1690 @sizeOf(usize),1625 @sizeOf(usize),
1691 builtin.cpu.arch.endian(),1626 native_endian,
1692 );1627 );
16931628
1694 fde = try FrameDescriptionEntry.parse(1629 fde = try FrameDescriptionEntry.parse(
...@@ -1697,7 +1632,7 @@ pub const DwarfInfo = struct {...@@ -1697,7 +1632,7 @@ pub const DwarfInfo = struct {
1697 true,1632 true,
1698 cie,1633 cie,
1699 @sizeOf(usize),1634 @sizeOf(usize),
1700 builtin.cpu.arch.endian(),1635 native_endian,
1701 );1636 );
1702 } else if (di.eh_frame_hdr) |header| {1637 } else if (di.eh_frame_hdr) |header| {
1703 const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null;1638 const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null;
...@@ -1711,7 +1646,7 @@ pub const DwarfInfo = struct {...@@ -1711,7 +1646,7 @@ pub const DwarfInfo = struct {
1711 );1646 );
1712 } else {1647 } else {
1713 const index = std.sort.binarySearch(FrameDescriptionEntry, context.pc, di.fde_list.items, {}, struct {1648 const index = std.sort.binarySearch(FrameDescriptionEntry, context.pc, di.fde_list.items, {}, struct {
1714 pub fn compareFn(_: void, pc: usize, mid_item: FrameDescriptionEntry) std.math.Order {1649 pub fn compareFn(_: void, pc: usize, mid_item: FrameDescriptionEntry) math.Order {
1715 if (pc < mid_item.pc_begin) return .lt;1650 if (pc < mid_item.pc_begin) return .lt;
17161651
1717 const range_end = mid_item.pc_begin + mid_item.pc_range;1652 const range_end = mid_item.pc_begin + mid_item.pc_range;
...@@ -1725,8 +1660,8 @@ pub const DwarfInfo = struct {...@@ -1725,8 +1660,8 @@ pub const DwarfInfo = struct {
1725 cie = di.cie_map.get(fde.cie_length_offset) orelse return error.MissingCIE;1660 cie = di.cie_map.get(fde.cie_length_offset) orelse return error.MissingCIE;
1726 }1661 }
17271662
1728 var expression_context = .{1663 var expression_context: expressions.ExpressionContext = .{
1729 .is_64 = cie.is_64,1664 .format = cie.format,
1730 .isValidMemory = context.isValidMemory,1665 .isValidMemory = context.isValidMemory,
1731 .compile_unit = di.findCompileUnit(fde.pc_begin) catch null,1666 .compile_unit = di.findCompileUnit(fde.pc_begin) catch null,
1732 .thread_context = context.thread_context,1667 .thread_context = context.thread_context,
...@@ -1973,10 +1908,10 @@ pub fn unwindFrameMachO(context: *UnwindContext, unwind_info: []const u8, eh_fra...@@ -1973,10 +1908,10 @@ pub fn unwindFrameMachO(context: *UnwindContext, unwind_info: []const u8, eh_fra
1973 .raw_encoding = common_encodings[entry.encodingIndex],1908 .raw_encoding = common_encodings[entry.encodingIndex],
1974 };1909 };
1975 } else {1910 } else {
1976 const local_index = try std.math.sub(1911 const local_index = try math.sub(
1977 u8,1912 u8,
1978 entry.encodingIndex,1913 entry.encodingIndex,
1979 std.math.cast(u8, header.commonEncodingsArrayCount) orelse return error.InvalidUnwindInfo,1914 math.cast(u8, header.commonEncodingsArrayCount) orelse return error.InvalidUnwindInfo,
1980 );1915 );
1981 const local_encodings = mem.bytesAsSlice(1916 const local_encodings = mem.bytesAsSlice(
1982 macho.compact_unwind_encoding_t,1917 macho.compact_unwind_encoding_t,
...@@ -2187,7 +2122,7 @@ pub fn unwindFrameMachO(context: *UnwindContext, unwind_info: []const u8, eh_fra...@@ -2187,7 +2122,7 @@ pub fn unwindFrameMachO(context: *UnwindContext, unwind_info: []const u8, eh_fra
21872122
2188fn unwindFrameMachODwarf(context: *UnwindContext, eh_frame: []const u8, fde_offset: usize) !usize {2123fn unwindFrameMachODwarf(context: *UnwindContext, eh_frame: []const u8, fde_offset: usize) !usize {
2189 var di = DwarfInfo{2124 var di = DwarfInfo{
2190 .endian = builtin.cpu.arch.endian(),2125 .endian = native_endian,
2191 .is_macho = true,2126 .is_macho = true,
2192 };2127 };
2193 defer di.deinit(context.allocator);2128 defer di.deinit(context.allocator);
...@@ -2207,8 +2142,8 @@ pub const UnwindContext = struct {...@@ -2207,8 +2142,8 @@ pub const UnwindContext = struct {
2207 thread_context: *debug.ThreadContext,2142 thread_context: *debug.ThreadContext,
2208 reg_context: abi.RegisterContext,2143 reg_context: abi.RegisterContext,
2209 isValidMemory: *const fn (address: usize) bool,2144 isValidMemory: *const fn (address: usize) bool,
2210 vm: call_frame.VirtualMachine = .{},2145 vm: call_frame.VirtualMachine,
2211 stack_machine: expressions.StackMachine(.{ .call_frame_context = true }) = .{},2146 stack_machine: expressions.StackMachine(.{ .call_frame_context = true }),
22122147
2213 pub fn init(allocator: mem.Allocator, thread_context: *const debug.ThreadContext, isValidMemory: *const fn (address: usize) bool) !UnwindContext {2148 pub fn init(allocator: mem.Allocator, thread_context: *const debug.ThreadContext, isValidMemory: *const fn (address: usize) bool) !UnwindContext {
2214 const pc = abi.stripInstructionPtrAuthCode((try abi.regValueNative(usize, thread_context, abi.ipRegNum(), null)).*);2149 const pc = abi.stripInstructionPtrAuthCode((try abi.regValueNative(usize, thread_context, abi.ipRegNum(), null)).*);
...@@ -2223,6 +2158,8 @@ pub const UnwindContext = struct {...@@ -2223,6 +2158,8 @@ pub const UnwindContext = struct {
2223 .thread_context = context_copy,2158 .thread_context = context_copy,
2224 .reg_context = undefined,2159 .reg_context = undefined,
2225 .isValidMemory = isValidMemory,2160 .isValidMemory = isValidMemory,
2161 .vm = .{},
2162 .stack_machine = .{},
2226 };2163 };
2227 }2164 }
22282165
...@@ -2230,6 +2167,7 @@ pub const UnwindContext = struct {...@@ -2230,6 +2167,7 @@ pub const UnwindContext = struct {
2230 self.vm.deinit(self.allocator);2167 self.vm.deinit(self.allocator);
2231 self.stack_machine.deinit(self.allocator);2168 self.stack_machine.deinit(self.allocator);
2232 self.allocator.destroy(self.thread_context);2169 self.allocator.destroy(self.thread_context);
2170 self.* = undefined;
2233 }2171 }
22342172
2235 pub fn getFp(self: *const UnwindContext) !usize {2173 pub fn getFp(self: *const UnwindContext) !usize {
...@@ -2281,8 +2219,7 @@ const EhPointerContext = struct {...@@ -2281,8 +2219,7 @@ const EhPointerContext = struct {
2281 text_rel_base: ?u64 = null,2219 text_rel_base: ?u64 = null,
2282 function_rel_base: ?u64 = null,2220 function_rel_base: ?u64 = null,
2283};2221};
22842222fn readEhPointer(fbr: *FixedBufferReader, enc: u8, addr_size_bytes: u8, ctx: EhPointerContext) !?u64 {
2285fn readEhPointer(reader: anytype, enc: u8, addr_size_bytes: u8, ctx: EhPointerContext, endian: std.builtin.Endian) !?u64 {
2286 if (enc == EH.PE.omit) return null;2223 if (enc == EH.PE.omit) return null;
22872224
2288 const value: union(enum) {2225 const value: union(enum) {
...@@ -2291,20 +2228,20 @@ fn readEhPointer(reader: anytype, enc: u8, addr_size_bytes: u8, ctx: EhPointerCo...@@ -2291,20 +2228,20 @@ fn readEhPointer(reader: anytype, enc: u8, addr_size_bytes: u8, ctx: EhPointerCo
2291 } = switch (enc & EH.PE.type_mask) {2228 } = switch (enc & EH.PE.type_mask) {
2292 EH.PE.absptr => .{2229 EH.PE.absptr => .{
2293 .unsigned = switch (addr_size_bytes) {2230 .unsigned = switch (addr_size_bytes) {
2294 2 => try reader.readInt(u16, endian),2231 2 => try fbr.readInt(u16),
2295 4 => try reader.readInt(u32, endian),2232 4 => try fbr.readInt(u32),
2296 8 => try reader.readInt(u64, endian),2233 8 => try fbr.readInt(u64),
2297 else => return error.InvalidAddrSize,2234 else => return error.InvalidAddrSize,
2298 },2235 },
2299 },2236 },
2300 EH.PE.uleb128 => .{ .unsigned = try leb.readULEB128(u64, reader) },2237 EH.PE.uleb128 => .{ .unsigned = try fbr.readUleb128(u64) },
2301 EH.PE.udata2 => .{ .unsigned = try reader.readInt(u16, endian) },2238 EH.PE.udata2 => .{ .unsigned = try fbr.readInt(u16) },
2302 EH.PE.udata4 => .{ .unsigned = try reader.readInt(u32, endian) },2239 EH.PE.udata4 => .{ .unsigned = try fbr.readInt(u32) },
2303 EH.PE.udata8 => .{ .unsigned = try reader.readInt(u64, endian) },2240 EH.PE.udata8 => .{ .unsigned = try fbr.readInt(u64) },
2304 EH.PE.sleb128 => .{ .signed = try leb.readILEB128(i64, reader) },2241 EH.PE.sleb128 => .{ .signed = try fbr.readIleb128(i64) },
2305 EH.PE.sdata2 => .{ .signed = try reader.readInt(i16, endian) },2242 EH.PE.sdata2 => .{ .signed = try fbr.readInt(i16) },
2306 EH.PE.sdata4 => .{ .signed = try reader.readInt(i32, endian) },2243 EH.PE.sdata4 => .{ .signed = try fbr.readInt(i32) },
2307 EH.PE.sdata8 => .{ .signed = try reader.readInt(i64, endian) },2244 EH.PE.sdata8 => .{ .signed = try fbr.readInt(i64) },
2308 else => return badDwarf(),2245 else => return badDwarf(),
2309 };2246 };
23102247
...@@ -2396,18 +2333,17 @@ pub const ExceptionFrameHeader = struct {...@@ -2396,18 +2333,17 @@ pub const ExceptionFrameHeader = struct {
2396 var left: usize = 0;2333 var left: usize = 0;
2397 var len: usize = self.fde_count;2334 var len: usize = self.fde_count;
23982335
2399 var stream = io.fixedBufferStream(self.entries);2336 var fbr: FixedBufferReader = .{ .buf = self.entries, .endian = native_endian };
2400 const reader = stream.reader();
24012337
2402 while (len > 1) {2338 while (len > 1) {
2403 const mid = left + len / 2;2339 const mid = left + len / 2;
24042340
2405 try stream.seekTo(mid * entry_size);2341 fbr.pos = mid * entry_size;
2406 const pc_begin = try readEhPointer(reader, self.table_enc, @sizeOf(usize), .{2342 const pc_begin = try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{
2407 .pc_rel_base = @intFromPtr(&self.entries[stream.pos]),2343 .pc_rel_base = @intFromPtr(&self.entries[fbr.pos]),
2408 .follow_indirect = true,2344 .follow_indirect = true,
2409 .data_rel_base = eh_frame_hdr_ptr,2345 .data_rel_base = eh_frame_hdr_ptr,
2410 }, builtin.cpu.arch.endian()) orelse return badDwarf();2346 }) orelse return badDwarf();
24112347
2412 if (pc < pc_begin) {2348 if (pc < pc_begin) {
2413 len /= 2;2349 len /= 2;
...@@ -2419,20 +2355,20 @@ pub const ExceptionFrameHeader = struct {...@@ -2419,20 +2355,20 @@ pub const ExceptionFrameHeader = struct {
2419 }2355 }
24202356
2421 if (len == 0) return badDwarf();2357 if (len == 0) return badDwarf();
2422 try stream.seekTo(left * entry_size);2358 fbr.pos = left * entry_size;
24232359
2424 // Read past the pc_begin field of the entry2360 // Read past the pc_begin field of the entry
2425 _ = try readEhPointer(reader, self.table_enc, @sizeOf(usize), .{2361 _ = try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{
2426 .pc_rel_base = @intFromPtr(&self.entries[stream.pos]),2362 .pc_rel_base = @intFromPtr(&self.entries[fbr.pos]),
2427 .follow_indirect = true,2363 .follow_indirect = true,
2428 .data_rel_base = eh_frame_hdr_ptr,2364 .data_rel_base = eh_frame_hdr_ptr,
2429 }, builtin.cpu.arch.endian()) orelse return badDwarf();2365 }) orelse return badDwarf();
24302366
2431 const fde_ptr = math.cast(usize, try readEhPointer(reader, self.table_enc, @sizeOf(usize), .{2367 const fde_ptr = math.cast(usize, try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{
2432 .pc_rel_base = @intFromPtr(&self.entries[stream.pos]),2368 .pc_rel_base = @intFromPtr(&self.entries[fbr.pos]),
2433 .follow_indirect = true,2369 .follow_indirect = true,
2434 .data_rel_base = eh_frame_hdr_ptr,2370 .data_rel_base = eh_frame_hdr_ptr,
2435 }, builtin.cpu.arch.endian()) orelse return badDwarf()) orelse return badDwarf();2371 }) orelse return badDwarf()) orelse return badDwarf();
24362372
2437 // Verify the length fields of the FDE header are readable2373 // Verify the length fields of the FDE header are readable
2438 if (!self.isValidPtr(fde_ptr, isValidMemory, eh_frame_len) or fde_ptr < self.eh_frame_ptr) return badDwarf();2374 if (!self.isValidPtr(fde_ptr, isValidMemory, eh_frame_len) or fde_ptr < self.eh_frame_ptr) return badDwarf();
...@@ -2445,17 +2381,20 @@ pub const ExceptionFrameHeader = struct {...@@ -2445,17 +2381,20 @@ pub const ExceptionFrameHeader = struct {
2445 const eh_frame = @as([*]const u8, @ptrFromInt(self.eh_frame_ptr))[0 .. eh_frame_len orelse math.maxInt(u32)];2381 const eh_frame = @as([*]const u8, @ptrFromInt(self.eh_frame_ptr))[0 .. eh_frame_len orelse math.maxInt(u32)];
24462382
2447 const fde_offset = fde_ptr - self.eh_frame_ptr;2383 const fde_offset = fde_ptr - self.eh_frame_ptr;
2448 var eh_frame_stream = io.fixedBufferStream(eh_frame);2384 var eh_frame_fbr: FixedBufferReader = .{
2449 try eh_frame_stream.seekTo(fde_offset);2385 .buf = eh_frame,
2386 .pos = fde_offset,
2387 .endian = native_endian,
2388 };
24502389
2451 const fde_entry_header = try EntryHeader.read(&eh_frame_stream, .eh_frame, builtin.cpu.arch.endian());2390 const fde_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame);
2452 if (!self.isValidPtr(@intFromPtr(&fde_entry_header.entry_bytes[fde_entry_header.entry_bytes.len - 1]), isValidMemory, eh_frame_len)) return badDwarf();2391 if (!self.isValidPtr(@intFromPtr(&fde_entry_header.entry_bytes[fde_entry_header.entry_bytes.len - 1]), isValidMemory, eh_frame_len)) return badDwarf();
2453 if (fde_entry_header.type != .fde) return badDwarf();2392 if (fde_entry_header.type != .fde) return badDwarf();
24542393
2455 // CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable2394 // CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable
2456 const cie_offset = fde_entry_header.type.fde;2395 const cie_offset = fde_entry_header.type.fde;
2457 try eh_frame_stream.seekTo(cie_offset);2396 try eh_frame_fbr.seekTo(cie_offset);
2458 const cie_entry_header = try EntryHeader.read(&eh_frame_stream, .eh_frame, builtin.cpu.arch.endian());2397 const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame);
2459 if (!self.isValidPtr(@intFromPtr(&cie_entry_header.entry_bytes[cie_entry_header.entry_bytes.len - 1]), isValidMemory, eh_frame_len)) return badDwarf();2398 if (!self.isValidPtr(@intFromPtr(&cie_entry_header.entry_bytes[cie_entry_header.entry_bytes.len - 1]), isValidMemory, eh_frame_len)) return badDwarf();
2460 if (cie_entry_header.type != .cie) return badDwarf();2399 if (cie_entry_header.type != .cie) return badDwarf();
24612400
...@@ -2463,11 +2402,11 @@ pub const ExceptionFrameHeader = struct {...@@ -2463,11 +2402,11 @@ pub const ExceptionFrameHeader = struct {
2463 cie_entry_header.entry_bytes,2402 cie_entry_header.entry_bytes,
2464 0,2403 0,
2465 true,2404 true,
2466 cie_entry_header.is_64,2405 cie_entry_header.format,
2467 .eh_frame,2406 .eh_frame,
2468 cie_entry_header.length_offset,2407 cie_entry_header.length_offset,
2469 @sizeOf(usize),2408 @sizeOf(usize),
2470 builtin.cpu.arch.endian(),2409 native_endian,
2471 );2410 );
24722411
2473 fde.* = try FrameDescriptionEntry.parse(2412 fde.* = try FrameDescriptionEntry.parse(
...@@ -2476,7 +2415,7 @@ pub const ExceptionFrameHeader = struct {...@@ -2476,7 +2415,7 @@ pub const ExceptionFrameHeader = struct {
2476 true,2415 true,
2477 cie.*,2416 cie.*,
2478 @sizeOf(usize),2417 @sizeOf(usize),
2479 builtin.cpu.arch.endian(),2418 native_endian,
2480 );2419 );
2481 }2420 }
2482};2421};
...@@ -2484,62 +2423,60 @@ pub const ExceptionFrameHeader = struct {...@@ -2484,62 +2423,60 @@ pub const ExceptionFrameHeader = struct {
2484pub const EntryHeader = struct {2423pub const EntryHeader = struct {
2485 /// Offset of the length field in the backing buffer2424 /// Offset of the length field in the backing buffer
2486 length_offset: usize,2425 length_offset: usize,
2487 is_64: bool,2426 format: Format,
2488 type: union(enum) {2427 type: union(enum) {
2489 cie,2428 cie,
2490 /// Value is the offset of the corresponding CIE2429 /// Value is the offset of the corresponding CIE
2491 fde: u64,2430 fde: u64,
2492 terminator: void,2431 terminator,
2493 },2432 },
2494 /// The entry's contents, not including the ID field2433 /// The entry's contents, not including the ID field
2495 entry_bytes: []const u8,2434 entry_bytes: []const u8,
24962435
2497 /// Reads a header for either an FDE or a CIE, then advances the stream to the position after the trailing structure.2436 /// The length of the entry including the ID field, but not the length field itself
2498 /// `stream` must be a stream backed by either the .eh_frame or .debug_frame sections.2437 pub fn entryLength(self: EntryHeader) usize {
2499 pub fn read(stream: *std.io.FixedBufferStream([]const u8), dwarf_section: DwarfSection, endian: std.builtin.Endian) !EntryHeader {2438 return self.entry_bytes.len + @as(u8, if (self.is_64) 8 else 4);
2500 assert(dwarf_section == .eh_frame or dwarf_section == .debug_frame);2439 }
25012440
2502 const reader = stream.reader();2441 /// Reads a header for either an FDE or a CIE, then advances the fbr to the position after the trailing structure.
2503 const length_offset = stream.pos;2442 /// `fbr` must be a FixedBufferReader backed by either the .eh_frame or .debug_frame sections.
2443 pub fn read(fbr: *FixedBufferReader, dwarf_section: DwarfSection) !EntryHeader {
2444 assert(dwarf_section == .eh_frame or dwarf_section == .debug_frame);
25042445
2505 var is_64: bool = undefined;2446 const length_offset = fbr.pos;
2506 const length = math.cast(usize, try readUnitLength(reader, endian, &is_64)) orelse return badDwarf();2447 const unit_header = try readUnitHeader(fbr);
2507 if (length == 0) return .{2448 const unit_length = math.cast(usize, unit_header.unit_length) orelse return badDwarf();
2449 if (unit_length == 0) return .{
2508 .length_offset = length_offset,2450 .length_offset = length_offset,
2509 .is_64 = is_64,2451 .format = unit_header.format,
2510 .type = .{ .terminator = {} },2452 .type = .terminator,
2511 .entry_bytes = &.{},2453 .entry_bytes = &.{},
2512 };2454 };
2455 const start_offset = fbr.pos;
2456 const end_offset = start_offset + unit_length;
2457 defer fbr.pos = end_offset;
25132458
2514 const id_len = @as(u8, if (is_64) 8 else 4);2459 const id = try fbr.readAddress(unit_header.format);
2515 const id = if (is_64) try reader.readInt(u64, endian) else try reader.readInt(u32, endian);2460 const entry_bytes = fbr.buf[fbr.pos..end_offset];
2516 const entry_bytes = stream.buffer[stream.pos..][0 .. length - id_len];
2517 const cie_id: u64 = switch (dwarf_section) {2461 const cie_id: u64 = switch (dwarf_section) {
2518 .eh_frame => CommonInformationEntry.eh_id,2462 .eh_frame => CommonInformationEntry.eh_id,
2519 .debug_frame => if (is_64) CommonInformationEntry.dwarf64_id else CommonInformationEntry.dwarf32_id,2463 .debug_frame => switch (unit_header.format) {
2464 .@"32" => CommonInformationEntry.dwarf32_id,
2465 .@"64" => CommonInformationEntry.dwarf64_id,
2466 },
2520 else => unreachable,2467 else => unreachable,
2521 };2468 };
25222469
2523 const result = EntryHeader{2470 return .{
2524 .length_offset = length_offset,2471 .length_offset = length_offset,
2525 .is_64 = is_64,2472 .format = unit_header.format,
2526 .type = if (id == cie_id) .{ .cie = {} } else .{2473 .type = if (id == cie_id) .cie else .{ .fde = switch (dwarf_section) {
2527 .fde = switch (dwarf_section) {2474 .eh_frame => try math.sub(u64, start_offset, id),
2528 .eh_frame => try std.math.sub(u64, stream.pos - id_len, id),2475 .debug_frame => id,
2529 .debug_frame => id,2476 else => unreachable,
2530 else => unreachable,2477 } },
2531 },
2532 },
2533 .entry_bytes = entry_bytes,2478 .entry_bytes = entry_bytes,
2534 };2479 };
2535
2536 stream.pos += entry_bytes.len;
2537 return result;
2538 }
2539
2540 /// The length of the entry including the ID field, but not the length field itself
2541 pub fn entryLength(self: EntryHeader) usize {
2542 return self.entry_bytes.len + @as(u8, if (self.is_64) 8 else 4);
2543 }2480 }
2544};2481};
25452482
...@@ -2558,7 +2495,7 @@ pub const CommonInformationEntry = struct {...@@ -2558,7 +2495,7 @@ pub const CommonInformationEntry = struct {
2558 length_offset: u64,2495 length_offset: u64,
2559 version: u8,2496 version: u8,
2560 address_size: u8,2497 address_size: u8,
2561 is_64: bool,2498 format: Format,
25622499
2563 // Only present in version 42500 // Only present in version 4
2564 segment_selector_size: ?u8,2501 segment_selector_size: ?u8,
...@@ -2602,7 +2539,7 @@ pub const CommonInformationEntry = struct {...@@ -2602,7 +2539,7 @@ pub const CommonInformationEntry = struct {
2602 cie_bytes: []const u8,2539 cie_bytes: []const u8,
2603 pc_rel_offset: i64,2540 pc_rel_offset: i64,
2604 is_runtime: bool,2541 is_runtime: bool,
2605 is_64: bool,2542 format: Format,
2606 dwarf_section: DwarfSection,2543 dwarf_section: DwarfSection,
2607 length_offset: u64,2544 length_offset: u64,
2608 addr_size_bytes: u8,2545 addr_size_bytes: u8,
...@@ -2610,10 +2547,9 @@ pub const CommonInformationEntry = struct {...@@ -2610,10 +2547,9 @@ pub const CommonInformationEntry = struct {
2610 ) !CommonInformationEntry {2547 ) !CommonInformationEntry {
2611 if (addr_size_bytes > 8) return error.UnsupportedAddrSize;2548 if (addr_size_bytes > 8) return error.UnsupportedAddrSize;
26122549
2613 var stream = io.fixedBufferStream(cie_bytes);2550 var fbr: FixedBufferReader = .{ .buf = cie_bytes, .endian = endian };
2614 const reader = stream.reader();
26152551
2616 const version = try reader.readByte();2552 const version = try fbr.readByte();
2617 switch (dwarf_section) {2553 switch (dwarf_section) {
2618 .eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,2554 .eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,
2619 .debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,2555 .debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,
...@@ -2624,9 +2560,9 @@ pub const CommonInformationEntry = struct {...@@ -2624,9 +2560,9 @@ pub const CommonInformationEntry = struct {
2624 var has_aug_data = false;2560 var has_aug_data = false;
26252561
2626 var aug_str_len: usize = 0;2562 var aug_str_len: usize = 0;
2627 const aug_str_start = stream.pos;2563 const aug_str_start = fbr.pos;
2628 var aug_byte = try reader.readByte();2564 var aug_byte = try fbr.readByte();
2629 while (aug_byte != 0) : (aug_byte = try reader.readByte()) {2565 while (aug_byte != 0) : (aug_byte = try fbr.readByte()) {
2630 switch (aug_byte) {2566 switch (aug_byte) {
2631 'z' => {2567 'z' => {
2632 if (aug_str_len != 0) return badDwarf();2568 if (aug_str_len != 0) return badDwarf();
...@@ -2634,7 +2570,7 @@ pub const CommonInformationEntry = struct {...@@ -2634,7 +2570,7 @@ pub const CommonInformationEntry = struct {
2634 },2570 },
2635 'e' => {2571 'e' => {
2636 if (has_aug_data or aug_str_len != 0) return badDwarf();2572 if (has_aug_data or aug_str_len != 0) return badDwarf();
2637 if (try reader.readByte() != 'h') return badDwarf();2573 if (try fbr.readByte() != 'h') return badDwarf();
2638 has_eh_data = true;2574 has_eh_data = true;
2639 },2575 },
2640 else => if (has_eh_data) return badDwarf(),2576 else => if (has_eh_data) return badDwarf(),
...@@ -2645,15 +2581,15 @@ pub const CommonInformationEntry = struct {...@@ -2645,15 +2581,15 @@ pub const CommonInformationEntry = struct {
26452581
2646 if (has_eh_data) {2582 if (has_eh_data) {
2647 // legacy data created by older versions of gcc - unsupported here2583 // legacy data created by older versions of gcc - unsupported here
2648 for (0..addr_size_bytes) |_| _ = try reader.readByte();2584 for (0..addr_size_bytes) |_| _ = try fbr.readByte();
2649 }2585 }
26502586
2651 const address_size = if (version == 4) try reader.readByte() else addr_size_bytes;2587 const address_size = if (version == 4) try fbr.readByte() else addr_size_bytes;
2652 const segment_selector_size = if (version == 4) try reader.readByte() else null;2588 const segment_selector_size = if (version == 4) try fbr.readByte() else null;
26532589
2654 const code_alignment_factor = try leb.readULEB128(u32, reader);2590 const code_alignment_factor = try fbr.readUleb128(u32);
2655 const data_alignment_factor = try leb.readILEB128(i32, reader);2591 const data_alignment_factor = try fbr.readIleb128(i32);
2656 const return_address_register = if (version == 1) try reader.readByte() else try leb.readULEB128(u8, reader);2592 const return_address_register = if (version == 1) try fbr.readByte() else try fbr.readUleb128(u8);
26572593
2658 var lsda_pointer_enc: u8 = EH.PE.omit;2594 var lsda_pointer_enc: u8 = EH.PE.omit;
2659 var personality_enc: ?u8 = null;2595 var personality_enc: ?u8 = null;
...@@ -2662,31 +2598,25 @@ pub const CommonInformationEntry = struct {...@@ -2662,31 +2598,25 @@ pub const CommonInformationEntry = struct {
26622598
2663 var aug_data: []const u8 = &[_]u8{};2599 var aug_data: []const u8 = &[_]u8{};
2664 const aug_str = if (has_aug_data) blk: {2600 const aug_str = if (has_aug_data) blk: {
2665 const aug_data_len = try leb.readULEB128(usize, reader);2601 const aug_data_len = try fbr.readUleb128(usize);
2666 const aug_data_start = stream.pos;2602 const aug_data_start = fbr.pos;
2667 aug_data = cie_bytes[aug_data_start..][0..aug_data_len];2603 aug_data = cie_bytes[aug_data_start..][0..aug_data_len];
26682604
2669 const aug_str = cie_bytes[aug_str_start..][0..aug_str_len];2605 const aug_str = cie_bytes[aug_str_start..][0..aug_str_len];
2670 for (aug_str[1..]) |byte| {2606 for (aug_str[1..]) |byte| {
2671 switch (byte) {2607 switch (byte) {
2672 'L' => {2608 'L' => {
2673 lsda_pointer_enc = try reader.readByte();2609 lsda_pointer_enc = try fbr.readByte();
2674 },2610 },
2675 'P' => {2611 'P' => {
2676 personality_enc = try reader.readByte();2612 personality_enc = try fbr.readByte();
2677 personality_routine_pointer = try readEhPointer(2613 personality_routine_pointer = try readEhPointer(&fbr, personality_enc.?, addr_size_bytes, .{
2678 reader,2614 .pc_rel_base = try pcRelBase(@intFromPtr(&cie_bytes[fbr.pos]), pc_rel_offset),
2679 personality_enc.?,2615 .follow_indirect = is_runtime,
2680 addr_size_bytes,2616 });
2681 .{
2682 .pc_rel_base = try pcRelBase(@intFromPtr(&cie_bytes[stream.pos]), pc_rel_offset),
2683 .follow_indirect = is_runtime,
2684 },
2685 endian,
2686 );
2687 },2617 },
2688 'R' => {2618 'R' => {
2689 fde_pointer_enc = try reader.readByte();2619 fde_pointer_enc = try fbr.readByte();
2690 },2620 },
2691 'S', 'B', 'G' => {},2621 'S', 'B', 'G' => {},
2692 else => return badDwarf(),2622 else => return badDwarf(),
...@@ -2694,16 +2624,16 @@ pub const CommonInformationEntry = struct {...@@ -2694,16 +2624,16 @@ pub const CommonInformationEntry = struct {
2694 }2624 }
26952625
2696 // aug_data_len can include padding so the CIE ends on an address boundary2626 // aug_data_len can include padding so the CIE ends on an address boundary
2697 try stream.seekTo(aug_data_start + aug_data_len);2627 fbr.pos = aug_data_start + aug_data_len;
2698 break :blk aug_str;2628 break :blk aug_str;
2699 } else &[_]u8{};2629 } else &[_]u8{};
27002630
2701 const initial_instructions = cie_bytes[stream.pos..];2631 const initial_instructions = cie_bytes[fbr.pos..];
2702 return .{2632 return .{
2703 .length_offset = length_offset,2633 .length_offset = length_offset,
2704 .version = version,2634 .version = version,
2705 .address_size = address_size,2635 .address_size = address_size,
2706 .is_64 = is_64,2636 .format = format,
2707 .segment_selector_size = segment_selector_size,2637 .segment_selector_size = segment_selector_size,
2708 .code_alignment_factor = code_alignment_factor,2638 .code_alignment_factor = code_alignment_factor,
2709 .data_alignment_factor = data_alignment_factor,2639 .data_alignment_factor = data_alignment_factor,
...@@ -2751,56 +2681,37 @@ pub const FrameDescriptionEntry = struct {...@@ -2751,56 +2681,37 @@ pub const FrameDescriptionEntry = struct {
2751 ) !FrameDescriptionEntry {2681 ) !FrameDescriptionEntry {
2752 if (addr_size_bytes > 8) return error.InvalidAddrSize;2682 if (addr_size_bytes > 8) return error.InvalidAddrSize;
27532683
2754 var stream = io.fixedBufferStream(fde_bytes);2684 var fbr: FixedBufferReader = .{ .buf = fde_bytes, .endian = endian };
2755 const reader = stream.reader();
27562685
2757 const pc_begin = try readEhPointer(2686 const pc_begin = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{
2758 reader,2687 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.pos]), pc_rel_offset),
2759 cie.fde_pointer_enc,2688 .follow_indirect = is_runtime,
2760 addr_size_bytes,2689 }) orelse return badDwarf();
2761 .{2690
2762 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[stream.pos]), pc_rel_offset),2691 const pc_range = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{
2763 .follow_indirect = is_runtime,2692 .pc_rel_base = 0,
2764 },2693 .follow_indirect = false,
2765 endian,2694 }) orelse return badDwarf();
2766 ) orelse return badDwarf();
2767
2768 const pc_range = try readEhPointer(
2769 reader,
2770 cie.fde_pointer_enc,
2771 addr_size_bytes,
2772 .{
2773 .pc_rel_base = 0,
2774 .follow_indirect = false,
2775 },
2776 endian,
2777 ) orelse return badDwarf();
27782695
2779 var aug_data: []const u8 = &[_]u8{};2696 var aug_data: []const u8 = &[_]u8{};
2780 const lsda_pointer = if (cie.aug_str.len > 0) blk: {2697 const lsda_pointer = if (cie.aug_str.len > 0) blk: {
2781 const aug_data_len = try leb.readULEB128(usize, reader);2698 const aug_data_len = try fbr.readUleb128(usize);
2782 const aug_data_start = stream.pos;2699 const aug_data_start = fbr.pos;
2783 aug_data = fde_bytes[aug_data_start..][0..aug_data_len];2700 aug_data = fde_bytes[aug_data_start..][0..aug_data_len];
27842701
2785 const lsda_pointer = if (cie.lsda_pointer_enc != EH.PE.omit)2702 const lsda_pointer = if (cie.lsda_pointer_enc != EH.PE.omit)
2786 try readEhPointer(2703 try readEhPointer(&fbr, cie.lsda_pointer_enc, addr_size_bytes, .{
2787 reader,2704 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.pos]), pc_rel_offset),
2788 cie.lsda_pointer_enc,2705 .follow_indirect = is_runtime,
2789 addr_size_bytes,2706 })
2790 .{
2791 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[stream.pos]), pc_rel_offset),
2792 .follow_indirect = is_runtime,
2793 },
2794 endian,
2795 )
2796 else2707 else
2797 null;2708 null;
27982709
2799 try stream.seekTo(aug_data_start + aug_data_len);2710 fbr.pos = aug_data_start + aug_data_len;
2800 break :blk lsda_pointer;2711 break :blk lsda_pointer;
2801 } else null;2712 } else null;
28022713
2803 const instructions = fde_bytes[stream.pos..];2714 const instructions = fde_bytes[fbr.pos..];
2804 return .{2715 return .{
2805 .cie_length_offset = cie.length_offset,2716 .cie_length_offset = cie.length_offset,
2806 .pc_begin = pc_begin,2717 .pc_begin = pc_begin,
...@@ -2820,6 +2731,75 @@ fn pcRelBase(field_ptr: usize, pc_rel_offset: i64) !usize {...@@ -2820,6 +2731,75 @@ fn pcRelBase(field_ptr: usize, pc_rel_offset: i64) !usize {
2820 }2731 }
2821}2732}
28222733
2734// Reading debug info needs to be fast, even when compiled in debug mode,
2735// so avoid using a `std.io.FixedBufferStream` which is too slow.
2736const FixedBufferReader = struct {
2737 buf: []const u8,
2738 pos: usize = 0,
2739 endian: std.builtin.Endian,
2740
2741 pub const Error = error{ EndOfBuffer, Overflow };
2742
2743 fn seekTo(fbr: *FixedBufferReader, pos: u64) Error!void {
2744 if (pos > fbr.buf.len) return error.EndOfBuffer;
2745 fbr.pos = @intCast(pos);
2746 }
2747
2748 fn seekForward(fbr: *FixedBufferReader, amount: u64) Error!void {
2749 if (fbr.buf.len - fbr.pos < amount) return error.EndOfBuffer;
2750 fbr.pos += @intCast(amount);
2751 }
2752
2753 pub inline fn readByte(fbr: *FixedBufferReader) Error!u8 {
2754 if (fbr.pos >= fbr.buf.len) return error.EndOfBuffer;
2755 defer fbr.pos += 1;
2756 return fbr.buf[fbr.pos];
2757 }
2758
2759 fn readByteSigned(fbr: *FixedBufferReader) Error!i8 {
2760 return @bitCast(try fbr.readByte());
2761 }
2762
2763 fn readInt(fbr: *FixedBufferReader, comptime T: type) Error!T {
2764 const size = @divExact(@typeInfo(T).Int.bits, 8);
2765 if (fbr.buf.len - fbr.pos < size) return error.EndOfBuffer;
2766 defer fbr.pos += size;
2767 return mem.readInt(T, fbr.buf[fbr.pos..][0..size], fbr.endian);
2768 }
2769
2770 fn readUleb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
2771 return std.leb.readULEB128(T, fbr);
2772 }
2773
2774 fn readIleb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
2775 return std.leb.readILEB128(T, fbr);
2776 }
2777
2778 fn readAddress(fbr: *FixedBufferReader, format: Format) Error!u64 {
2779 return switch (format) {
2780 .@"32" => try fbr.readInt(u32),
2781 .@"64" => try fbr.readInt(u64),
2782 };
2783 }
2784
2785 fn readBytes(fbr: *FixedBufferReader, len: usize) Error![]const u8 {
2786 if (fbr.buf.len - fbr.pos < len) return error.EndOfBuffer;
2787 defer fbr.pos += len;
2788 return fbr.buf[fbr.pos..][0..len];
2789 }
2790
2791 fn readBytesTo(fbr: *FixedBufferReader, comptime sentinel: u8) Error![:sentinel]const u8 {
2792 const end = @call(.always_inline, mem.indexOfScalarPos, .{
2793 u8,
2794 fbr.buf,
2795 fbr.pos,
2796 sentinel,
2797 }) orelse return error.EndOfBuffer;
2798 defer fbr.pos = end + 1;
2799 return fbr.buf[fbr.pos..end :sentinel];
2800 }
2801};
2802
2823test {2803test {
2824 std.testing.refAllDecls(@This());2804 std.testing.refAllDecls(@This());
2825}2805}
lib/std/dwarf/TAG.zig+3
...@@ -116,3 +116,6 @@ pub const upc_relaxed_type = 0x8767;...@@ -116,3 +116,6 @@ pub const upc_relaxed_type = 0x8767;
116// PGI (STMicroelectronics; extensions. No documentation available.116// PGI (STMicroelectronics; extensions. No documentation available.
117pub const PGI_kanji_type = 0xA000;117pub const PGI_kanji_type = 0xA000;
118pub const PGI_interface_block = 0xA020;118pub const PGI_interface_block = 0xA020;
119
120// ZIG extensions.
121pub const ZIG_padding = 0xfdb1;
lib/std/dwarf/expressions.zig+9-9
...@@ -12,8 +12,8 @@ const native_endian = builtin.cpu.arch.endian();...@@ -12,8 +12,8 @@ const native_endian = builtin.cpu.arch.endian();
12/// Callers should specify all the fields relevant to their context. If a field is required12/// Callers should specify all the fields relevant to their context. If a field is required
13/// by the expression and it isn't in the context, error.IncompleteExpressionContext is returned.13/// by the expression and it isn't in the context, error.IncompleteExpressionContext is returned.
14pub const ExpressionContext = struct {14pub const ExpressionContext = struct {
15 /// This expression is from a DWARF64 section15 /// The dwarf format of the section this expression is in
16 is_64: bool = false,16 format: dwarf.Format = .@"32",
1717
18 /// If specified, any addresses will pass through this function before being acccessed18 /// If specified, any addresses will pass through this function before being acccessed
19 isValidMemory: ?*const fn (address: usize) bool = null,19 isValidMemory: ?*const fn (address: usize) bool = null,
...@@ -190,10 +190,10 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -190,10 +190,10 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
190 const reader = stream.reader();190 const reader = stream.reader();
191 return switch (opcode) {191 return switch (opcode) {
192 OP.addr => generic(try reader.readInt(addr_type, options.endian)),192 OP.addr => generic(try reader.readInt(addr_type, options.endian)),
193 OP.call_ref => if (context.is_64)193 OP.call_ref => switch (context.format) {
194 generic(try reader.readInt(u64, options.endian))194 .@"32" => generic(try reader.readInt(u32, options.endian)),
195 else195 .@"64" => generic(try reader.readInt(u64, options.endian)),
196 generic(try reader.readInt(u32, options.endian)),196 },
197 OP.const1u,197 OP.const1u,
198 OP.pick,198 OP.pick,
199 => generic(try reader.readByte()),199 => generic(try reader.readByte()),
...@@ -366,15 +366,15 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -366,15 +366,15 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
366 _ = offset;366 _ = offset;
367367
368 switch (context.compile_unit.?.frame_base.?.*) {368 switch (context.compile_unit.?.frame_base.?.*) {
369 .ExprLoc => {369 .exprloc => {
370 // TODO: Run this expression in a nested stack machine370 // TODO: Run this expression in a nested stack machine
371 return error.UnimplementedOpcode;371 return error.UnimplementedOpcode;
372 },372 },
373 .LocListOffset => {373 .loclistx => {
374 // TODO: Read value from .debug_loclists374 // TODO: Read value from .debug_loclists
375 return error.UnimplementedOpcode;375 return error.UnimplementedOpcode;
376 },376 },
377 .SecOffset => {377 .sec_offset => {
378 // TODO: Read value from .debug_loclists378 // TODO: Read value from .debug_loclists
379 return error.UnimplementedOpcode;379 return error.UnimplementedOpcode;
380 },380 },
lib/std/io/fixed_buffer_stream.zig+2-6
...@@ -62,11 +62,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {...@@ -62,11 +62,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
62 if (bytes.len == 0) return 0;62 if (bytes.len == 0) return 0;
63 if (self.pos >= self.buffer.len) return error.NoSpaceLeft;63 if (self.pos >= self.buffer.len) return error.NoSpaceLeft;
6464
65 const n = if (self.pos + bytes.len <= self.buffer.len)65 const n = @min(self.buffer.len - self.pos, bytes.len);
66 bytes.len
67 else
68 self.buffer.len - self.pos;
69
70 @memcpy(self.buffer[self.pos..][0..n], bytes[0..n]);66 @memcpy(self.buffer[self.pos..][0..n], bytes[0..n]);
71 self.pos += n;67 self.pos += n;
7268
...@@ -76,7 +72,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {...@@ -76,7 +72,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
76 }72 }
7773
78 pub fn seekTo(self: *Self, pos: u64) SeekError!void {74 pub fn seekTo(self: *Self, pos: u64) SeekError!void {
79 self.pos = if (std.math.cast(usize, pos)) |x| @min(self.buffer.len, x) else self.buffer.len;75 self.pos = @min(std.math.lossyCast(usize, pos), self.buffer.len);
80 }76 }
8177
82 pub fn seekBy(self: *Self, amt: i64) SeekError!void {78 pub fn seekBy(self: *Self, amt: i64) SeekError!void {
src/link/Dwarf.zig+68-59
...@@ -140,11 +140,11 @@ pub const DeclState = struct {...@@ -140,11 +140,11 @@ pub const DeclState = struct {
140 switch (ty.zigTypeTag(mod)) {140 switch (ty.zigTypeTag(mod)) {
141 .NoReturn => unreachable,141 .NoReturn => unreachable,
142 .Void => {142 .Void => {
143 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.pad1));143 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.zero_bit_type));
144 },144 },
145 .Bool => {145 .Bool => {
146 try dbg_info_buffer.ensureUnusedCapacity(12);146 try dbg_info_buffer.ensureUnusedCapacity(12);
147 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.base_type));147 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.base_type));
148 // DW.AT.encoding, DW.FORM.data1148 // DW.AT.encoding, DW.FORM.data1
149 dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean);149 dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean);
150 // DW.AT.byte_size, DW.FORM.udata150 // DW.AT.byte_size, DW.FORM.udata
...@@ -155,7 +155,7 @@ pub const DeclState = struct {...@@ -155,7 +155,7 @@ pub const DeclState = struct {
155 .Int => {155 .Int => {
156 const info = ty.intInfo(mod);156 const info = ty.intInfo(mod);
157 try dbg_info_buffer.ensureUnusedCapacity(12);157 try dbg_info_buffer.ensureUnusedCapacity(12);
158 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.base_type));158 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.base_type));
159 // DW.AT.encoding, DW.FORM.data1159 // DW.AT.encoding, DW.FORM.data1
160 dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) {160 dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) {
161 .signed => DW.ATE.signed,161 .signed => DW.ATE.signed,
...@@ -169,7 +169,7 @@ pub const DeclState = struct {...@@ -169,7 +169,7 @@ pub const DeclState = struct {
169 .Optional => {169 .Optional => {
170 if (ty.isPtrLikeOptional(mod)) {170 if (ty.isPtrLikeOptional(mod)) {
171 try dbg_info_buffer.ensureUnusedCapacity(12);171 try dbg_info_buffer.ensureUnusedCapacity(12);
172 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.base_type));172 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.base_type));
173 // DW.AT.encoding, DW.FORM.data1173 // DW.AT.encoding, DW.FORM.data1
174 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);174 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);
175 // DW.AT.byte_size, DW.FORM.udata175 // DW.AT.byte_size, DW.FORM.udata
...@@ -180,7 +180,7 @@ pub const DeclState = struct {...@@ -180,7 +180,7 @@ pub const DeclState = struct {
180 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }180 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }
181 const payload_ty = ty.optionalChild(mod);181 const payload_ty = ty.optionalChild(mod);
182 // DW.AT.structure_type182 // DW.AT.structure_type
183 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_type));183 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_type));
184 // DW.AT.byte_size, DW.FORM.udata184 // DW.AT.byte_size, DW.FORM.udata
185 const abi_size = ty.abiSize(mod);185 const abi_size = ty.abiSize(mod);
186 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);186 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
...@@ -188,7 +188,7 @@ pub const DeclState = struct {...@@ -188,7 +188,7 @@ pub const DeclState = struct {
188 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});188 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
189 // DW.AT.member189 // DW.AT.member
190 try dbg_info_buffer.ensureUnusedCapacity(7);190 try dbg_info_buffer.ensureUnusedCapacity(7);
191 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));191 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
192 // DW.AT.name, DW.FORM.string192 // DW.AT.name, DW.FORM.string
193 dbg_info_buffer.appendSliceAssumeCapacity("maybe");193 dbg_info_buffer.appendSliceAssumeCapacity("maybe");
194 dbg_info_buffer.appendAssumeCapacity(0);194 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -200,7 +200,7 @@ pub const DeclState = struct {...@@ -200,7 +200,7 @@ pub const DeclState = struct {
200 try dbg_info_buffer.ensureUnusedCapacity(6);200 try dbg_info_buffer.ensureUnusedCapacity(6);
201 dbg_info_buffer.appendAssumeCapacity(0);201 dbg_info_buffer.appendAssumeCapacity(0);
202 // DW.AT.member202 // DW.AT.member
203 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));203 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
204 // DW.AT.name, DW.FORM.string204 // DW.AT.name, DW.FORM.string
205 dbg_info_buffer.appendSliceAssumeCapacity("val");205 dbg_info_buffer.appendSliceAssumeCapacity("val");
206 dbg_info_buffer.appendAssumeCapacity(0);206 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -222,14 +222,14 @@ pub const DeclState = struct {...@@ -222,14 +222,14 @@ pub const DeclState = struct {
222 const ptr_bytes: u8 = @intCast(@divExact(ptr_bits, 8));222 const ptr_bytes: u8 = @intCast(@divExact(ptr_bits, 8));
223 // DW.AT.structure_type223 // DW.AT.structure_type
224 try dbg_info_buffer.ensureUnusedCapacity(2);224 try dbg_info_buffer.ensureUnusedCapacity(2);
225 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_type));225 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_type));
226 // DW.AT.byte_size, DW.FORM.udata226 // DW.AT.byte_size, DW.FORM.udata
227 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));227 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
228 // DW.AT.name, DW.FORM.string228 // DW.AT.name, DW.FORM.string
229 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});229 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
230 // DW.AT.member230 // DW.AT.member
231 try dbg_info_buffer.ensureUnusedCapacity(5);231 try dbg_info_buffer.ensureUnusedCapacity(5);
232 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));232 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
233 // DW.AT.name, DW.FORM.string233 // DW.AT.name, DW.FORM.string
234 dbg_info_buffer.appendSliceAssumeCapacity("ptr");234 dbg_info_buffer.appendSliceAssumeCapacity("ptr");
235 dbg_info_buffer.appendAssumeCapacity(0);235 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -242,7 +242,7 @@ pub const DeclState = struct {...@@ -242,7 +242,7 @@ pub const DeclState = struct {
242 try dbg_info_buffer.ensureUnusedCapacity(6);242 try dbg_info_buffer.ensureUnusedCapacity(6);
243 dbg_info_buffer.appendAssumeCapacity(0);243 dbg_info_buffer.appendAssumeCapacity(0);
244 // DW.AT.member244 // DW.AT.member
245 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));245 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
246 // DW.AT.name, DW.FORM.string246 // DW.AT.name, DW.FORM.string
247 dbg_info_buffer.appendSliceAssumeCapacity("len");247 dbg_info_buffer.appendSliceAssumeCapacity("len");
248 dbg_info_buffer.appendAssumeCapacity(0);248 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -257,7 +257,7 @@ pub const DeclState = struct {...@@ -257,7 +257,7 @@ pub const DeclState = struct {
257 dbg_info_buffer.appendAssumeCapacity(0);257 dbg_info_buffer.appendAssumeCapacity(0);
258 } else {258 } else {
259 try dbg_info_buffer.ensureUnusedCapacity(5);259 try dbg_info_buffer.ensureUnusedCapacity(5);
260 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.ptr_type));260 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.ptr_type));
261 // DW.AT.type, DW.FORM.ref4261 // DW.AT.type, DW.FORM.ref4
262 const index = dbg_info_buffer.items.len;262 const index = dbg_info_buffer.items.len;
263 try dbg_info_buffer.resize(index + 4);263 try dbg_info_buffer.resize(index + 4);
...@@ -266,7 +266,7 @@ pub const DeclState = struct {...@@ -266,7 +266,7 @@ pub const DeclState = struct {
266 },266 },
267 .Array => {267 .Array => {
268 // DW.AT.array_type268 // DW.AT.array_type
269 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.array_type));269 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.array_type));
270 // DW.AT.name, DW.FORM.string270 // DW.AT.name, DW.FORM.string
271 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});271 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
272 // DW.AT.type, DW.FORM.ref4272 // DW.AT.type, DW.FORM.ref4
...@@ -274,7 +274,7 @@ pub const DeclState = struct {...@@ -274,7 +274,7 @@ pub const DeclState = struct {
274 try dbg_info_buffer.resize(index + 4);274 try dbg_info_buffer.resize(index + 4);
275 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(index));275 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(index));
276 // DW.AT.subrange_type276 // DW.AT.subrange_type
277 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.array_dim));277 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.array_dim));
278 // DW.AT.type, DW.FORM.ref4278 // DW.AT.type, DW.FORM.ref4
279 index = dbg_info_buffer.items.len;279 index = dbg_info_buffer.items.len;
280 try dbg_info_buffer.resize(index + 4);280 try dbg_info_buffer.resize(index + 4);
...@@ -287,7 +287,7 @@ pub const DeclState = struct {...@@ -287,7 +287,7 @@ pub const DeclState = struct {
287 },287 },
288 .Struct => {288 .Struct => {
289 // DW.AT.structure_type289 // DW.AT.structure_type
290 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_type));290 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_type));
291 // DW.AT.byte_size, DW.FORM.udata291 // DW.AT.byte_size, DW.FORM.udata
292 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));292 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
293293
...@@ -299,7 +299,7 @@ pub const DeclState = struct {...@@ -299,7 +299,7 @@ pub const DeclState = struct {
299299
300 for (fields.types.get(ip), 0..) |field_ty, field_index| {300 for (fields.types.get(ip), 0..) |field_ty, field_index| {
301 // DW.AT.member301 // DW.AT.member
302 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_member));302 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member));
303 // DW.AT.name, DW.FORM.string303 // DW.AT.name, DW.FORM.string
304 try dbg_info_buffer.writer().print("{d}\x00", .{field_index});304 try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
305 // DW.AT.type, DW.FORM.ref4305 // DW.AT.type, DW.FORM.ref4
...@@ -325,7 +325,7 @@ pub const DeclState = struct {...@@ -325,7 +325,7 @@ pub const DeclState = struct {
325 for (struct_type.field_types.get(ip), struct_type.offsets.get(ip), 0..) |field_ty, field_off, field_index| {325 for (struct_type.field_types.get(ip), struct_type.offsets.get(ip), 0..) |field_ty, field_off, field_index| {
326 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;326 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
327 // DW.AT.member327 // DW.AT.member
328 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_member));328 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member));
329 // DW.AT.name, DW.FORM.string329 // DW.AT.name, DW.FORM.string
330 try dbg_info_buffer.writer().print("{d}\x00", .{field_index});330 try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
331 // DW.AT.type, DW.FORM.ref4331 // DW.AT.type, DW.FORM.ref4
...@@ -345,7 +345,7 @@ pub const DeclState = struct {...@@ -345,7 +345,7 @@ pub const DeclState = struct {
345 const field_name = ip.stringToSlice(field_name_ip);345 const field_name = ip.stringToSlice(field_name_ip);
346 // DW.AT.member346 // DW.AT.member
347 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);347 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
348 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));348 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
349 // DW.AT.name, DW.FORM.string349 // DW.AT.name, DW.FORM.string
350 dbg_info_buffer.appendSliceAssumeCapacity(field_name);350 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
351 dbg_info_buffer.appendAssumeCapacity(0);351 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -367,7 +367,7 @@ pub const DeclState = struct {...@@ -367,7 +367,7 @@ pub const DeclState = struct {
367 },367 },
368 .Enum => {368 .Enum => {
369 // DW.AT.enumeration_type369 // DW.AT.enumeration_type
370 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.enum_type));370 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.enum_type));
371 // DW.AT.byte_size, DW.FORM.udata371 // DW.AT.byte_size, DW.FORM.udata
372 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));372 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
373 // DW.AT.name, DW.FORM.string373 // DW.AT.name, DW.FORM.string
...@@ -379,7 +379,7 @@ pub const DeclState = struct {...@@ -379,7 +379,7 @@ pub const DeclState = struct {
379 const field_name = ip.stringToSlice(field_name_index);379 const field_name = ip.stringToSlice(field_name_index);
380 // DW.AT.enumerator380 // DW.AT.enumerator
381 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));381 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
382 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.enum_variant));382 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.enum_variant));
383 // DW.AT.name, DW.FORM.string383 // DW.AT.name, DW.FORM.string
384 dbg_info_buffer.appendSliceAssumeCapacity(field_name);384 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
385 dbg_info_buffer.appendAssumeCapacity(0);385 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -409,7 +409,7 @@ pub const DeclState = struct {...@@ -409,7 +409,7 @@ pub const DeclState = struct {
409 const is_tagged = layout.tag_size > 0;409 const is_tagged = layout.tag_size > 0;
410 if (is_tagged) {410 if (is_tagged) {
411 // DW.AT.structure_type411 // DW.AT.structure_type
412 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_type));412 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_type));
413 // DW.AT.byte_size, DW.FORM.udata413 // DW.AT.byte_size, DW.FORM.udata
414 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size);414 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size);
415 // DW.AT.name, DW.FORM.string415 // DW.AT.name, DW.FORM.string
...@@ -418,7 +418,7 @@ pub const DeclState = struct {...@@ -418,7 +418,7 @@ pub const DeclState = struct {
418418
419 // DW.AT.member419 // DW.AT.member
420 try dbg_info_buffer.ensureUnusedCapacity(9);420 try dbg_info_buffer.ensureUnusedCapacity(9);
421 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));421 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
422 // DW.AT.name, DW.FORM.string422 // DW.AT.name, DW.FORM.string
423 dbg_info_buffer.appendSliceAssumeCapacity("payload");423 dbg_info_buffer.appendSliceAssumeCapacity("payload");
424 dbg_info_buffer.appendAssumeCapacity(0);424 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -431,7 +431,7 @@ pub const DeclState = struct {...@@ -431,7 +431,7 @@ pub const DeclState = struct {
431 }431 }
432432
433 // DW.AT.union_type433 // DW.AT.union_type
434 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.union_type));434 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.union_type));
435 // DW.AT.byte_size, DW.FORM.udata,435 // DW.AT.byte_size, DW.FORM.udata,
436 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size);436 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size);
437 // DW.AT.name, DW.FORM.string437 // DW.AT.name, DW.FORM.string
...@@ -445,7 +445,7 @@ pub const DeclState = struct {...@@ -445,7 +445,7 @@ pub const DeclState = struct {
445 for (union_obj.field_types.get(ip), union_obj.field_names.get(ip)) |field_ty, field_name| {445 for (union_obj.field_types.get(ip), union_obj.field_names.get(ip)) |field_ty, field_name| {
446 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;446 if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue;
447 // DW.AT.member447 // DW.AT.member
448 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_member));448 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member));
449 // DW.AT.name, DW.FORM.string449 // DW.AT.name, DW.FORM.string
450 try dbg_info_buffer.appendSlice(ip.stringToSlice(field_name));450 try dbg_info_buffer.appendSlice(ip.stringToSlice(field_name));
451 try dbg_info_buffer.append(0);451 try dbg_info_buffer.append(0);
...@@ -462,7 +462,7 @@ pub const DeclState = struct {...@@ -462,7 +462,7 @@ pub const DeclState = struct {
462 if (is_tagged) {462 if (is_tagged) {
463 // DW.AT.member463 // DW.AT.member
464 try dbg_info_buffer.ensureUnusedCapacity(5);464 try dbg_info_buffer.ensureUnusedCapacity(5);
465 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));465 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
466 // DW.AT.name, DW.FORM.string466 // DW.AT.name, DW.FORM.string
467 dbg_info_buffer.appendSliceAssumeCapacity("tag");467 dbg_info_buffer.appendSliceAssumeCapacity("tag");
468 dbg_info_buffer.appendAssumeCapacity(0);468 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -488,7 +488,7 @@ pub const DeclState = struct {...@@ -488,7 +488,7 @@ pub const DeclState = struct {
488 const error_off = if (error_align.compare(.gte, payload_align)) 0 else payload_ty.abiSize(mod);488 const error_off = if (error_align.compare(.gte, payload_align)) 0 else payload_ty.abiSize(mod);
489489
490 // DW.AT.structure_type490 // DW.AT.structure_type
491 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_type));491 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_type));
492 // DW.AT.byte_size, DW.FORM.udata492 // DW.AT.byte_size, DW.FORM.udata
493 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);493 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
494 // DW.AT.name, DW.FORM.string494 // DW.AT.name, DW.FORM.string
...@@ -498,7 +498,7 @@ pub const DeclState = struct {...@@ -498,7 +498,7 @@ pub const DeclState = struct {
498 if (!payload_ty.isNoReturn(mod)) {498 if (!payload_ty.isNoReturn(mod)) {
499 // DW.AT.member499 // DW.AT.member
500 try dbg_info_buffer.ensureUnusedCapacity(7);500 try dbg_info_buffer.ensureUnusedCapacity(7);
501 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));501 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
502 // DW.AT.name, DW.FORM.string502 // DW.AT.name, DW.FORM.string
503 dbg_info_buffer.appendSliceAssumeCapacity("value");503 dbg_info_buffer.appendSliceAssumeCapacity("value");
504 dbg_info_buffer.appendAssumeCapacity(0);504 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -513,7 +513,7 @@ pub const DeclState = struct {...@@ -513,7 +513,7 @@ pub const DeclState = struct {
513 {513 {
514 // DW.AT.member514 // DW.AT.member
515 try dbg_info_buffer.ensureUnusedCapacity(5);515 try dbg_info_buffer.ensureUnusedCapacity(5);
516 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));516 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member));
517 // DW.AT.name, DW.FORM.string517 // DW.AT.name, DW.FORM.string
518 dbg_info_buffer.appendSliceAssumeCapacity("err");518 dbg_info_buffer.appendSliceAssumeCapacity("err");
519 dbg_info_buffer.appendAssumeCapacity(0);519 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -530,7 +530,7 @@ pub const DeclState = struct {...@@ -530,7 +530,7 @@ pub const DeclState = struct {
530 },530 },
531 else => {531 else => {
532 log.debug("TODO implement .debug_info for type '{}'", .{ty.fmt(self.mod)});532 log.debug("TODO implement .debug_info for type '{}'", .{ty.fmt(self.mod)});
533 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.pad1));533 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.zero_bit_type));
534 },534 },
535 }535 }
536 }536 }
...@@ -565,7 +565,7 @@ pub const DeclState = struct {...@@ -565,7 +565,7 @@ pub const DeclState = struct {
565 switch (loc) {565 switch (loc) {
566 .register => |reg| {566 .register => |reg| {
567 try dbg_info.ensureUnusedCapacity(4);567 try dbg_info.ensureUnusedCapacity(4);
568 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevKind.parameter));568 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevCode.parameter));
569 // DW.AT.location, DW.FORM.exprloc569 // DW.AT.location, DW.FORM.exprloc
570 var expr_len = std.io.countingWriter(std.io.null_writer);570 var expr_len = std.io.countingWriter(std.io.null_writer);
571 if (reg < 32) {571 if (reg < 32) {
...@@ -587,7 +587,7 @@ pub const DeclState = struct {...@@ -587,7 +587,7 @@ pub const DeclState = struct {
587 const reg_bytes: u8 = @intCast(@divExact(reg_bits, 8));587 const reg_bytes: u8 = @intCast(@divExact(reg_bits, 8));
588 const abi_size = ty.abiSize(self.mod);588 const abi_size = ty.abiSize(self.mod);
589 try dbg_info.ensureUnusedCapacity(10);589 try dbg_info.ensureUnusedCapacity(10);
590 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevKind.parameter));590 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevCode.parameter));
591 // DW.AT.location, DW.FORM.exprloc591 // DW.AT.location, DW.FORM.exprloc
592 var expr_len = std.io.countingWriter(std.io.null_writer);592 var expr_len = std.io.countingWriter(std.io.null_writer);
593 for (regs, 0..) |reg, reg_i| {593 for (regs, 0..) |reg, reg_i| {
...@@ -620,7 +620,7 @@ pub const DeclState = struct {...@@ -620,7 +620,7 @@ pub const DeclState = struct {
620 },620 },
621 .stack => |info| {621 .stack => |info| {
622 try dbg_info.ensureUnusedCapacity(9);622 try dbg_info.ensureUnusedCapacity(9);
623 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevKind.parameter));623 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevCode.parameter));
624 // DW.AT.location, DW.FORM.exprloc624 // DW.AT.location, DW.FORM.exprloc
625 var expr_len = std.io.countingWriter(std.io.null_writer);625 var expr_len = std.io.countingWriter(std.io.null_writer);
626 if (info.fp_register < 32) {626 if (info.fp_register < 32) {
...@@ -649,7 +649,7 @@ pub const DeclState = struct {...@@ -649,7 +649,7 @@ pub const DeclState = struct {
649 // where each argument is encoded as649 // where each argument is encoded as
650 // <opcode> i:uleb128650 // <opcode> i:uleb128
651 dbg_info.appendSliceAssumeCapacity(&.{651 dbg_info.appendSliceAssumeCapacity(&.{
652 @intFromEnum(AbbrevKind.parameter),652 @intFromEnum(AbbrevCode.parameter),
653 DW.OP.WASM_location,653 DW.OP.WASM_location,
654 DW.OP.WASM_local,654 DW.OP.WASM_local,
655 });655 });
...@@ -676,7 +676,7 @@ pub const DeclState = struct {...@@ -676,7 +676,7 @@ pub const DeclState = struct {
676 const dbg_info = &self.dbg_info;676 const dbg_info = &self.dbg_info;
677 const atom_index = self.di_atom_decls.get(owner_decl).?;677 const atom_index = self.di_atom_decls.get(owner_decl).?;
678 const name_with_null = name.ptr[0 .. name.len + 1];678 const name_with_null = name.ptr[0 .. name.len + 1];
679 try dbg_info.append(@intFromEnum(AbbrevKind.variable));679 try dbg_info.append(@intFromEnum(AbbrevCode.variable));
680 const gpa = self.dwarf.allocator;680 const gpa = self.dwarf.allocator;
681 const mod = self.mod;681 const mod = self.mod;
682 const target = mod.getTarget();682 const target = mod.getTarget();
...@@ -991,8 +991,10 @@ pub const ExprlocRelocation = struct {...@@ -991,8 +991,10 @@ pub const ExprlocRelocation = struct {
991991
992pub const PtrWidth = enum { p32, p64 };992pub const PtrWidth = enum { p32, p64 };
993993
994pub const AbbrevKind = enum(u8) {994pub const AbbrevCode = enum(u8) {
995 compile_unit = 1,995 null,
996 padding,
997 compile_unit,
996 subprogram,998 subprogram,
997 subprogram_retvoid,999 subprogram_retvoid,
998 base_type,1000 base_type,
...@@ -1002,7 +1004,7 @@ pub const AbbrevKind = enum(u8) {...@@ -1002,7 +1004,7 @@ pub const AbbrevKind = enum(u8) {
1002 enum_type,1004 enum_type,
1003 enum_variant,1005 enum_variant,
1004 union_type,1006 union_type,
1005 pad1,1007 zero_bit_type,
1006 parameter,1008 parameter,
1007 variable,1009 variable,
1008 array_type,1010 array_type,
...@@ -1162,7 +1164,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde...@@ -1162,7 +1164,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde
1162 const fn_ret_type = decl.ty.fnReturnType(mod);1164 const fn_ret_type = decl.ty.fnReturnType(mod);
1163 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);1165 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);
1164 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(1166 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(
1165 @as(AbbrevKind, if (fn_ret_has_bits) .subprogram else .subprogram_retvoid),1167 @as(AbbrevCode, if (fn_ret_has_bits) .subprogram else .subprogram_retvoid),
1166 ));1168 ));
1167 // These get overwritten after generating the machine code. These values are1169 // These get overwritten after generating the machine code. These values are
1168 // "relocations" and have to be in this fixed place so that functions can be1170 // "relocations" and have to be in this fixed place so that functions can be
...@@ -1806,7 +1808,14 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1806,7 +1808,14 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1806 // we can simply append these bytes.1808 // we can simply append these bytes.
1807 // zig fmt: off1809 // zig fmt: off
1808 const abbrev_buf = [_]u8{1810 const abbrev_buf = [_]u8{
1809 @intFromEnum(AbbrevKind.compile_unit),1811 @intFromEnum(AbbrevCode.padding),
1812 @as(u8, 0x80) | @as(u7, @truncate(DW.TAG.ZIG_padding >> 0)),
1813 @as(u8, 0x80) | @as(u7, @truncate(DW.TAG.ZIG_padding >> 7)),
1814 @as(u8, 0x00) | @as(u7, @intCast(DW.TAG.ZIG_padding >> 14)),
1815 DW.CHILDREN.no,
1816 0, 0,
1817
1818 @intFromEnum(AbbrevCode.compile_unit),
1810 DW.TAG.compile_unit,1819 DW.TAG.compile_unit,
1811 DW.CHILDREN.yes,1820 DW.CHILDREN.yes,
1812 DW.AT.stmt_list, DW.FORM.sec_offset,1821 DW.AT.stmt_list, DW.FORM.sec_offset,
...@@ -1818,7 +1827,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1818,7 +1827,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1818 DW.AT.language, DW.FORM.data2,1827 DW.AT.language, DW.FORM.data2,
1819 0, 0,1828 0, 0,
18201829
1821 @intFromEnum(AbbrevKind.subprogram),1830 @intFromEnum(AbbrevCode.subprogram),
1822 DW.TAG.subprogram,1831 DW.TAG.subprogram,
1823 DW.CHILDREN.yes,1832 DW.CHILDREN.yes,
1824 DW.AT.low_pc, DW.FORM.addr,1833 DW.AT.low_pc, DW.FORM.addr,
...@@ -1828,7 +1837,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1828,7 +1837,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1828 DW.AT.linkage_name, DW.FORM.string,1837 DW.AT.linkage_name, DW.FORM.string,
1829 0, 0,1838 0, 0,
18301839
1831 @intFromEnum(AbbrevKind.subprogram_retvoid),1840 @intFromEnum(AbbrevCode.subprogram_retvoid),
1832 DW.TAG.subprogram,1841 DW.TAG.subprogram,
1833 DW.CHILDREN.yes,1842 DW.CHILDREN.yes,
1834 DW.AT.low_pc, DW.FORM.addr,1843 DW.AT.low_pc, DW.FORM.addr,
...@@ -1837,25 +1846,25 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1837,25 +1846,25 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1837 DW.AT.linkage_name, DW.FORM.string,1846 DW.AT.linkage_name, DW.FORM.string,
1838 0, 0,1847 0, 0,
18391848
1840 @intFromEnum(AbbrevKind.base_type),1849 @intFromEnum(AbbrevCode.base_type),
1841 DW.TAG.base_type, DW.CHILDREN.no,1850 DW.TAG.base_type, DW.CHILDREN.no,
1842 DW.AT.encoding, DW.FORM.data1,1851 DW.AT.encoding, DW.FORM.data1,
1843 DW.AT.byte_size, DW.FORM.udata,1852 DW.AT.byte_size, DW.FORM.udata,
1844 DW.AT.name, DW.FORM.string,1853 DW.AT.name, DW.FORM.string,
1845 0, 0,1854 0, 0,
18461855
1847 @intFromEnum(AbbrevKind.ptr_type),1856 @intFromEnum(AbbrevCode.ptr_type),
1848 DW.TAG.pointer_type, DW.CHILDREN.no,1857 DW.TAG.pointer_type, DW.CHILDREN.no,
1849 DW.AT.type, DW.FORM.ref4,1858 DW.AT.type, DW.FORM.ref4,
1850 0, 0,1859 0, 0,
18511860
1852 @intFromEnum(AbbrevKind.struct_type),1861 @intFromEnum(AbbrevCode.struct_type),
1853 DW.TAG.structure_type, DW.CHILDREN.yes,1862 DW.TAG.structure_type, DW.CHILDREN.yes,
1854 DW.AT.byte_size, DW.FORM.udata,1863 DW.AT.byte_size, DW.FORM.udata,
1855 DW.AT.name, DW.FORM.string,1864 DW.AT.name, DW.FORM.string,
1856 0, 0,1865 0, 0,
18571866
1858 @intFromEnum(AbbrevKind.struct_member),1867 @intFromEnum(AbbrevCode.struct_member),
1859 DW.TAG.member,1868 DW.TAG.member,
1860 DW.CHILDREN.no,1869 DW.CHILDREN.no,
1861 DW.AT.name, DW.FORM.string,1870 DW.AT.name, DW.FORM.string,
...@@ -1863,31 +1872,31 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1863,31 +1872,31 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1863 DW.AT.data_member_location, DW.FORM.udata,1872 DW.AT.data_member_location, DW.FORM.udata,
1864 0, 0,1873 0, 0,
18651874
1866 @intFromEnum(AbbrevKind.enum_type),1875 @intFromEnum(AbbrevCode.enum_type),
1867 DW.TAG.enumeration_type,1876 DW.TAG.enumeration_type,
1868 DW.CHILDREN.yes,1877 DW.CHILDREN.yes,
1869 DW.AT.byte_size, DW.FORM.udata,1878 DW.AT.byte_size, DW.FORM.udata,
1870 DW.AT.name, DW.FORM.string,1879 DW.AT.name, DW.FORM.string,
1871 0, 0,1880 0, 0,
18721881
1873 @intFromEnum(AbbrevKind.enum_variant),1882 @intFromEnum(AbbrevCode.enum_variant),
1874 DW.TAG.enumerator, DW.CHILDREN.no,1883 DW.TAG.enumerator, DW.CHILDREN.no,
1875 DW.AT.name, DW.FORM.string,1884 DW.AT.name, DW.FORM.string,
1876 DW.AT.const_value, DW.FORM.data8,1885 DW.AT.const_value, DW.FORM.data8,
1877 0, 0,1886 0, 0,
18781887
1879 @intFromEnum(AbbrevKind.union_type),1888 @intFromEnum(AbbrevCode.union_type),
1880 DW.TAG.union_type, DW.CHILDREN.yes,1889 DW.TAG.union_type, DW.CHILDREN.yes,
1881 DW.AT.byte_size, DW.FORM.udata,1890 DW.AT.byte_size, DW.FORM.udata,
1882 DW.AT.name, DW.FORM.string,1891 DW.AT.name, DW.FORM.string,
1883 0, 0,1892 0, 0,
18841893
1885 @intFromEnum(AbbrevKind.pad1),1894 @intFromEnum(AbbrevCode.zero_bit_type),
1886 DW.TAG.unspecified_type,1895 DW.TAG.unspecified_type,
1887 DW.CHILDREN.no,1896 DW.CHILDREN.no,
1888 0, 0,1897 0, 0,
18891898
1890 @intFromEnum(AbbrevKind.parameter),1899 @intFromEnum(AbbrevCode.parameter),
1891 DW.TAG.formal_parameter,1900 DW.TAG.formal_parameter,
1892 DW.CHILDREN.no,1901 DW.CHILDREN.no,
1893 DW.AT.location, DW.FORM.exprloc,1902 DW.AT.location, DW.FORM.exprloc,
...@@ -1895,7 +1904,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1895,7 +1904,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1895 DW.AT.name, DW.FORM.string,1904 DW.AT.name, DW.FORM.string,
1896 0, 0,1905 0, 0,
18971906
1898 @intFromEnum(AbbrevKind.variable),1907 @intFromEnum(AbbrevCode.variable),
1899 DW.TAG.variable,1908 DW.TAG.variable,
1900 DW.CHILDREN.no,1909 DW.CHILDREN.no,
1901 DW.AT.location, DW.FORM.exprloc,1910 DW.AT.location, DW.FORM.exprloc,
...@@ -1903,14 +1912,14 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1903,14 +1912,14 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1903 DW.AT.name, DW.FORM.string,1912 DW.AT.name, DW.FORM.string,
1904 0, 0,1913 0, 0,
19051914
1906 @intFromEnum(AbbrevKind.array_type),1915 @intFromEnum(AbbrevCode.array_type),
1907 DW.TAG.array_type,1916 DW.TAG.array_type,
1908 DW.CHILDREN.yes,1917 DW.CHILDREN.yes,
1909 DW.AT.name, DW.FORM.string,1918 DW.AT.name, DW.FORM.string,
1910 DW.AT.type, DW.FORM.ref4,1919 DW.AT.type, DW.FORM.ref4,
1911 0, 0,1920 0, 0,
19121921
1913 @intFromEnum(AbbrevKind.array_dim),1922 @intFromEnum(AbbrevCode.array_dim),
1914 DW.TAG.subrange_type,1923 DW.TAG.subrange_type,
1915 DW.CHILDREN.no,1924 DW.CHILDREN.no,
1916 DW.AT.type, DW.FORM.ref4,1925 DW.AT.type, DW.FORM.ref4,
...@@ -2007,7 +2016,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64)...@@ -2007,7 +2016,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64)
2007 const comp_dir_strp = try self.strtab.insert(self.allocator, compile_unit_dir);2016 const comp_dir_strp = try self.strtab.insert(self.allocator, compile_unit_dir);
2008 const producer_strp = try self.strtab.insert(self.allocator, link.producer_string);2017 const producer_strp = try self.strtab.insert(self.allocator, link.producer_string);
20092018
2010 di_buf.appendAssumeCapacity(@intFromEnum(AbbrevKind.compile_unit));2019 di_buf.appendAssumeCapacity(@intFromEnum(AbbrevCode.compile_unit));
2011 self.writeOffsetAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset2020 self.writeOffsetAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset
2012 self.writeAddrAssumeCapacity(&di_buf, low_pc);2021 self.writeAddrAssumeCapacity(&di_buf, low_pc);
2013 self.writeAddrAssumeCapacity(&di_buf, high_pc);2022 self.writeAddrAssumeCapacity(&di_buf, high_pc);
...@@ -2226,7 +2235,7 @@ fn pwriteDbgInfoNops(...@@ -2226,7 +2235,7 @@ fn pwriteDbgInfoNops(
2226 const tracy = trace(@src());2235 const tracy = trace(@src());
2227 defer tracy.end();2236 defer tracy.end();
22282237
2229 const page_of_nops = [1]u8{@intFromEnum(AbbrevKind.pad1)} ** 4096;2238 const page_of_nops = [1]u8{@intFromEnum(AbbrevCode.padding)} ** 4096;
2230 var vecs: [32]std.os.iovec_const = undefined;2239 var vecs: [32]std.os.iovec_const = undefined;
2231 var vec_index: usize = 0;2240 var vec_index: usize = 0;
2232 {2241 {
...@@ -2298,9 +2307,9 @@ fn writeDbgInfoNopsToArrayList(...@@ -2298,9 +2307,9 @@ fn writeDbgInfoNopsToArrayList(
2298 buffer.items.len,2307 buffer.items.len,
2299 offset + content.len + next_padding_size + 1,2308 offset + content.len + next_padding_size + 1,
2300 ));2309 ));
2301 @memset(buffer.items[offset - prev_padding_size .. offset], @intFromEnum(AbbrevKind.pad1));2310 @memset(buffer.items[offset - prev_padding_size .. offset], @intFromEnum(AbbrevCode.padding));
2302 @memcpy(buffer.items[offset..][0..content.len], content);2311 @memcpy(buffer.items[offset..][0..content.len], content);
2303 @memset(buffer.items[offset + content.len ..][0..next_padding_size], @intFromEnum(AbbrevKind.pad1));2312 @memset(buffer.items[offset + content.len ..][0..next_padding_size], @intFromEnum(AbbrevCode.padding));
23042313
2305 if (trailing_zero) {2314 if (trailing_zero) {
2306 buffer.items[offset + content.len + next_padding_size] = 0;2315 buffer.items[offset + content.len + next_padding_size] = 0;
...@@ -2842,7 +2851,7 @@ fn addDbgInfoErrorSetNames(...@@ -2842,7 +2851,7 @@ fn addDbgInfoErrorSetNames(
2842 const target_endian = target.cpu.arch.endian();2851 const target_endian = target.cpu.arch.endian();
28432852
2844 // DW.AT.enumeration_type2853 // DW.AT.enumeration_type
2845 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.enum_type));2854 try dbg_info_buffer.append(@intFromEnum(AbbrevCode.enum_type));
2846 // DW.AT.byte_size, DW.FORM.udata2855 // DW.AT.byte_size, DW.FORM.udata
2847 const abi_size = Type.anyerror.abiSize(mod);2856 const abi_size = Type.anyerror.abiSize(mod);
2848 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);2857 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
...@@ -2853,7 +2862,7 @@ fn addDbgInfoErrorSetNames(...@@ -2853,7 +2862,7 @@ fn addDbgInfoErrorSetNames(
2853 // DW.AT.enumerator2862 // DW.AT.enumerator
2854 const no_error = "(no error)";2863 const no_error = "(no error)";
2855 try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64));2864 try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64));
2856 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.enum_variant));2865 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.enum_variant));
2857 // DW.AT.name, DW.FORM.string2866 // DW.AT.name, DW.FORM.string
2858 dbg_info_buffer.appendSliceAssumeCapacity(no_error);2867 dbg_info_buffer.appendSliceAssumeCapacity(no_error);
2859 dbg_info_buffer.appendAssumeCapacity(0);2868 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -2865,7 +2874,7 @@ fn addDbgInfoErrorSetNames(...@@ -2865,7 +2874,7 @@ fn addDbgInfoErrorSetNames(
2865 const error_name = mod.intern_pool.stringToSlice(error_name_ip);2874 const error_name = mod.intern_pool.stringToSlice(error_name_ip);
2866 // DW.AT.enumerator2875 // DW.AT.enumerator
2867 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));2876 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
2868 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.enum_variant));2877 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.enum_variant));
2869 // DW.AT.name, DW.FORM.string2878 // DW.AT.name, DW.FORM.string
2870 dbg_info_buffer.appendSliceAssumeCapacity(error_name);2879 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
2871 dbg_info_buffer.appendAssumeCapacity(0);2880 dbg_info_buffer.appendAssumeCapacity(0);