authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-04-19 00:10:43+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-04-20 23:36:42+02:00
log2cc16239259a62502a5c67535de162e89fbfc4a9
treea02feb93d2956f784fbf5f3c99caeeff3c9f65a6
parent63a40bff47ce49a0cd27ef2adf99fa5e316fa8f9

link/elf: fix parsing SHF_STRINGS section


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 };
13411341
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}
33713371
3372pub fn sortMergeSections(self: *Elf) !void {3372pub 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}
33773377
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 {
683683
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);
687686
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 out720 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 }
5858
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());
6464
...@@ -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 }
272272
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};
283275
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);
186186
187 try initSections(elf_file);187 try initSections(elf_file);