diff options
| author | Tom Maenan Read Cutting <readcuttingt@gmail.com> | 2021-06-24 23:29:39 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-06-25 08:38:47 +0200 |
| commit | 177b1b6bf9a7402eb688159dfa94ea5a5ea6f550 (patch) | |
| tree | 2b14f44eb4fd81a0f3e0067190f71e09f8a2cffb /lib | |
| parent | 2d2a6ed1a46349355650bfdd68688738c67bbf9c (diff) | |
| download | zig-177b1b6bf9a7402eb688159dfa94ea5a5ea6f550.tar.gz zig-177b1b6bf9a7402eb688159dfa94ea5a5ea6f550.zip | |
Add fat/universal dylib support to zig ld
With this change zig ld can link with dynamic libraries
contained within a fat/universal file that had multiple
seperate binaries embedded within it for multi-arch
support (in macOS).
Whilst zig can still only create single-architecture
executables - the ability to link with fat libraries is
useful for cases where they are the easiest (or only)
option to link against.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/elf.zig | 28 | ||||
| -rw-r--r-- | lib/std/macho.zig | 27 | ||||
| -rw-r--r-- | lib/std/mem.zig | 28 |
3 files changed, 59 insertions, 24 deletions
diff --git a/lib/std/elf.zig b/lib/std/elf.zig index b74ea6e837..6c90dff929 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -429,7 +429,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type { if (self.elf_header.endian == native_endian) return phdr; // Convert fields to native endianness. - bswapAllFields(Elf64_Phdr, &phdr); + mem.bswapAllFields(Elf64_Phdr, &phdr); return phdr; } @@ -441,7 +441,7 @@ pub fn ProgramHeaderIterator(ParseSource: anytype) type { // ELF endianness does NOT match native endianness. if (self.elf_header.endian != native_endian) { // Convert fields to native endianness. - bswapAllFields(Elf32_Phdr, &phdr); + mem.bswapAllFields(Elf32_Phdr, &phdr); } // Convert 32-bit header to 64-bit. @@ -479,7 +479,7 @@ pub fn SectionHeaderIterator(ParseSource: anytype) type { if (self.elf_header.endian == native_endian) return shdr; // Convert fields to native endianness. - bswapAllFields(Elf64_Shdr, &shdr); + mem.bswapAllFields(Elf64_Shdr, &shdr); return shdr; } @@ -491,7 +491,7 @@ pub fn SectionHeaderIterator(ParseSource: anytype) type { // ELF endianness does NOT match native endianness. if (self.elf_header.endian != native_endian) { // Convert fields to native endianness. - bswapAllFields(Elf32_Shdr, &shdr); + mem.bswapAllFields(Elf32_Shdr, &shdr); } // Convert 32-bit header to 64-bit. @@ -531,26 +531,6 @@ pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 { } } -pub fn bswapAllFields(comptime S: type, ptr: *S) void { - if (@typeInfo(S) != .Struct) @compileError("bswapAllFields expects a struct as the first argument"); - inline for (std.meta.fields(S)) |f| { - @field(ptr, f.name) = @byteSwap(f.field_type, @field(ptr, f.name)); - } -} -test "bswapAllFields" { - var s: Elf32_Chdr = .{ - .ch_type = 0x12341234, - .ch_size = 0x56785678, - .ch_addralign = 0x12124242, - }; - bswapAllFields(Elf32_Chdr, &s); - try std.testing.expectEqual(Elf32_Chdr{ - .ch_type = 0x34123412, - .ch_size = 0x78567856, - .ch_addralign = 0x42421212, - }, s); -} - pub const EI_NIDENT = 16; pub const EI_CLASS = 4; diff --git a/lib/std/macho.zig b/lib/std/macho.zig index 20620b1fbf..cb030e941e 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -24,6 +24,19 @@ pub const mach_header_64 = extern struct { reserved: u32, }; +pub const fat_header = extern struct { + magic: u32, + nfat_arch: u32, +}; + +pub const fat_arch = extern struct { + cputype: cpu_type_t, + cpusubtype: cpu_subtype_t, + offset: u32, + size: u32, + @"align": u32, +}; + pub const load_command = extern struct { cmd: u32, cmdsize: u32, @@ -1040,6 +1053,20 @@ pub const MH_APP_EXTENSION_SAFE = 0x02000000; /// The external symbols listed in the nlist symbol table do not include all the symbols listed in the dyld info. pub const MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000; +// Constants for the flags field of the fat_header + +/// the fat magic number +pub const FAT_MAGIC = 0xcafebabe; + +/// NXSwapLong(FAT_MAGIC) +pub const FAT_CIGAM = 0xbebafeca; + +/// the 64-bit fat magic number +pub const FAT_MAGIC_64 = 0xcafebabf; + +/// NXSwapLong(FAT_MAGIC_64) +pub const FAT_CIGAM_64 = 0xbfbafeca; + /// The flags field of a section structure is separated into two parts a section /// type and section attributes. The section types are mutually exclusive (it /// can only have one type) but the section attributes are not (it may have more diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 2273db34cb..b7b9d92165 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1539,6 +1539,34 @@ test "writeIntBig and writeIntLittle" { try testing.expect(eql(u8, buf2[0..], &[_]u8{ 0xfc, 0xff })); } +/// Swap the byte order of all the members of the fields of a struct +/// (Changing their endianess) +pub fn bswapAllFields(comptime S: type, ptr: *S) void { + if (@typeInfo(S) != .Struct) @compileError("bswapAllFields expects a struct as the first argument"); + inline for (std.meta.fields(S)) |f| { + @field(ptr, f.name) = @byteSwap(f.field_type, @field(ptr, f.name)); + } +} + +test "bswapAllFields" { + const T = extern struct { + f0: u8, + f1: u16, + f2: u32, + }; + var s = T{ + .f0 = 0x12, + .f1 = 0x1234, + .f2 = 0x12345678, + }; + bswapAllFields(T, &s); + try std.testing.expectEqual(T{ + .f0 = 0x12, + .f1 = 0x3412, + .f2 = 0x78563412, + }, s); +} + /// Returns an iterator that iterates over the slices of `buffer` that are not /// any of the bytes in `delimiter_bytes`. /// tokenize(" abc def ghi ", " ") |
