| ... | ... | @@ -784,8 +784,10 @@ pub const abbrev_subprogram = 2; |
| 784 | 784 | pub const abbrev_subprogram_retvoid = 3; |
| 785 | 785 | pub const abbrev_base_type = 4; |
| 786 | 786 | pub const abbrev_ptr_type = 5; |
| 787 | | pub const abbrev_pad1 = 6; |
| 788 | | pub const abbrev_parameter = 7; |
| 787 | pub const abbrev_anon_struct_type = 6; |
| 788 | pub const abbrev_struct_member = 7; |
| 789 | pub const abbrev_pad1 = 8; |
| 790 | pub const abbrev_parameter = 9; |
| 789 | 791 | |
| 790 | 792 | pub fn flush(self: *Elf, comp: *Compilation) !void { |
| 791 | 793 | if (self.base.options.emit == null) { |
| ... | ... | @@ -882,6 +884,24 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 882 | 884 | DW.FORM.ref4, |
| 883 | 885 | 0, |
| 884 | 886 | 0, // table sentinel |
| 887 | abbrev_anon_struct_type, |
| 888 | DW.TAG.structure_type, |
| 889 | DW.CHILDREN.yes, // header |
| 890 | DW.AT.byte_size, |
| 891 | DW.FORM.sdata, |
| 892 | 0, |
| 893 | 0, // table sentinel |
| 894 | abbrev_struct_member, |
| 895 | DW.TAG.member, |
| 896 | DW.CHILDREN.no, // header |
| 897 | DW.AT.name, |
| 898 | DW.FORM.string, |
| 899 | DW.AT.type, |
| 900 | DW.FORM.ref4, |
| 901 | DW.AT.data_member_location, |
| 902 | DW.FORM.sdata, |
| 903 | 0, |
| 904 | 0, // table sentinel |
| 885 | 905 | abbrev_pad1, |
| 886 | 906 | DW.TAG.unspecified_type, |
| 887 | 907 | DW.CHILDREN.no, // header |
| ... | ... | @@ -2395,6 +2415,16 @@ fn finishUpdateDecl( |
| 2395 | 2415 | dbg_info_type_relocs: *File.DbgInfoTypeRelocsTable, |
| 2396 | 2416 | dbg_info_buffer: *std.ArrayList(u8), |
| 2397 | 2417 | ) !void { |
| 2418 | // We need this for the duration of this function only so that for composite |
| 2419 | // types such as []const u32, if the type *u32 is non-existent, we create |
| 2420 | // it synthetically and store the backing bytes in this arena. After we are |
| 2421 | // done with the relocations, we can safely deinit the entire memory slab. |
| 2422 | // TODO currently, we do not store the relocations for future use, however, |
| 2423 | // if that is the case, we should move memory management to a higher scope, |
| 2424 | // such as linker scope, or whatnot. |
| 2425 | var dbg_type_arena = std.heap.ArenaAllocator.init(self.base.allocator); |
| 2426 | defer dbg_type_arena.deinit(); |
| 2427 | |
| 2398 | 2428 | // Now we emit the .debug_info types of the Decl. These will count towards the size of |
| 2399 | 2429 | // the buffer, so we have to do it before computing the offset, and we can't perform the actual |
| 2400 | 2430 | // relocations yet. |
| ... | ... | @@ -2404,7 +2434,7 @@ fn finishUpdateDecl( |
| 2404 | 2434 | const ty = dbg_info_type_relocs.keys()[it]; |
| 2405 | 2435 | const value_ptr = dbg_info_type_relocs.getPtr(ty).?; |
| 2406 | 2436 | value_ptr.off = @intCast(u32, dbg_info_buffer.items.len); |
| 2407 | | try self.addDbgInfoType(ty, dbg_info_buffer, dbg_info_type_relocs); |
| 2437 | try self.addDbgInfoType(dbg_type_arena.allocator(), ty, dbg_info_buffer, dbg_info_type_relocs); |
| 2408 | 2438 | } |
| 2409 | 2439 | } |
| 2410 | 2440 | |
| ... | ... | @@ -2721,11 +2751,12 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2721 | 2751 | /// Asserts the type has codegen bits. |
| 2722 | 2752 | fn addDbgInfoType( |
| 2723 | 2753 | self: *Elf, |
| 2754 | arena: Allocator, |
| 2724 | 2755 | ty: Type, |
| 2725 | 2756 | dbg_info_buffer: *std.ArrayList(u8), |
| 2726 | 2757 | dbg_info_type_relocs: *File.DbgInfoTypeRelocsTable, |
| 2727 | 2758 | ) error{OutOfMemory}!void { |
| 2728 | | var reloc: ?struct { ty: Type, reloc: u32 } = null; |
| 2759 | var relocs = std.ArrayList(struct { ty: Type, reloc: u32 }).init(arena); |
| 2729 | 2760 | |
| 2730 | 2761 | switch (ty.zigTypeTag()) { |
| 2731 | 2762 | .Void => unreachable, |
| ... | ... | @@ -2767,17 +2798,48 @@ fn addDbgInfoType( |
| 2767 | 2798 | try dbg_info_buffer.append(abbrev_pad1); |
| 2768 | 2799 | } |
| 2769 | 2800 | }, |
| 2770 | | .Pointer => blk: { |
| 2801 | .Pointer => { |
| 2771 | 2802 | if (ty.isSlice()) { |
| 2772 | | log.debug("TODO implement .debug_info for type '{}'", .{ty}); |
| 2773 | | try dbg_info_buffer.append(abbrev_pad1); |
| 2774 | | break :blk; |
| 2803 | // Slices are anonymous structs: struct { .ptr = *, .len = N } |
| 2804 | try dbg_info_buffer.ensureUnusedCapacity(23); |
| 2805 | // DW.AT.structure_type |
| 2806 | dbg_info_buffer.appendAssumeCapacity(abbrev_anon_struct_type); |
| 2807 | // DW.AT.byte_size, DW.FORM.sdata |
| 2808 | dbg_info_buffer.appendAssumeCapacity(16); |
| 2809 | // DW.AT.member |
| 2810 | dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); |
| 2811 | // DW.AT.name, DW.FORM.string |
| 2812 | dbg_info_buffer.appendSliceAssumeCapacity("ptr"); |
| 2813 | dbg_info_buffer.appendAssumeCapacity(0); |
| 2814 | // DW.AT.type, DW.FORM.ref4 |
| 2815 | var index = dbg_info_buffer.items.len; |
| 2816 | try dbg_info_buffer.resize(index + 4); |
| 2817 | var buf = try arena.create(Type.SlicePtrFieldTypeBuffer); |
| 2818 | const ptr_ty = ty.slicePtrFieldType(buf); |
| 2819 | try relocs.append(.{ .ty = ptr_ty, .reloc = @intCast(u32, index) }); |
| 2820 | // DW.AT.data_member_location, DW.FORM.sdata |
| 2821 | dbg_info_buffer.appendAssumeCapacity(0); |
| 2822 | // DW.AT.member |
| 2823 | dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); |
| 2824 | // DW.AT.name, DW.FORM.string |
| 2825 | dbg_info_buffer.appendSliceAssumeCapacity("len"); |
| 2826 | dbg_info_buffer.appendAssumeCapacity(0); |
| 2827 | // DW.AT.type, DW.FORM.ref4 |
| 2828 | index = dbg_info_buffer.items.len; |
| 2829 | try dbg_info_buffer.resize(index + 4); |
| 2830 | try relocs.append(.{ .ty = Type.initTag(.usize), .reloc = @intCast(u32, index) }); |
| 2831 | // DW.AT.data_member_location, DW.FORM.sdata |
| 2832 | dbg_info_buffer.appendAssumeCapacity(8); |
| 2833 | // DW.AT.structure_type delimit children |
| 2834 | dbg_info_buffer.appendAssumeCapacity(0); |
| 2835 | } else { |
| 2836 | try dbg_info_buffer.ensureUnusedCapacity(5); |
| 2837 | dbg_info_buffer.appendAssumeCapacity(abbrev_ptr_type); |
| 2838 | // DW.AT.type, DW.FORM.ref4 |
| 2839 | const index = dbg_info_buffer.items.len; |
| 2840 | try dbg_info_buffer.resize(index + 4); |
| 2841 | try relocs.append(.{ .ty = ty.childType(), .reloc = @intCast(u32, index) }); |
| 2775 | 2842 | } |
| 2776 | | try dbg_info_buffer.ensureUnusedCapacity(5); |
| 2777 | | dbg_info_buffer.appendAssumeCapacity(abbrev_ptr_type); |
| 2778 | | const index = dbg_info_buffer.items.len; |
| 2779 | | try dbg_info_buffer.resize(index + 4); // DW.AT.type, DW.FORM.ref4 |
| 2780 | | reloc = .{ .ty = ty.childType(), .reloc = @intCast(u32, index) }; |
| 2781 | 2843 | }, |
| 2782 | 2844 | else => { |
| 2783 | 2845 | log.debug("TODO implement .debug_info for type '{}'", .{ty}); |
| ... | ... | @@ -2785,7 +2847,7 @@ fn addDbgInfoType( |
| 2785 | 2847 | }, |
| 2786 | 2848 | } |
| 2787 | 2849 | |
| 2788 | | if (reloc) |rel| { |
| 2850 | for (relocs.items) |rel| { |
| 2789 | 2851 | const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, rel.ty); |
| 2790 | 2852 | if (!gop.found_existing) { |
| 2791 | 2853 | gop.value_ptr.* = .{ |