aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-08-29 20:13:55 +0200
committerLuuk de Gram <luuk@degram.dev>2022-09-07 18:53:12 +0200
commit9a92f3d290694bfefbc7d71b5ba1823edb6c547f (patch)
treea2b6759748a3c0d561d0bccdcbe43f14e7d20c4b /src
parent924679abc46deeaae9284ab6ce928aaddb0fae95 (diff)
downloadzig-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')
-rw-r--r--src/link/Wasm.zig2
-rw-r--r--src/link/Wasm/Object.zig51
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