diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-08-29 20:13:55 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-09-07 18:53:12 +0200 |
| commit | 9a92f3d290694bfefbc7d71b5ba1823edb6c547f (patch) | |
| tree | a2b6759748a3c0d561d0bccdcbe43f14e7d20c4b /src/link | |
| parent | 924679abc46deeaae9284ab6ce928aaddb0fae95 (diff) | |
| download | zig-9a92f3d290694bfefbc7d71b5ba1823edb6c547f.tar.gz zig-9a92f3d290694bfefbc7d71b5ba1823edb6c547f.zip | |
wasm/Object: parse debug sections into reloc data
Rather than storing the name of a debug section into the structure
`RelocatableData`, we use the `index` field as an offset into the
debug names table. This means we do not have to store an extra 16 bytes
for non-debug sections which can be massive for object files where each
data symbol has its own data section. The name of a debug section
can then be retrieved again when needed by using the offset and
then reading until the 0-delimiter.
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Wasm.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm/Object.zig | 51 |
2 files changed, 45 insertions, 8 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 050d9287a5..a62a11a389 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1782,7 +1782,7 @@ pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32 }); break :blk index; }, - .custom => return error.@"TODO: Custom section relocations for wasm", + .debug => return error.@"TODO: Custom section relocations for wasm", } } diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 50827ca9fb..d07d0b39ea 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -63,16 +63,21 @@ relocatable_data: []const RelocatableData = &.{}, /// import name, module name and export names. Each string will be deduplicated /// and returns an offset into the table. string_table: Wasm.StringTable = .{}, +/// All the names of each debug section found in the current object file. +/// Each name is terminated by a null-terminator. The name can be found, +/// from the `index` offset within the `RelocatableData`. +debug_names: [:0]const u8, /// Represents a single item within a section (depending on its `type`) const RelocatableData = struct { /// The type of the relocatable data - type: enum { data, code, custom }, + type: enum { data, code, debug }, /// Pointer to the data of the segment, where its length is written to `size` data: [*]u8, /// The size in bytes of the data representing the segment within the section size: u32, - /// The index within the section itself + /// The index within the section itself, or in case of a debug section, + /// the offset within the `debug_names` table. index: u32, /// The offset within the section where the data starts offset: u32, @@ -96,7 +101,7 @@ const RelocatableData = struct { return switch (self.type) { .data => .data, .code => .function, - .custom => .section, + .debug => unreachable, // illegal, debug sections are not represented by a symbol }; } }; @@ -111,6 +116,7 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz var object: Object = .{ .file = file, .name = try gpa.dupe(u8, name), + .debug_names = &.{}, }; var is_object_file: bool = false; @@ -197,6 +203,11 @@ pub fn importedCountByKind(self: *const Object, kind: std.wasm.ExternalKind) u32 } else i; } +/// 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); +} + /// Checks if the object file is an MVP version. /// When that's the case, we check if there's an import table definiton with its name /// set to '__indirect_function_table". When that's also the case, @@ -328,10 +339,15 @@ fn Parser(comptime ReaderType: type) type { self.object.version = version; var relocatable_data = std.ArrayList(RelocatableData).init(gpa); - - errdefer while (relocatable_data.popOrNull()) |rel_data| { - gpa.free(rel_data.data[0..rel_data.size]); - } else relocatable_data.deinit(); + var debug_names = std.ArrayList(u8).init(gpa); + + errdefer { + while (relocatable_data.popOrNull()) |rel_data| { + gpa.free(rel_data.data[0..rel_data.size]); + } else relocatable_data.deinit(); + gpa.free(debug_names.items); + debug_names.deinit(); + } var section_index: u32 = 0; while (self.reader.reader().readByte()) |byte| : (section_index += 1) { @@ -352,6 +368,24 @@ fn Parser(comptime ReaderType: type) type { try self.parseRelocations(gpa); } else if (std.mem.eql(u8, name, "target_features")) { try self.parseFeatures(gpa); + } else if (std.mem.startsWith(u8, name, ".debug")) { + const debug_size = @intCast(u32, reader.context.bytes_left); + const debug_content = try gpa.alloc(u8, debug_size); + 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, + .offset = len - debug_size, + .section_index = section_index, + }); } else { try reader.skipBytes(reader.context.bytes_left, .{}); } @@ -517,6 +551,9 @@ 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 |
