diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-11-07 03:22:14 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-07 03:22:14 +0100 |
| commit | bf0387b6bb9c65c30f14e699a2f2cfbfea27184e (patch) | |
| tree | c0d68c1f225ed91cc900475958d1c125ae3239fb /lib/std/elf.zig | |
| parent | 234693bcbba6f55ff6e975ddbedf0fad4dfaa8f1 (diff) | |
| parent | 261db02018c71e8977d2bf2a78d495cc31abd1bc (diff) | |
| download | zig-bf0387b6bb9c65c30f14e699a2f2cfbfea27184e.tar.gz zig-bf0387b6bb9c65c30f14e699a2f2cfbfea27184e.zip | |
Merge pull request #17873 from ziglang/elf-archive
elf: implement archiving input object files
Diffstat (limited to 'lib/std/elf.zig')
| -rw-r--r-- | lib/std/elf.zig | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 7cb36a17ee..4c53898df8 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -1896,3 +1896,92 @@ pub const STV = enum(u2) { HIDDEN = 2, PROTECTED = 3, }; + +pub const ar_hdr = extern struct { + /// Member file name, sometimes / terminated. + ar_name: [16]u8, + + /// File date, decimal seconds since Epoch. + ar_date: [12]u8, + + /// User ID, in ASCII format. + ar_uid: [6]u8, + + /// Group ID, in ASCII format. + ar_gid: [6]u8, + + /// File mode, in ASCII octal. + ar_mode: [8]u8, + + /// File size, in ASCII decimal. + ar_size: [10]u8, + + /// Always contains ARFMAG. + ar_fmag: [2]u8, + + pub fn date(self: ar_hdr) std.fmt.ParseIntError!u64 { + const value = mem.trimRight(u8, &self.ar_date, &[_]u8{0x20}); + return std.fmt.parseInt(u64, value, 10); + } + + pub fn size(self: ar_hdr) std.fmt.ParseIntError!u32 { + const value = mem.trimRight(u8, &self.ar_size, &[_]u8{0x20}); + return std.fmt.parseInt(u32, value, 10); + } + + pub fn isStrtab(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, STRNAME); + } + + pub fn isSymtab(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, SYMNAME); + } + + pub fn isSymtab64(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, SYM64NAME); + } + + pub fn isSymdef(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, SYMDEFNAME); + } + + pub fn isSymdefSorted(self: ar_hdr) bool { + return mem.eql(u8, &self.ar_name, SYMDEFSORTEDNAME); + } + + pub 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]; + } + + pub fn nameOffset(self: ar_hdr) std.fmt.ParseIntError!?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); + } +}; + +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 = "!<arch>\n"; +/// String in ar_fmag at the end of each header. +pub const ARFMAG = "`\n"; +/// 32-bit symtab identifier +pub const SYMNAME = genSpecialMemberName("/"); +/// Strtab identifier +pub const STRNAME = genSpecialMemberName("//"); +/// 64-bit symtab identifier +pub const SYM64NAME = genSpecialMemberName("/SYM64/"); +pub const SYMDEFNAME = genSpecialMemberName("__.SYMDEF"); +pub const SYMDEFSORTEDNAME = genSpecialMemberName("__.SYMDEF SORTED"); |
