aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorTom Maenan Read Cutting <readcuttingt@gmail.com>2021-06-24 23:29:39 +0100
committerJakub Konka <kubkon@jakubkonka.com>2021-06-25 08:38:47 +0200
commit177b1b6bf9a7402eb688159dfa94ea5a5ea6f550 (patch)
tree2b14f44eb4fd81a0f3e0067190f71e09f8a2cffb /lib/std
parent2d2a6ed1a46349355650bfdd68688738c67bbf9c (diff)
downloadzig-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/std')
-rw-r--r--lib/std/elf.zig28
-rw-r--r--lib/std/macho.zig27
-rw-r--r--lib/std/mem.zig28
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 ", " ")