authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-05-10 00:48:48-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:13-04:00
loga0a40c2e7e177bed7032ddd3d271016127ae9205
treefd9ac796767e430ef597304c3e64bb2c8d3a5fdd
parent7b4611cfb3eb0c1c3f4fcae8c0a4beaf28473803

- implement more opcodes


1 files changed, 93 insertions(+), 25 deletions(-)

lib/std/dwarf/call_frame.zig+93-25
...@@ -171,7 +171,7 @@ pub const Instruction = union(Opcode) {...@@ -171,7 +171,7 @@ pub const Instruction = union(Opcode) {
171 advance_loc4: InstructionType(.{ .delta = .u32_delta }),171 advance_loc4: InstructionType(.{ .delta = .u32_delta }),
172 undefined: InstructionType(.{ .register = .uleb128_register }),172 undefined: InstructionType(.{ .register = .uleb128_register }),
173 same_value: InstructionType(.{ .register = .uleb128_register }),173 same_value: InstructionType(.{ .register = .uleb128_register }),
174 register: InstructionType(.{ .register = .uleb128_register, .offset = .uleb128_offset }),174 register: InstructionType(.{ .register = .uleb128_register, .target_register = .uleb128_register }),
175 remember_state: InstructionType(.{}),175 remember_state: InstructionType(.{}),
176 restore_state: InstructionType(.{}),176 restore_state: InstructionType(.{}),
177 def_cfa: InstructionType(.{ .register = .uleb128_register, .offset = .uleb128_offset }),177 def_cfa: InstructionType(.{ .register = .uleb128_register, .offset = .uleb128_offset }),
...@@ -229,15 +229,20 @@ pub const VirtualMachine = struct {...@@ -229,15 +229,20 @@ pub const VirtualMachine = struct {
229 architectural: void,229 architectural: void,
230 };230 };
231231
232 /// Each row contains unwinding rules for a set of registers at a specific location in the232 /// Each row contains unwinding rules for a set of registers.
233 pub const Row = struct {233 pub const Row = struct {
234 /// Offset from pc_begin234 /// Offset from `FrameDescriptionEntry.pc_begin`
235 offset: u64 = 0,235 offset: u64 = 0,
236
236 /// Special-case column that defines the CFA (Canonical Frame Address) rule.237 /// Special-case column that defines the CFA (Canonical Frame Address) rule.
237 /// The register field of this column defines the register that CFA is derived238 /// The register field of this column defines the register that CFA is derived
238 /// from, while other columns define registers in terms of the CFA.239 /// from, while other columns define register rules in terms of the CFA.
239 cfa: Column = .{},240 cfa: Column = .{},
240 columns: ColumnRange = .{},241 columns: ColumnRange = .{},
242
243 /// Indicates that the next write to any column in this row needs to copy
244 /// the backing column storage first.
245 copy_on_write: bool = false,
241 };246 };
242247
243 pub const Column = struct {248 pub const Column = struct {
...@@ -339,6 +344,17 @@ pub const VirtualMachine = struct {...@@ -339,6 +344,17 @@ pub const VirtualMachine = struct {
339 self.stepTo(allocator, pc, cie, fde, @sizeOf(usize), builtin.target.cpu.arch.endian());344 self.stepTo(allocator, pc, cie, fde, @sizeOf(usize), builtin.target.cpu.arch.endian());
340 }345 }
341346
347 fn resolveCopyOnWrite(self: *VirtualMachine, allocator: std.mem.Allocator) !void {
348 if (!self.current_row.copy_on_write) return;
349
350 const new_start = self.columns.items.len;
351 if (self.current_row.columns.len > 0) {
352 try self.columns.ensureUnusedCapacity(allocator, self.current_row.columns.len);
353 self.columns.appendSliceAssumeCapacity(self.rowColumns(self.current_row));
354 self.current_row.columns.start = new_start;
355 }
356 }
357
342 /// Executes a single instruction.358 /// Executes a single instruction.
343 /// If this instruction is from the CIE, `is_initial` should be set.359 /// If this instruction is from the CIE, `is_initial` should be set.
344 /// Returns the value of `current_row` before executing this instruction360 /// Returns the value of `current_row` before executing this instruction
...@@ -355,14 +371,36 @@ pub const VirtualMachine = struct {...@@ -355,14 +371,36 @@ pub const VirtualMachine = struct {
355371
356 const prev_row = self.current_row;372 const prev_row = self.current_row;
357 switch (instruction) {373 switch (instruction) {
358 inline .advance_loc, .advance_loc1, .advance_loc2, .advance_loc4 => |i| {374 .set_loc => |i| {
375 if (i.operands.address <= self.current_row.offset) return error.InvalidOperation;
376 // TODO: Check cie.segment_selector_size != for DWARFV4
377 self.current_row.offset = i.operands.address;
378 },
379 inline .advance_loc,
380 .advance_loc1,
381 .advance_loc2,
382 .advance_loc4,
383 => |i| {
359 self.current_row.offset += i.operands.delta * cie.code_alignment_factor;384 self.current_row.offset += i.operands.delta * cie.code_alignment_factor;
385 self.current_row.copy_on_write = true;
360 },386 },
361 inline .offset, .offset_extended => |i| {387 inline .offset,
388 .offset_extended,
389 .offset_extended_sf,
390 => |i| {
391 try self.resolveCopyOnWrite(allocator);
362 const column = try self.getOrAddColumn(allocator, i.operands.register);392 const column = try self.getOrAddColumn(allocator, i.operands.register);
363 column.rule = .{ .offset = @intCast(i64, i.operands.offset) * cie.data_alignment_factor };393 column.rule = .{ .offset = @intCast(i64, i.operands.offset) * cie.data_alignment_factor };
364 },394 },
365 inline .restore, .restore_extended => |i| {395 // .offset_extended_sf => |i| {
396 // try self.resolveCopyOnWrite(allocator);
397 // const column = try self.getOrAddColumn(allocator, i.operands.register);
398 // column.rule = .{ .offset = i.operands.offset * cie.data_alignment_factor };
399 // },
400 inline .restore,
401 .restore_extended,
402 => |i| {
403 try self.resolveCopyOnWrite(allocator);
366 if (self.cie_row) |cie_row| {404 if (self.cie_row) |cie_row| {
367 const column = try self.getOrAddColumn(allocator, i.operands.register);405 const column = try self.getOrAddColumn(allocator, i.operands.register);
368 column.rule = for (self.rowColumns(cie_row)) |cie_column| {406 column.rule = for (self.rowColumns(cie_row)) |cie_column| {
...@@ -371,20 +409,31 @@ pub const VirtualMachine = struct {...@@ -371,20 +409,31 @@ pub const VirtualMachine = struct {
371 } else return error.InvalidOperation;409 } else return error.InvalidOperation;
372 },410 },
373 .nop => {},411 .nop => {},
374 .set_loc => {},412 .undefined => |i| {
375 .undefined => {},413 try self.resolveCopyOnWrite(allocator);
376 .same_value => {},414 const column = try self.getOrAddColumn(allocator, i.operands.register);
377 .register => {},415 column.rule = .{ .undefined = {} };
416 },
417 .same_value => |i| {
418 try self.resolveCopyOnWrite(allocator);
419 const column = try self.getOrAddColumn(allocator, i.operands.register);
420 column.rule = .{ .same_value = {} };
421 },
422 .register => |i| {
423 try self.resolveCopyOnWrite(allocator);
424 const column = try self.getOrAddColumn(allocator, i.operands.register);
425 column.rule = .{ .register = i.operands.target_register };
426 },
378 .remember_state => {427 .remember_state => {
379 try self.stack.append(allocator, self.current_row.columns);428 try self.stack.append(allocator, self.current_row.columns);
380 errdefer _ = self.stack.pop();429 self.current_row.copy_on_write = true;
381430
382 const new_start = self.columns.items.len;431 // const new_start = self.columns.items.len;
383 if (self.current_row.columns.len > 0) {432 // if (self.current_row.columns.len > 0) {
384 try self.columns.ensureUnusedCapacity(allocator, self.current_row.columns.len);433 // try self.columns.ensureUnusedCapacity(allocator, self.current_row.columns.len);
385 self.columns.appendSliceAssumeCapacity(self.rowColumns(self.current_row));434 // self.columns.appendSliceAssumeCapacity(self.rowColumns(self.current_row));
386 self.current_row.columns.start = new_start;435 // self.current_row.columns.start = new_start;
387 }436 // }
388 },437 },
389 .restore_state => {438 .restore_state => {
390 const restored_columns = self.stack.popOrNull() orelse return error.InvalidOperation;439 const restored_columns = self.stack.popOrNull() orelse return error.InvalidOperation;
...@@ -396,29 +445,48 @@ pub const VirtualMachine = struct {...@@ -396,29 +445,48 @@ pub const VirtualMachine = struct {
396 self.columns.appendSliceAssumeCapacity(self.columns.items[restored_columns.start..][0..restored_columns.len]);445 self.columns.appendSliceAssumeCapacity(self.columns.items[restored_columns.start..][0..restored_columns.len]);
397 },446 },
398 .def_cfa => |i| {447 .def_cfa => |i| {
448 try self.resolveCopyOnWrite(allocator);
399 self.current_row.cfa = .{449 self.current_row.cfa = .{
400 .register = i.operands.register,450 .register = i.operands.register,
401 .rule = .{ .offset = @intCast(i64, i.operands.offset) },451 .rule = .{ .offset = @intCast(i64, i.operands.offset) },
402 };452 };
403 },453 },
454 .def_cfa_sf => |i| {
455 try self.resolveCopyOnWrite(allocator);
456 self.current_row.cfa = .{
457 .register = i.operands.register,
458 .rule = .{ .offset = i.operands.offset * cie.data_alignment_factor },
459 };
460 },
404 .def_cfa_register => |i| {461 .def_cfa_register => |i| {
405 // TODO: Verify the the current row is using a register and offset (validation)462 try self.resolveCopyOnWrite(allocator);
463 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .offset) return error.InvalidOperation;
406 self.current_row.cfa.register = i.operands.register;464 self.current_row.cfa.register = i.operands.register;
407 },465 },
408 .def_cfa_offset => |i| {466 .def_cfa_offset => |i| {
409 // TODO: Verify the the current row is using a register and offset (validation)467 try self.resolveCopyOnWrite(allocator);
468 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .offset) return error.InvalidOperation;
410 self.current_row.cfa.rule = .{ .offset = @intCast(i64, i.operands.offset) };469 self.current_row.cfa.rule = .{ .offset = @intCast(i64, i.operands.offset) };
411 },470 },
471 .def_cfa_offset_sf => |i| {
472 try self.resolveCopyOnWrite(allocator);
473 if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .offset) return error.InvalidOperation;
474 self.current_row.cfa.rule = .{ .offset = i.operands.offset * cie.data_alignment_factor };
475 },
412 .def_cfa_expression => |i| {476 .def_cfa_expression => |i| {
477 try self.resolveCopyOnWrite(allocator);
413 self.current_row.cfa.register = undefined;478 self.current_row.cfa.register = undefined;
414 self.current_row.cfa.rule = .{479 self.current_row.cfa.rule = .{
415 .expression = i.operands.block,480 .expression = i.operands.block,
416 };481 };
417 },482 },
418 .expression => {},483 .expression => |i| {
419 .offset_extended_sf => {},484 try self.resolveCopyOnWrite(allocator);
420 .def_cfa_sf => {},485 const column = try self.getOrAddColumn(allocator, i.operands.register);
421 .def_cfa_offset_sf => {},486 column.rule = .{
487 .expression = i.operands.block,
488 };
489 },
422 .val_offset => {},490 .val_offset => {},
423 .val_offset_sf => {},491 .val_offset_sf => {},
424 .val_expression => {},492 .val_expression => {},