diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-11-05 12:08:15 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-11-05 12:08:15 +0100 |
| commit | 8d7ec05070ba5798adbeaf9a7153b6316fa6dcc3 (patch) | |
| tree | ec26ac5cd4ef5e9bdd13b0f426296ed7054f1035 /src | |
| parent | f24ceec35a6fd1e5e6a671461b78919b5f588a32 (diff) | |
| download | zig-8d7ec05070ba5798adbeaf9a7153b6316fa6dcc3.tar.gz zig-8d7ec05070ba5798adbeaf9a7153b6316fa6dcc3.zip | |
elf: actually save correct object names in the archive
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf/Archive.zig | 100 |
2 files changed, 60 insertions, 42 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ab986aeaf9..a3d2a28dbe 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1581,7 +1581,7 @@ pub fn flushStaticLib( // Update file offsets of contributing objects. const total_size: usize = blk: { - var pos: usize = Archive.SARMAG; + var pos: usize = Archive.ARMAG.len; pos += @sizeOf(Archive.ar_hdr) + ar_symtab.size(.p64); if (ar_strtab.size() > 0) { diff --git a/src/link/Elf/Archive.zig b/src/link/Elf/Archive.zig index 58a9e541a7..c106e2f1ec 100644 --- a/src/link/Elf/Archive.zig +++ b/src/link/Elf/Archive.zig @@ -8,7 +8,7 @@ pub fn isArchive(path: []const u8) !bool { const file = try std.fs.cwd().openFile(path, .{}); defer file.close(); const reader = file.reader(); - const magic = reader.readBytesNoEof(SARMAG) catch return false; + const magic = reader.readBytesNoEof(ARMAG.len) catch return false; if (!mem.eql(u8, &magic, ARMAG)) return false; return true; } @@ -24,14 +24,12 @@ pub fn parse(self: *Archive, elf_file: *Elf) !void { var stream = std.io.fixedBufferStream(self.data); const reader = stream.reader(); - _ = try reader.readBytesNoEof(SARMAG); + _ = try reader.readBytesNoEof(ARMAG.len); while (true) { if (stream.pos >= self.data.len) break; + if (!mem.isAligned(stream.pos, 2)) stream.pos += 1; - if (stream.pos % 2 != 0) { - stream.pos += 1; - } const hdr = try reader.readStruct(ar_hdr); if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) { @@ -48,28 +46,23 @@ pub fn parse(self: *Archive, elf_file: *Elf) !void { _ = stream.seekBy(size) catch {}; } - if (hdr.isSymtab()) continue; + if (hdr.isSymtab() or hdr.isSymtab64()) continue; if (hdr.isStrtab()) { self.strtab = self.data[stream.pos..][0..size]; continue; } + if (hdr.isSymdef() or hdr.isSymdefSorted()) continue; - const name = ar_hdr.getValue(&hdr.ar_name); - - if (mem.eql(u8, name, "__.SYMDEF") or mem.eql(u8, name, "__.SYMDEF SORTED")) continue; - - const object_name = blk: { - if (name[0] == '/') { - const off = try std.fmt.parseInt(u32, name[1..], 10); - const object_name = self.getString(off); - break :blk try gpa.dupe(u8, object_name[0 .. object_name.len - 1]); // To account for trailing '/' - } - break :blk try gpa.dupe(u8, name); - }; + const name = if (hdr.name()) |name| + try gpa.dupe(u8, name) + else if (try hdr.nameOffset()) |off| + try gpa.dupe(u8, self.getString(off)) + else + unreachable; const object = Object{ .archive = try gpa.dupe(u8, self.path), - .path = object_name, + .path = name, .data = try gpa.dupe(u8, self.data[stream.pos..][0..size]), .index = undefined, .alive = false, @@ -83,7 +76,8 @@ pub fn parse(self: *Archive, elf_file: *Elf) !void { fn getString(self: Archive, off: u32) []const u8 { assert(off < self.strtab.len); - return mem.sliceTo(@as([*:strtab_delimiter]const u8, @ptrCast(self.strtab.ptr + off)), 0); + const name = mem.sliceTo(@as([*:'\n']const u8, @ptrCast(self.strtab.ptr + off)), 0); + return name[0 .. name.len - 1]; } pub fn setArHdr(opts: struct { @@ -113,7 +107,7 @@ pub fn setArHdr(opts: struct { switch (opts.name) { .symtab => writer.print("{s}", .{Archive.SYM64NAME}) catch unreachable, .strtab => writer.print("//", .{}) catch unreachable, - .name => |x| writer.print("{s}", .{x}) catch unreachable, + .name => |x| writer.print("{s}/", .{x}) catch unreachable, .name_off => |x| writer.print("/{d}", .{x}) catch unreachable, } } @@ -125,25 +119,27 @@ pub fn setArHdr(opts: struct { return hdr; } +fn genSpecialMemberName(comptime name: []const u8) *const [16]u8 { + assert(name.len <= 16); + const padding = 16 - name.len; + return name ++ &[_]u8{0x20} ** padding; +} + // Archive files start with the ARMAG identifying string. Then follows a // `struct ar_hdr', and as many bytes of member file data as its `ar_size' // member indicates, for each member file. /// String that begins an archive file. -pub const ARMAG: *const [SARMAG:0]u8 = "!<arch>\n"; -/// Size of that string. -pub const SARMAG = 8; - +pub const ARMAG = "!<arch>\n"; /// String in ar_fmag at the end of each header. -const ARFMAG: *const [2:0]u8 = "`\n"; - -/// Strtab identifier -const STRNAME: *const [2:0]u8 = "//"; - +const ARFMAG = "`\n"; /// 32-bit symtab identifier -const SYMNAME: *const [1:0]u8 = "/"; - +const SYMNAME = genSpecialMemberName("/"); +/// Strtab identifier +const STRNAME = genSpecialMemberName("//"); /// 64-bit symtab identifier -const SYM64NAME: *const [7:0]u8 = "/SYM64/"; +const SYM64NAME = genSpecialMemberName("/SYM64/"); +const SYMDEFNAME = genSpecialMemberName("__.SYMDEF"); +const SYMDEFSORTEDNAME = genSpecialMemberName("__.SYMDEF SORTED"); const strtab_delimiter = '\n'; @@ -170,25 +166,47 @@ pub const ar_hdr = extern struct { ar_fmag: [2]u8, fn date(self: ar_hdr) !u64 { - const value = getValue(&self.ar_date); + const value = mem.trimRight(u8, &self.ar_date, &[_]u8{0x20}); return std.fmt.parseInt(u64, value, 10); } fn size(self: ar_hdr) !u32 { - const value = getValue(&self.ar_size); + const value = mem.trimRight(u8, &self.ar_size, &[_]u8{0x20}); return std.fmt.parseInt(u32, value, 10); } - fn getValue(raw: []const u8) []const u8 { - return mem.trimRight(u8, raw, &[_]u8{@as(u8, 0x20)}); - } - fn isStrtab(self: ar_hdr) bool { - return mem.eql(u8, getValue(&self.ar_name), STRNAME); + return mem.eql(u8, &self.ar_name, STRNAME); } fn isSymtab(self: ar_hdr) bool { - return mem.eql(u8, getValue(&self.ar_name), SYMNAME) or mem.eql(u8, getValue(&self.ar_name), SYM64NAME); + return mem.eql(u8, &self.ar_name, SYMNAME); + } + + fn isSymtab64(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, SYM64NAME); + } + + fn isSymdef(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, SYMDEFNAME); + } + + fn isSymdefSorted(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, SYMDEFSORTEDNAME); + } + + fn name(self: *const ar_hdr) ?[]const u8 { + const value = &self.ar_name; + if (value[0] == '/') return null; + const sentinel = mem.indexOfScalar(u8, value, '/') orelse value.len; + return value[0..sentinel]; + } + + fn nameOffset(self: ar_hdr) !?u32 { + const value = &self.ar_name; + if (value[0] != '/') return null; + const trimmed = mem.trimRight(u8, value, &[_]u8{0x20}); + return try std.fmt.parseInt(u32, trimmed[1..], 10); } }; |
