| author | |
| committer | |
| log | 2cc16239259a62502a5c67535de162e89fbfc4a9 |
| tree | a02feb93d2956f784fbf5f3c99caeeff3c9f65a6 |
| parent | 63a40bff47ce49a0cd27ef2adf99fa5e316fa8f9 |
4 files changed, 36 insertions(+), 43 deletions(-)
src/link/Elf.zig+3-3| ... | @@ -1340,7 +1340,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1340,7 +1340,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1340 | }; | 1340 | }; |
| 1341 | 1341 | ||
| 1342 | try self.addCommentString(); | 1342 | try self.addCommentString(); |
| 1343 | try self.sortMergeSections(); | 1343 | try self.finalizeMergeSections(); |
| 1344 | try self.initOutputSections(); | 1344 | try self.initOutputSections(); |
| 1345 | try self.addLinkerDefinedSymbols(); | 1345 | try self.addLinkerDefinedSymbols(); |
| 1346 | self.claimUnresolved(); | 1346 | self.claimUnresolved(); |
| ... | @@ -3369,9 +3369,9 @@ pub fn resolveMergeSections(self: *Elf) !void { | ... | @@ -3369,9 +3369,9 @@ pub fn resolveMergeSections(self: *Elf) !void { |
| 3369 | if (has_errors) return error.FlushFailure; | 3369 | if (has_errors) return error.FlushFailure; |
| 3370 | } | 3370 | } |
| 3371 | 3371 | ||
| 3372 | pub fn sortMergeSections(self: *Elf) !void { | 3372 | pub fn finalizeMergeSections(self: *Elf) !void { |
| 3373 | for (self.merge_sections.items) |*msec| { | 3373 | for (self.merge_sections.items) |*msec| { |
| 3374 | try msec.sort(self); | 3374 | try msec.finalize(self); |
| 3375 | } | 3375 | } |
| 3376 | } | 3376 | } |
| 3377 | 3377 |
src/link/Elf/Object.zig+30-29| ... | @@ -683,39 +683,40 @@ pub fn initMergeSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -683,39 +683,40 @@ pub fn initMergeSections(self: *Object, elf_file: *Elf) !void { |
| 683 | 683 | ||
| 684 | const data = try self.codeDecompressAlloc(elf_file, atom_index); | 684 | const data = try self.codeDecompressAlloc(elf_file, atom_index); |
| 685 | defer gpa.free(data); | 685 | defer gpa.free(data); |
| 686 | const sh_entsize: u32 = @intCast(shdr.sh_entsize); | ||
| 687 | 686 | ||
| 688 | if (shdr.sh_flags & elf.SHF_STRINGS != 0) { | 687 | if (shdr.sh_flags & elf.SHF_STRINGS != 0) { |
| 689 | var pos: u32 = 0; | 688 | const sh_entsize: u32 = switch (shdr.sh_entsize) { |
| 690 | while (pos < data.len) switch (sh_entsize) { | 689 | // According to mold's source code, GHC emits MS sections with sh_entsize = 0. |
| 691 | 0, 1 => { | 690 | // This actually can also happen for output created with `-r` mode. |
| 692 | // According to mold's source code, GHC emits MS sections with sh_entsize = 0. | 691 | 0 => 1, |
| 693 | // This actually can also happen for output created with `-r` mode. | 692 | else => |x| @intCast(x), |
| 694 | const string = mem.sliceTo(@as([*:0]const u8, @ptrCast(data.ptr + pos)), 0); | ||
| 695 | if (pos + string.len == data.len) { | ||
| 696 | var err = try elf_file.addErrorWithNotes(1); | ||
| 697 | try err.addMsg(elf_file, "string not null terminated", .{}); | ||
| 698 | try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | ||
| 699 | return error.MalformedObject; | ||
| 700 | } | ||
| 701 | try imsec.insertZ(gpa, string); | ||
| 702 | try imsec.offsets.append(gpa, pos); | ||
| 703 | pos += @as(u32, @intCast(string.len)) + 1; // account for null | ||
| 704 | }, | ||
| 705 | else => |entsize| { | ||
| 706 | const string = data.ptr[pos..][0..entsize]; | ||
| 707 | if (string[string.len - 1] != 0) { | ||
| 708 | var err = try elf_file.addErrorWithNotes(1); | ||
| 709 | try err.addMsg(elf_file, "string not null terminated", .{}); | ||
| 710 | try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | ||
| 711 | return error.MalformedObject; | ||
| 712 | } | ||
| 713 | try imsec.insert(gpa, string); | ||
| 714 | try imsec.offsets.append(gpa, pos); | ||
| 715 | pos += @as(u32, @intCast(string.len)); | ||
| 716 | }, | ||
| 717 | }; | 693 | }; |
| 694 | |||
| 695 | const isNull = struct { | ||
| 696 | fn isNull(slice: []u8) bool { | ||
| 697 | for (slice) |x| if (x != 0) return false; | ||
| 698 | return true; | ||
| 699 | } | ||
| 700 | }.isNull; | ||
| 701 | |||
| 702 | var start: u32 = 0; | ||
| 703 | while (start < data.len) { | ||
| 704 | var end = start; | ||
| 705 | while (end < data.len - sh_entsize and !isNull(data[end .. end + sh_entsize])) : (end += sh_entsize) {} | ||
| 706 | if (!isNull(data[end .. end + sh_entsize])) { | ||
| 707 | var err = try elf_file.addErrorWithNotes(1); | ||
| 708 | try err.addMsg(elf_file, "string not null terminated", .{}); | ||
| 709 | try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | ||
| 710 | return error.MalformedObject; | ||
| 711 | } | ||
| 712 | end += sh_entsize; | ||
| 713 | const string = data[start..end]; | ||
| 714 | try imsec.insert(gpa, string); | ||
| 715 | try imsec.offsets.append(gpa, start); | ||
| 716 | start = end; | ||
| 717 | } | ||
| 718 | } else { | 718 | } else { |
| 719 | const sh_entsize: u32 = @intCast(shdr.sh_entsize); | ||
| 719 | if (sh_entsize == 0) continue; // Malformed, don't split but don't error out | 720 | if (sh_entsize == 0) continue; // Malformed, don't split but don't error out |
| 720 | if (shdr.sh_size % sh_entsize != 0) { | 721 | if (shdr.sh_size % sh_entsize != 0) { |
| 721 | var err = try elf_file.addErrorWithNotes(1); | 722 | var err = try elf_file.addErrorWithNotes(1); |
src/link/Elf/merge_section.zig+2-10| ... | @@ -56,9 +56,9 @@ pub const MergeSection = struct { | ... | @@ -56,9 +56,9 @@ pub const MergeSection = struct { |
| 56 | return msec.insert(allocator, with_null); | 56 | return msec.insert(allocator, with_null); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | /// Finalizes the merge section and clears hash table. | ||
| 59 | /// Sorts all owned subsections. | 60 | /// Sorts all owned subsections. |
| 60 | /// Clears string table. | 61 | pub fn finalize(msec: *MergeSection, elf_file: *Elf) !void { |
| 61 | pub fn sort(msec: *MergeSection, elf_file: *Elf) !void { | ||
| 62 | const gpa = elf_file.base.comp.gpa; | 62 | const gpa = elf_file.base.comp.gpa; |
| 63 | try msec.subsections.ensureTotalCapacityPrecise(gpa, msec.table.count()); | 63 | try msec.subsections.ensureTotalCapacityPrecise(gpa, msec.table.count()); |
| 64 | 64 | ||
| ... | @@ -270,14 +270,6 @@ pub const InputMergeSection = struct { | ... | @@ -270,14 +270,6 @@ pub const InputMergeSection = struct { |
| 270 | try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len) }); | 270 | try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len) }); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | pub fn insertZ(imsec: *InputMergeSection, allocator: Allocator, string: []const u8) !void { | ||
| 274 | const index: u32 = @intCast(imsec.bytes.items.len); | ||
| 275 | try imsec.bytes.ensureUnusedCapacity(allocator, string.len + 1); | ||
| 276 | imsec.bytes.appendSliceAssumeCapacity(string); | ||
| 277 | imsec.bytes.appendAssumeCapacity(0); | ||
| 278 | try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len + 1) }); | ||
| 279 | } | ||
| 280 | |||
| 281 | pub const Index = u32; | 273 | pub const Index = u32; |
| 282 | }; | 274 | }; |
| 283 | 275 |
src/link/Elf/relocatable.zig+1-1| ... | @@ -181,7 +181,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -181,7 +181,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 181 | elf_file.markEhFrameAtomsDead(); | 181 | elf_file.markEhFrameAtomsDead(); |
| 182 | try elf_file.resolveMergeSections(); | 182 | try elf_file.resolveMergeSections(); |
| 183 | try elf_file.addCommentString(); | 183 | try elf_file.addCommentString(); |
| 184 | try elf_file.sortMergeSections(); | 184 | try elf_file.finalizeMergeSections(); |
| 185 | claimUnresolved(elf_file); | 185 | claimUnresolved(elf_file); |
| 186 | 186 | ||
| 187 | try initSections(elf_file); | 187 | try initSections(elf_file); |