| ... | @@ -63,16 +63,21 @@ relocatable_data: []const RelocatableData = &.{}, | ... | @@ -63,16 +63,21 @@ relocatable_data: []const RelocatableData = &.{}, |
| 63 | /// import name, module name and export names. Each string will be deduplicated | 63 | /// import name, module name and export names. Each string will be deduplicated |
| 64 | /// and returns an offset into the table. | 64 | /// and returns an offset into the table. |
| 65 | string_table: Wasm.StringTable = .{}, | 65 | string_table: Wasm.StringTable = .{}, |
| | 66 | /// All the names of each debug section found in the current object file. |
| | 67 | /// Each name is terminated by a null-terminator. The name can be found, |
| | 68 | /// from the `index` offset within the `RelocatableData`. |
| | 69 | debug_names: [:0]const u8, |
| 66 | | 70 | |
| 67 | /// Represents a single item within a section (depending on its `type`) | 71 | /// Represents a single item within a section (depending on its `type`) |
| 68 | const RelocatableData = struct { | 72 | const RelocatableData = struct { |
| 69 | /// The type of the relocatable data | 73 | /// The type of the relocatable data |
| 70 | type: enum { data, code, custom }, | 74 | type: enum { data, code, debug }, |
| 71 | /// Pointer to the data of the segment, where its length is written to `size` | 75 | /// Pointer to the data of the segment, where its length is written to `size` |
| 72 | data: [*]u8, | 76 | data: [*]u8, |
| 73 | /// The size in bytes of the data representing the segment within the section | 77 | /// The size in bytes of the data representing the segment within the section |
| 74 | size: u32, | 78 | size: u32, |
| 75 | /// The index within the section itself | 79 | /// The index within the section itself, or in case of a debug section, |
| | 80 | /// the offset within the `debug_names` table. |
| 76 | index: u32, | 81 | index: u32, |
| 77 | /// The offset within the section where the data starts | 82 | /// The offset within the section where the data starts |
| 78 | offset: u32, | 83 | offset: u32, |
| ... | @@ -96,7 +101,7 @@ const RelocatableData = struct { | ... | @@ -96,7 +101,7 @@ const RelocatableData = struct { |
| 96 | return switch (self.type) { | 101 | return switch (self.type) { |
| 97 | .data => .data, | 102 | .data => .data, |
| 98 | .code => .function, | 103 | .code => .function, |
| 99 | .custom => .section, | 104 | .debug => unreachable, // illegal, debug sections are not represented by a symbol |
| 100 | }; | 105 | }; |
| 101 | } | 106 | } |
| 102 | }; | 107 | }; |
| ... | @@ -111,6 +116,7 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz | ... | @@ -111,6 +116,7 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz |
| 111 | var object: Object = .{ | 116 | var object: Object = .{ |
| 112 | .file = file, | 117 | .file = file, |
| 113 | .name = try gpa.dupe(u8, name), | 118 | .name = try gpa.dupe(u8, name), |
| | 119 | .debug_names = &.{}, |
| 114 | }; | 120 | }; |
| 115 | | 121 | |
| 116 | var is_object_file: bool = false; | 122 | var is_object_file: bool = false; |
| ... | @@ -197,6 +203,11 @@ pub fn importedCountByKind(self: *const Object, kind: std.wasm.ExternalKind) u32 | ... | @@ -197,6 +203,11 @@ pub fn importedCountByKind(self: *const Object, kind: std.wasm.ExternalKind) u32 |
| 197 | } else i; | 203 | } else i; |
| 198 | } | 204 | } |
| 199 | | 205 | |
| | 206 | /// From a given `RelocatableDate`, find the corresponding debug section name |
| | 207 | pub fn getDebugName(self: *const Object, relocatable_data: RelocatableData) []const u8 { |
| | 208 | return std.mem.sliceTo(self.debug_names[relocatable_data.index..], 0); |
| | 209 | } |
| | 210 | |
| 200 | /// Checks if the object file is an MVP version. | 211 | /// Checks if the object file is an MVP version. |
| 201 | /// When that's the case, we check if there's an import table definiton with its name | 212 | /// When that's the case, we check if there's an import table definiton with its name |
| 202 | /// set to '__indirect_function_table". When that's also the case, | 213 | /// set to '__indirect_function_table". When that's also the case, |
| ... | @@ -328,10 +339,15 @@ fn Parser(comptime ReaderType: type) type { | ... | @@ -328,10 +339,15 @@ fn Parser(comptime ReaderType: type) type { |
| 328 | | 339 | |
| 329 | self.object.version = version; | 340 | self.object.version = version; |
| 330 | var relocatable_data = std.ArrayList(RelocatableData).init(gpa); | 341 | var relocatable_data = std.ArrayList(RelocatableData).init(gpa); |
| 331 | | 342 | var debug_names = std.ArrayList(u8).init(gpa); |
| 332 | errdefer while (relocatable_data.popOrNull()) |rel_data| { | 343 | |
| 333 | gpa.free(rel_data.data[0..rel_data.size]); | 344 | errdefer { |
| 334 | } else relocatable_data.deinit(); | 345 | while (relocatable_data.popOrNull()) |rel_data| { |
| | 346 | gpa.free(rel_data.data[0..rel_data.size]); |
| | 347 | } else relocatable_data.deinit(); |
| | 348 | gpa.free(debug_names.items); |
| | 349 | debug_names.deinit(); |
| | 350 | } |
| 335 | | 351 | |
| 336 | var section_index: u32 = 0; | 352 | var section_index: u32 = 0; |
| 337 | while (self.reader.reader().readByte()) |byte| : (section_index += 1) { | 353 | while (self.reader.reader().readByte()) |byte| : (section_index += 1) { |
| ... | @@ -352,6 +368,24 @@ fn Parser(comptime ReaderType: type) type { | ... | @@ -352,6 +368,24 @@ fn Parser(comptime ReaderType: type) type { |
| 352 | try self.parseRelocations(gpa); | 368 | try self.parseRelocations(gpa); |
| 353 | } else if (std.mem.eql(u8, name, "target_features")) { | 369 | } else if (std.mem.eql(u8, name, "target_features")) { |
| 354 | try self.parseFeatures(gpa); | 370 | try self.parseFeatures(gpa); |
| | 371 | } else if (std.mem.startsWith(u8, name, ".debug")) { |
| | 372 | const debug_size = @intCast(u32, reader.context.bytes_left); |
| | 373 | const debug_content = try gpa.alloc(u8, debug_size); |
| | 374 | errdefer gpa.free(debug_content); |
| | 375 | try reader.readNoEof(debug_content); |
| | 376 | |
| | 377 | const debug_name_index = @intCast(u32, debug_names.items.len); |
| | 378 | try debug_names.ensureUnusedCapacity(name.len + 1); |
| | 379 | debug_names.appendSliceAssumeCapacity(try gpa.dupe(u8, name)); |
| | 380 | debug_names.appendAssumeCapacity(0); |
| | 381 | try relocatable_data.append(.{ |
| | 382 | .type = .debug, |
| | 383 | .data = debug_content.ptr, |
| | 384 | .size = debug_size, |
| | 385 | .index = debug_name_index, |
| | 386 | .offset = len - debug_size, |
| | 387 | .section_index = section_index, |
| | 388 | }); |
| 355 | } else { | 389 | } else { |
| 356 | try reader.skipBytes(reader.context.bytes_left, .{}); | 390 | try reader.skipBytes(reader.context.bytes_left, .{}); |
| 357 | } | 391 | } |
| ... | @@ -517,6 +551,9 @@ fn Parser(comptime ReaderType: type) type { | ... | @@ -517,6 +551,9 @@ fn Parser(comptime ReaderType: type) type { |
| 517 | else => |e| return e, | 551 | else => |e| return e, |
| 518 | } | 552 | } |
| 519 | self.object.relocatable_data = relocatable_data.toOwnedSlice(); | 553 | self.object.relocatable_data = relocatable_data.toOwnedSlice(); |
| | 554 | |
| | 555 | const names = debug_names.toOwnedSlice(); |
| | 556 | self.object.debug_names = names[0 .. names.len - 1 :0]; |
| 520 | } | 557 | } |
| 521 | | 558 | |
| 522 | /// Based on the "features" custom section, parses it into a list of | 559 | /// Based on the "features" custom section, parses it into a list of |