diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index ae995bd0b99e48e2d17c41a45a36b8527b99fdc5..b17eeb57e973d65a75cb8656e4065b4ba4c19382 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2495,21 +2495,39 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } } else if (!self.base.options.strip) { if (self.dwarf) |*dwarf| { - if (self.debug_info_index != null) { - if (self.base.options.module) |mod| { - try dwarf.writeDbgAbbrev(&self.base); - // for debug info and ranges, the address is always 0, - // as locations are always offsets relative to 'code' section. - try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size); - try dwarf.writeDbgAranges(&self.base, 0, code_section_size); - try dwarf.writeDbgLineHeader(&self.base, mod); + const mod = self.base.options.module.?; + try dwarf.writeDbgAbbrev(&self.base); + // for debug info and ranges, the address is always 0, + // as locations are always offsets relative to 'code' section. + try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size); + try dwarf.writeDbgAranges(&self.base, 0, code_section_size); + try dwarf.writeDbgLineHeader(&self.base, mod); + } + + var debug_bytes = std.ArrayList(u8).init(self.base.allocator); + defer debug_bytes.deinit(); + + const debug_sections = .{ + .{ ".debug_info", self.debug_info_index }, + .{ ".debug_pubtypes", self.debug_pubtypes_index }, + .{ ".debug_abbrev", self.debug_abbrev_index }, + .{ ".debug_line", self.debug_line_index }, + .{ ".debug_str", self.debug_str_index }, + .{ ".debug_pubnames", self.debug_pubnames_index }, + .{ ".debug_loc", self.debug_loc_index }, + .{ ".debug_ranges", self.debug_ranges_index }, + }; + + inline for (debug_sections) |item| { + if (item[1]) |index| { + var atom = self.atoms.get(index).?.getFirst(); + while (true) { + atom.resolveRelocs(self); + try debug_bytes.appendSlice(atom.code.items); + atom = atom.next orelse break; } - - try emitDebugSection(file, self.debug_info.items, ".debug_info"); - try emitDebugSection(file, self.debug_aranges.items, ".debug_ranges"); - try emitDebugSection(file, self.debug_abbrev.items, ".debug_abbrev"); - try emitDebugSection(file, self.debug_line.items, ".debug_line"); - try emitDebugSection(file, dwarf.strtab.items, ".debug_str"); + try emitDebugSection(file, debug_bytes.items, item[0]); + debug_bytes.clearRetainingCapacity(); } } try self.emitNameSection(file, arena); @@ -2517,6 +2535,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod } fn emitDebugSection(file: fs.File, data: []const u8, name: []const u8) !void { + if (data.len == 0) return; const header_offset = try reserveCustomSectionHeader(file); const writer = file.writer(); try leb.writeULEB128(writer, @intCast(u32, name.len)); diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index bb00eeb82141afe4576453e257e79795816fa70d..fac5ce3aa8735d45f45b40fee14f9f787bd78b8e 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -77,7 +77,7 @@ const RelocatableData = struct { /// The size in bytes of the data representing the segment within the section size: u32, /// The index within the section itself, or in case of a debug section, - /// the offset within the `debug_names` table. + /// the offset within the `string_table`. index: u32, /// The offset within the section where the data starts offset: u32, @@ -101,9 +101,16 @@ const RelocatableData = struct { return switch (self.type) { .data => .data, .code => .function, - .debug => unreachable, // illegal, debug sections are not represented by a symbol + .debug => .section, }; } + + /// Returns the index within a section itself, or in case of a debug section, + /// returns the section index within the object file. + pub fn getIndex(self: RelocatableData) u32 { + if (self.type == .debug) return self.section_index; + return self.index; + } }; pub const InitError = error{NotObjectFile} || ParseError || std.fs.File.ReadError; @@ -205,7 +212,7 @@ pub fn importedCountByKind(self: *const Object, kind: std.wasm.ExternalKind) u32 /// From a given `RelocatableDate`, find the corresponding debug section name pub fn getDebugName(self: *const Object, relocatable_data: RelocatableData) []const u8 { - return std.mem.sliceTo(self.debug_names[relocatable_data.index..], 0); + return self.string_table.get(relocatable_data.index); } /// Checks if the object file is an MVP version. @@ -363,6 +370,7 @@ fn Parser(comptime ReaderType: type) type { if (std.mem.eql(u8, name, "linking")) { is_object_file.* = true; + self.object.relocatable_data = relocatable_data.items; // at this point no new relocatable sections will appear so we're free to store them. try self.parseMetadata(gpa, @intCast(usize, reader.context.bytes_left)); } else if (std.mem.startsWith(u8, name, "reloc")) { try self.parseRelocations(gpa); @@ -374,19 +382,16 @@ fn Parser(comptime ReaderType: type) type { errdefer gpa.free(debug_content); try reader.readNoEof(debug_content); - const debug_name_index = @intCast(u32, debug_names.items.len); - try debug_names.ensureUnusedCapacity(name.len + 1); - debug_names.appendSliceAssumeCapacity(try gpa.dupe(u8, name)); - debug_names.appendAssumeCapacity(0); try relocatable_data.append(.{ .type = .debug, .data = debug_content.ptr, .size = debug_size, - .index = debug_name_index, + .index = try self.object.string_table.put(gpa, name), .offset = len - debug_size, .section_index = section_index, }); } else { + log.info("found unknown custom section '{s}' - skipping parsing", .{name}); try reader.skipBytes(reader.context.bytes_left, .{}); } }, @@ -551,9 +556,6 @@ fn Parser(comptime ReaderType: type) type { else => |e| return e, } self.object.relocatable_data = relocatable_data.toOwnedSlice(); - - const names = debug_names.toOwnedSlice(); - self.object.debug_names = names[0 .. names.len - 1 :0]; } /// Based on the "features" custom section, parses it into a list of @@ -774,7 +776,12 @@ fn Parser(comptime ReaderType: type) type { }, .section => { symbol.index = try leb.readULEB128(u32, reader); - symbol.name = try self.object.string_table.put(gpa, @tagName(symbol.tag)); + for (self.object.relocatable_data) |data| { + if (data.section_index == symbol.index) { + symbol.name = data.index; + break; + } + } }, else => { symbol.index = try leb.readULEB128(u32, reader); @@ -864,7 +871,6 @@ fn assertEnd(reader: anytype) !void { /// Parses an object file into atoms, for code and data sections pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin: *Wasm) !void { - log.debug("Parsing data section into atoms", .{}); const Key = struct { kind: Symbol.Tag, index: u32, @@ -876,7 +882,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin for (self.symtable) |symbol, symbol_index| { switch (symbol.tag) { - .function, .data => if (!symbol.isUndefined()) { + .function, .data, .section => if (!symbol.isUndefined()) { const gop = try symbol_for_segment.getOrPut(.{ .kind = symbol.tag, .index = symbol.index }); const sym_idx = @intCast(u32, symbol_index); if (!gop.found_existing) { @@ -925,13 +931,11 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin try atom.code.appendSlice(gpa, relocatable_data.data[0..relocatable_data.size]); - if (relocatable_data.type != .debug) { - const symbols = symbol_for_segment.getPtr(.{ - .kind = relocatable_data.getSymbolKind(), - .index = @intCast(u32, relocatable_data.index), - }) orelse continue; // encountered a segment we do not create an atom for - const sym_index = symbols.pop(); - atom.sym_index = sym_index; + if (symbol_for_segment.getPtr(.{ + .kind = relocatable_data.getSymbolKind(), + .index = relocatable_data.getIndex(), + })) |symbols| { + atom.sym_index = symbols.pop(); // symbols referencing the same atom will be added as alias // or as 'parent' when they are global. @@ -957,7 +961,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin } else { try wasm_bin.atoms.putNoClobber(gpa, final_index, atom); } - log.debug("Parsed into atom: '{s}'", .{self.string_table.get(self.symtable[atom.sym_index].name)}); + log.debug("Parsed into atom: '{s}' at segment index {d}", .{ self.string_table.get(self.symtable[atom.sym_index].name), final_index }); } }