aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2024-04-19 00:10:43 +0200
committerJakub Konka <kubkon@jakubkonka.com>2024-04-20 23:36:42 +0200
commit2cc16239259a62502a5c67535de162e89fbfc4a9 (patch)
treea02feb93d2956f784fbf5f3c99caeeff3c9f65a6 /src
parent63a40bff47ce49a0cd27ef2adf99fa5e316fa8f9 (diff)
downloadzig-2cc16239259a62502a5c67535de162e89fbfc4a9.tar.gz
zig-2cc16239259a62502a5c67535de162e89fbfc4a9.zip
link/elf: fix parsing SHF_STRINGS section
Diffstat (limited to 'src')
-rw-r--r--src/link/Elf.zig6
-rw-r--r--src/link/Elf/Object.zig59
-rw-r--r--src/link/Elf/merge_section.zig12
-rw-r--r--src/link/Elf/relocatable.zig2
4 files changed, 36 insertions, 43 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index dd42de37df..1677daa64f 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1340,7 +1340,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)
};
try self.addCommentString();
- try self.sortMergeSections();
+ try self.finalizeMergeSections();
try self.initOutputSections();
try self.addLinkerDefinedSymbols();
self.claimUnresolved();
@@ -3369,9 +3369,9 @@ pub fn resolveMergeSections(self: *Elf) !void {
if (has_errors) return error.FlushFailure;
}
-pub fn sortMergeSections(self: *Elf) !void {
+pub fn finalizeMergeSections(self: *Elf) !void {
for (self.merge_sections.items) |*msec| {
- try msec.sort(self);
+ try msec.finalize(self);
}
}
diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig
index b652dc6790..f4aeb9b4c9 100644
--- a/src/link/Elf/Object.zig
+++ b/src/link/Elf/Object.zig
@@ -683,39 +683,40 @@ pub fn initMergeSections(self: *Object, elf_file: *Elf) !void {
const data = try self.codeDecompressAlloc(elf_file, atom_index);
defer gpa.free(data);
- const sh_entsize: u32 = @intCast(shdr.sh_entsize);
if (shdr.sh_flags & elf.SHF_STRINGS != 0) {
- var pos: u32 = 0;
- while (pos < data.len) switch (sh_entsize) {
- 0, 1 => {
- // According to mold's source code, GHC emits MS sections with sh_entsize = 0.
- // This actually can also happen for output created with `-r` mode.
- const string = mem.sliceTo(@as([*:0]const u8, @ptrCast(data.ptr + pos)), 0);
- if (pos + string.len == data.len) {
- var err = try elf_file.addErrorWithNotes(1);
- try err.addMsg(elf_file, "string not null terminated", .{});
- try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
- return error.MalformedObject;
- }
- try imsec.insertZ(gpa, string);
- try imsec.offsets.append(gpa, pos);
- pos += @as(u32, @intCast(string.len)) + 1; // account for null
- },
- else => |entsize| {
- const string = data.ptr[pos..][0..entsize];
- if (string[string.len - 1] != 0) {
- var err = try elf_file.addErrorWithNotes(1);
- try err.addMsg(elf_file, "string not null terminated", .{});
- try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
- return error.MalformedObject;
- }
- try imsec.insert(gpa, string);
- try imsec.offsets.append(gpa, pos);
- pos += @as(u32, @intCast(string.len));
- },
+ const sh_entsize: u32 = switch (shdr.sh_entsize) {
+ // According to mold's source code, GHC emits MS sections with sh_entsize = 0.
+ // This actually can also happen for output created with `-r` mode.
+ 0 => 1,
+ else => |x| @intCast(x),
};
+
+ const isNull = struct {
+ fn isNull(slice: []u8) bool {
+ for (slice) |x| if (x != 0) return false;
+ return true;
+ }
+ }.isNull;
+
+ var start: u32 = 0;
+ while (start < data.len) {
+ var end = start;
+ while (end < data.len - sh_entsize and !isNull(data[end .. end + sh_entsize])) : (end += sh_entsize) {}
+ if (!isNull(data[end .. end + sh_entsize])) {
+ var err = try elf_file.addErrorWithNotes(1);
+ try err.addMsg(elf_file, "string not null terminated", .{});
+ try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) });
+ return error.MalformedObject;
+ }
+ end += sh_entsize;
+ const string = data[start..end];
+ try imsec.insert(gpa, string);
+ try imsec.offsets.append(gpa, start);
+ start = end;
+ }
} else {
+ const sh_entsize: u32 = @intCast(shdr.sh_entsize);
if (sh_entsize == 0) continue; // Malformed, don't split but don't error out
if (shdr.sh_size % sh_entsize != 0) {
var err = try elf_file.addErrorWithNotes(1);
diff --git a/src/link/Elf/merge_section.zig b/src/link/Elf/merge_section.zig
index f3be74b3ad..50f4194f19 100644
--- a/src/link/Elf/merge_section.zig
+++ b/src/link/Elf/merge_section.zig
@@ -56,9 +56,9 @@ pub const MergeSection = struct {
return msec.insert(allocator, with_null);
}
+ /// Finalizes the merge section and clears hash table.
/// Sorts all owned subsections.
- /// Clears string table.
- pub fn sort(msec: *MergeSection, elf_file: *Elf) !void {
+ pub fn finalize(msec: *MergeSection, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa;
try msec.subsections.ensureTotalCapacityPrecise(gpa, msec.table.count());
@@ -270,14 +270,6 @@ pub const InputMergeSection = struct {
try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len) });
}
- pub fn insertZ(imsec: *InputMergeSection, allocator: Allocator, string: []const u8) !void {
- const index: u32 = @intCast(imsec.bytes.items.len);
- try imsec.bytes.ensureUnusedCapacity(allocator, string.len + 1);
- imsec.bytes.appendSliceAssumeCapacity(string);
- imsec.bytes.appendAssumeCapacity(0);
- try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len + 1) });
- }
-
pub const Index = u32;
};
diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig
index da15e4aa14..eb8569d252 100644
--- a/src/link/Elf/relocatable.zig
+++ b/src/link/Elf/relocatable.zig
@@ -181,7 +181,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const
elf_file.markEhFrameAtomsDead();
try elf_file.resolveMergeSections();
try elf_file.addCommentString();
- try elf_file.sortMergeSections();
+ try elf_file.finalizeMergeSections();
claimUnresolved(elf_file);
try initSections(elf_file);