authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-15 15:54:48+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-12-15 15:54:48+01:00
log87b843ef08426e1b14b2128987dfb52bb7de6788
tree463e9a1c77ad8cf0d9dce57ee4dbb47b9c62c0d8
parentff93486d0cbf032cbbf8b7953a072d448400ba2a
parentbd926e5ea0f9b27677a270a4e8253b6a6f77379c
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10338 from ziglang/macho-missing-feats

macho: refactor consts in std.macho, and fix two bugs in MachO linker backend

14 files changed, 409 insertions(+), 208 deletions(-)

lib/std/debug.zig+4-4
...@@ -843,7 +843,7 @@ fn readMachODebugInfo(allocator: mem.Allocator, macho_file: File) !ModuleDebugIn...@@ -843,7 +843,7 @@ fn readMachODebugInfo(allocator: mem.Allocator, macho_file: File) !ModuleDebugIn
843 const symtab = while (ncmd != 0) : (ncmd -= 1) {843 const symtab = while (ncmd != 0) : (ncmd -= 1) {
844 const lc = @ptrCast(*const std.macho.load_command, ptr);844 const lc = @ptrCast(*const std.macho.load_command, ptr);
845 switch (lc.cmd) {845 switch (lc.cmd) {
846 std.macho.LC_SYMTAB => break @ptrCast(*const std.macho.symtab_command, ptr),846 .SYMTAB => break @ptrCast(*const std.macho.symtab_command, ptr),
847 else => {},847 else => {},
848 }848 }
849 ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);849 ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
...@@ -1072,7 +1072,7 @@ pub const DebugInfo = struct {...@@ -1072,7 +1072,7 @@ pub const DebugInfo = struct {
1072 @alignCast(@alignOf(macho.load_command), cmd_ptr),1072 @alignCast(@alignOf(macho.load_command), cmd_ptr),
1073 );1073 );
1074 cmd_ptr += lc.cmdsize;1074 cmd_ptr += lc.cmdsize;
1075 if (lc.cmd != macho.LC_SEGMENT_64) continue;1075 if (lc.cmd != .SEGMENT_64) continue;
10761076
1077 const segment_cmd = @ptrCast(1077 const segment_cmd = @ptrCast(
1078 *const std.macho.segment_command_64,1078 *const std.macho.segment_command_64,
...@@ -1303,14 +1303,14 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1303,14 +1303,14 @@ pub const ModuleDebugInfo = switch (native_os) {
1303 while (ncmd != 0) : (ncmd -= 1) {1303 while (ncmd != 0) : (ncmd -= 1) {
1304 const lc = @ptrCast(*const std.macho.load_command, ptr);1304 const lc = @ptrCast(*const std.macho.load_command, ptr);
1305 switch (lc.cmd) {1305 switch (lc.cmd) {
1306 std.macho.LC_SEGMENT_64 => {1306 .SEGMENT_64 => {
1307 segcmd = @ptrCast(1307 segcmd = @ptrCast(
1308 *const std.macho.segment_command_64,1308 *const std.macho.segment_command_64,
1309 @alignCast(@alignOf(std.macho.segment_command_64), ptr),1309 @alignCast(@alignOf(std.macho.segment_command_64), ptr),
1310 );1310 );
1311 segptr = ptr;1311 segptr = ptr;
1312 },1312 },
1313 std.macho.LC_SYMTAB => {1313 .SYMTAB => {
1314 symtabcmd = @ptrCast(1314 symtabcmd = @ptrCast(
1315 *const std.macho.symtab_command,1315 *const std.macho.symtab_command,
1316 @alignCast(@alignOf(std.macho.symtab_command), ptr),1316 @alignCast(@alignOf(std.macho.symtab_command), ptr),
lib/std/macho.zig+162-152
...@@ -43,7 +43,7 @@ pub const fat_arch = extern struct {...@@ -43,7 +43,7 @@ pub const fat_arch = extern struct {
43};43};
4444
45pub const load_command = extern struct {45pub const load_command = extern struct {
46 cmd: u32,46 cmd: LC,
47 cmdsize: u32,47 cmdsize: u32,
48};48};
4949
...@@ -51,7 +51,7 @@ pub const load_command = extern struct {...@@ -51,7 +51,7 @@ pub const load_command = extern struct {
51/// identifies an object produced by the static link editor.51/// identifies an object produced by the static link editor.
52pub const uuid_command = extern struct {52pub const uuid_command = extern struct {
53 /// LC_UUID53 /// LC_UUID
54 cmd: u32,54 cmd: LC = .UUID,
5555
56 /// sizeof(struct uuid_command)56 /// sizeof(struct uuid_command)
57 cmdsize: u32,57 cmdsize: u32,
...@@ -64,7 +64,7 @@ pub const uuid_command = extern struct {...@@ -64,7 +64,7 @@ pub const uuid_command = extern struct {
64/// binary was built to run.64/// binary was built to run.
65pub const version_min_command = extern struct {65pub const version_min_command = extern struct {
66 /// LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_WATCHOS or LC_VERSION_MIN_TVOS66 /// LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_WATCHOS or LC_VERSION_MIN_TVOS
67 cmd: u32,67 cmd: LC,
6868
69 /// sizeof(struct version_min_command)69 /// sizeof(struct version_min_command)
70 cmdsize: u32,70 cmdsize: u32,
...@@ -80,7 +80,7 @@ pub const version_min_command = extern struct {...@@ -80,7 +80,7 @@ pub const version_min_command = extern struct {
80/// the version of the sources used to build the binary.80/// the version of the sources used to build the binary.
81pub const source_version_command = extern struct {81pub const source_version_command = extern struct {
82 /// LC_SOURCE_VERSION82 /// LC_SOURCE_VERSION
83 cmd: u32,83 cmd: LC = .SOURCE_VERSION,
8484
85 /// sizeof(source_version_command)85 /// sizeof(source_version_command)
86 cmdsize: u32,86 cmdsize: u32,
...@@ -94,14 +94,14 @@ pub const source_version_command = extern struct {...@@ -94,14 +94,14 @@ pub const source_version_command = extern struct {
94/// tool values following it.94/// tool values following it.
95pub const build_version_command = extern struct {95pub const build_version_command = extern struct {
96 /// LC_BUILD_VERSION96 /// LC_BUILD_VERSION
97 cmd: u32,97 cmd: LC = .BUILD_VERSION,
9898
99 /// sizeof(struct build_version_command) plus99 /// sizeof(struct build_version_command) plus
100 /// ntools * sizeof(struct build_version_command)100 /// ntools * sizeof(struct build_version_command)
101 cmdsize: u32,101 cmdsize: u32,
102102
103 /// platform103 /// platform
104 platform: u32,104 platform: PLATFORM,
105105
106 /// X.Y.Z is encoded in nibbles xxxx.yy.zz106 /// X.Y.Z is encoded in nibbles xxxx.yy.zz
107 minos: u32,107 minos: u32,
...@@ -115,26 +115,32 @@ pub const build_version_command = extern struct {...@@ -115,26 +115,32 @@ pub const build_version_command = extern struct {
115115
116pub const build_tool_version = extern struct {116pub const build_tool_version = extern struct {
117 /// enum for the tool117 /// enum for the tool
118 tool: u32,118 tool: TOOL,
119119
120 /// version number of the tool120 /// version number of the tool
121 version: u32,121 version: u32,
122};122};
123123
124pub const PLATFORM_MACOS: u32 = 0x1;124pub const PLATFORM = enum(u32) {
125pub const PLATFORM_IOS: u32 = 0x2;125 MACOS = 0x1,
126pub const PLATFORM_TVOS: u32 = 0x3;126 IOS = 0x2,
127pub const PLATFORM_WATCHOS: u32 = 0x4;127 TVOS = 0x3,
128pub const PLATFORM_BRIDGEOS: u32 = 0x5;128 WATCHOS = 0x4,
129pub const PLATFORM_MACCATALYST: u32 = 0x6;129 BRIDGEOS = 0x5,
130pub const PLATFORM_IOSSIMULATOR: u32 = 0x7;130 MACCATALYST = 0x6,
131pub const PLATFORM_TVOSSIMULATOR: u32 = 0x8;131 IOSSIMULATOR = 0x7,
132pub const PLATFORM_WATCHOSSIMULATOR: u32 = 0x9;132 TVOSSIMULATOR = 0x8,
133pub const PLATFORM_DRIVERKIT: u32 = 0x10;133 WATCHOSSIMULATOR = 0x9,
134134 DRIVERKIT = 0x10,
135pub const TOOL_CLANG: u32 = 0x1;135 _,
136pub const TOOL_SWIFT: u32 = 0x2;136};
137pub const TOOL_LD: u32 = 0x3;137
138pub const TOOL = enum(u32) {
139 CLANG = 0x1,
140 SWIFT = 0x2,
141 LD = 0x3,
142 _,
143};
138144
139/// The entry_point_command is a replacement for thread_command.145/// The entry_point_command is a replacement for thread_command.
140/// It is used for main executables to specify the location (file offset)146/// It is used for main executables to specify the location (file offset)
...@@ -142,7 +148,7 @@ pub const TOOL_LD: u32 = 0x3;...@@ -142,7 +148,7 @@ pub const TOOL_LD: u32 = 0x3;
142/// field will contain the stack size needed for the main thread.148/// field will contain the stack size needed for the main thread.
143pub const entry_point_command = extern struct {149pub const entry_point_command = extern struct {
144 /// LC_MAIN only used in MH_EXECUTE filetypes150 /// LC_MAIN only used in MH_EXECUTE filetypes
145 cmd: u32,151 cmd: LC = .MAIN,
146152
147 /// sizeof(struct entry_point_command)153 /// sizeof(struct entry_point_command)
148 cmdsize: u32,154 cmdsize: u32,
...@@ -159,7 +165,7 @@ pub const entry_point_command = extern struct {...@@ -159,7 +165,7 @@ pub const entry_point_command = extern struct {
159/// <nlist.h> and <stab.h>.165/// <nlist.h> and <stab.h>.
160pub const symtab_command = extern struct {166pub const symtab_command = extern struct {
161 /// LC_SYMTAB167 /// LC_SYMTAB
162 cmd: u32,168 cmd: LC = .SYMTAB,
163169
164 /// sizeof(struct symtab_command)170 /// sizeof(struct symtab_command)
165 cmdsize: u32,171 cmdsize: u32,
...@@ -217,7 +223,7 @@ pub const symtab_command = extern struct {...@@ -217,7 +223,7 @@ pub const symtab_command = extern struct {
217/// off the section structures.223/// off the section structures.
218pub const dysymtab_command = extern struct {224pub const dysymtab_command = extern struct {
219 /// LC_DYSYMTAB225 /// LC_DYSYMTAB
220 cmd: u32,226 cmd: LC = .DYSYMTAB,
221227
222 /// sizeof(struct dysymtab_command)228 /// sizeof(struct dysymtab_command)
223 cmdsize: u32,229 cmdsize: u32,
...@@ -357,7 +363,7 @@ pub const dysymtab_command = extern struct {...@@ -357,7 +363,7 @@ pub const dysymtab_command = extern struct {
357/// of data in the __LINKEDIT segment.363/// of data in the __LINKEDIT segment.
358pub const linkedit_data_command = extern struct {364pub const linkedit_data_command = extern struct {
359 /// LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS or LC_LINKER_OPTIMIZATION_HINT.365 /// LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS or LC_LINKER_OPTIMIZATION_HINT.
360 cmd: u32,366 cmd: LC,
361367
362 /// sizeof(struct linkedit_data_command)368 /// sizeof(struct linkedit_data_command)
363 cmdsize: u32,369 cmdsize: u32,
...@@ -377,7 +383,7 @@ pub const linkedit_data_command = extern struct {...@@ -377,7 +383,7 @@ pub const linkedit_data_command = extern struct {
377/// to interpret it.383/// to interpret it.
378pub const dyld_info_command = extern struct {384pub const dyld_info_command = extern struct {
379 /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY385 /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY
380 cmd: u32,386 cmd: LC,
381387
382 /// sizeof(struct dyld_info_command)388 /// sizeof(struct dyld_info_command)
383 cmdsize: u32,389 cmdsize: u32,
...@@ -498,7 +504,7 @@ pub const dyld_info_command = extern struct {...@@ -498,7 +504,7 @@ pub const dyld_info_command = extern struct {
498/// string for dyld to treat like an environment variable.504/// string for dyld to treat like an environment variable.
499pub const dylinker_command = extern struct {505pub const dylinker_command = extern struct {
500 /// LC_ID_DYLINKER, LC_LOAD_DYLINKER, or LC_DYLD_ENVIRONMENT506 /// LC_ID_DYLINKER, LC_LOAD_DYLINKER, or LC_DYLD_ENVIRONMENT
501 cmd: u32,507 cmd: LC,
502508
503 /// includes pathname string509 /// includes pathname string
504 cmdsize: u32,510 cmdsize: u32,
...@@ -519,7 +525,7 @@ pub const dylinker_command = extern struct {...@@ -519,7 +525,7 @@ pub const dylinker_command = extern struct {
519/// LC_REEXPORT_DYLIB) for each library it uses.525/// LC_REEXPORT_DYLIB) for each library it uses.
520pub const dylib_command = extern struct {526pub const dylib_command = extern struct {
521 /// LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_LOAD_DYLIB, LC_REEXPORT_DYLIB527 /// LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_LOAD_DYLIB, LC_REEXPORT_DYLIB
522 cmd: u32,528 cmd: LC,
523529
524 /// includes pathname string530 /// includes pathname string
525 cmdsize: u32,531 cmdsize: u32,
...@@ -553,7 +559,7 @@ pub const dylib = extern struct {...@@ -553,7 +559,7 @@ pub const dylib = extern struct {
553/// run path used to find @rpath prefixed dylibs.559/// run path used to find @rpath prefixed dylibs.
554pub const rpath_command = extern struct {560pub const rpath_command = extern struct {
555 /// LC_RPATH561 /// LC_RPATH
556 cmd: u32,562 cmd: LC = .RPATH,
557563
558 /// includes string564 /// includes string
559 cmdsize: u32,565 cmdsize: u32,
...@@ -574,7 +580,7 @@ pub const rpath_command = extern struct {...@@ -574,7 +580,7 @@ pub const rpath_command = extern struct {
574/// reflected in cmdsize.580/// reflected in cmdsize.
575pub const segment_command = extern struct {581pub const segment_command = extern struct {
576 /// LC_SEGMENT582 /// LC_SEGMENT
577 cmd: u32,583 cmd: LC = .SEGMENT,
578584
579 /// includes sizeof section structs585 /// includes sizeof section structs
580 cmdsize: u32,586 cmdsize: u32,
...@@ -611,7 +617,7 @@ pub const segment_command = extern struct {...@@ -611,7 +617,7 @@ pub const segment_command = extern struct {
611/// command and their size is reflected in cmdsize.617/// command and their size is reflected in cmdsize.
612pub const segment_command_64 = extern struct {618pub const segment_command_64 = extern struct {
613 /// LC_SEGMENT_64619 /// LC_SEGMENT_64
614 cmd: u32 = LC_SEGMENT_64,620 cmd: LC = .SEGMENT_64,
615621
616 /// includes sizeof section_64 structs622 /// includes sizeof section_64 structs
617 cmdsize: u32 = @sizeOf(segment_command_64),623 cmdsize: u32 = @sizeOf(segment_command_64),
...@@ -882,159 +888,163 @@ pub const relocation_info = packed struct {...@@ -882,159 +888,163 @@ pub const relocation_info = packed struct {
882/// simply be ignored.888/// simply be ignored.
883pub const LC_REQ_DYLD = 0x80000000;889pub const LC_REQ_DYLD = 0x80000000;
884890
885/// segment of this file to be mapped891pub const LC = enum(u32) {
886pub const LC_SEGMENT = 0x1;892 /// segment of this file to be mapped
893 SEGMENT = 0x1,
887894
888/// link-edit stab symbol table info895 /// link-edit stab symbol table info
889pub const LC_SYMTAB = 0x2;896 SYMTAB = 0x2,
890897
891/// link-edit gdb symbol table info (obsolete)898 /// link-edit gdb symbol table info (obsolete)
892pub const LC_SYMSEG = 0x3;899 SYMSEG = 0x3,
893900
894/// thread901 /// thread
895pub const LC_THREAD = 0x4;902 THREAD = 0x4,
896903
897/// unix thread (includes a stack)904 /// unix thread (includes a stack)
898pub const LC_UNIXTHREAD = 0x5;905 UNIXTHREAD = 0x5,
899906
900/// load a specified fixed VM shared library907 /// load a specified fixed VM shared library
901pub const LC_LOADFVMLIB = 0x6;908 LOADFVMLIB = 0x6,
902909
903/// fixed VM shared library identification910 /// fixed VM shared library identification
904pub const LC_IDFVMLIB = 0x7;911 IDFVMLIB = 0x7,
905912
906/// object identification info (obsolete)913 /// object identification info (obsolete)
907pub const LC_IDENT = 0x8;914 IDENT = 0x8,
908915
909/// fixed VM file inclusion (internal use)916 /// fixed VM file inclusion (internal use)
910pub const LC_FVMFILE = 0x9;917 FVMFILE = 0x9,
911918
912/// prepage command (internal use)919 /// prepage command (internal use)
913pub const LC_PREPAGE = 0xa;920 PREPAGE = 0xa,
914921
915/// dynamic link-edit symbol table info922 /// dynamic link-edit symbol table info
916pub const LC_DYSYMTAB = 0xb;923 DYSYMTAB = 0xb,
917924
918/// load a dynamically linked shared library925 /// load a dynamically linked shared library
919pub const LC_LOAD_DYLIB = 0xc;926 LOAD_DYLIB = 0xc,
920927
921/// dynamically linked shared lib ident928 /// dynamically linked shared lib ident
922pub const LC_ID_DYLIB = 0xd;929 ID_DYLIB = 0xd,
923930
924/// load a dynamic linker931 /// load a dynamic linker
925pub const LC_LOAD_DYLINKER = 0xe;932 LOAD_DYLINKER = 0xe,
926933
927/// dynamic linker identification934 /// dynamic linker identification
928pub const LC_ID_DYLINKER = 0xf;935 ID_DYLINKER = 0xf,
929936
930/// modules prebound for a dynamically937 /// modules prebound for a dynamically
931pub const LC_PREBOUND_DYLIB = 0x10;938 PREBOUND_DYLIB = 0x10,
932939
933/// image routines940 /// image routines
934pub const LC_ROUTINES = 0x11;941 ROUTINES = 0x11,
935942
936/// sub framework943 /// sub framework
937pub const LC_SUB_FRAMEWORK = 0x12;944 SUB_FRAMEWORK = 0x12,
938945
939/// sub umbrella946 /// sub umbrella
940pub const LC_SUB_UMBRELLA = 0x13;947 SUB_UMBRELLA = 0x13,
941948
942/// sub client949 /// sub client
943pub const LC_SUB_CLIENT = 0x14;950 SUB_CLIENT = 0x14,
944951
945/// sub library952 /// sub library
946pub const LC_SUB_LIBRARY = 0x15;953 SUB_LIBRARY = 0x15,
947954
948/// two-level namespace lookup hints955 /// two-level namespace lookup hints
949pub const LC_TWOLEVEL_HINTS = 0x16;956 TWOLEVEL_HINTS = 0x16,
950957
951/// prebind checksum958 /// prebind checksum
952pub const LC_PREBIND_CKSUM = 0x17;959 PREBIND_CKSUM = 0x17,
953960
954/// load a dynamically linked shared library that is allowed to be missing961 /// load a dynamically linked shared library that is allowed to be missing
955/// (all symbols are weak imported).962 /// (all symbols are weak imported).
956pub const LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD);963 LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD),
957964
958/// 64-bit segment of this file to be mapped965 /// 64-bit segment of this file to be mapped
959pub const LC_SEGMENT_64 = 0x19;966 SEGMENT_64 = 0x19,
960967
961/// 64-bit image routines968 /// 64-bit image routines
962pub const LC_ROUTINES_64 = 0x1a;969 ROUTINES_64 = 0x1a,
963970
964/// the uuid971 /// the uuid
965pub const LC_UUID = 0x1b;972 UUID = 0x1b,
966973
967/// runpath additions974 /// runpath additions
968pub const LC_RPATH = (0x1c | LC_REQ_DYLD);975 RPATH = (0x1c | LC_REQ_DYLD),
969976
970/// local of code signature977 /// local of code signature
971pub const LC_CODE_SIGNATURE = 0x1d;978 CODE_SIGNATURE = 0x1d,
972979
973/// local of info to split segments980 /// local of info to split segments
974pub const LC_SEGMENT_SPLIT_INFO = 0x1e;981 SEGMENT_SPLIT_INFO = 0x1e,
975982
976/// load and re-export dylib983 /// load and re-export dylib
977pub const LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD);984 REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD),
978985
979/// delay load of dylib until first use986 /// delay load of dylib until first use
980pub const LC_LAZY_LOAD_DYLIB = 0x20;987 LAZY_LOAD_DYLIB = 0x20,
981988
982/// encrypted segment information989 /// encrypted segment information
983pub const LC_ENCRYPTION_INFO = 0x21;990 ENCRYPTION_INFO = 0x21,
984991
985/// compressed dyld information992 /// compressed dyld information
986pub const LC_DYLD_INFO = 0x22;993 DYLD_INFO = 0x22,
987994
988/// compressed dyld information only995 /// compressed dyld information only
989pub const LC_DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD);996 DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD),
990997
991/// load upward dylib998 /// load upward dylib
992pub const LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD);999 LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD),
9931000
994/// build for MacOSX min OS version1001 /// build for MacOSX min OS version
995pub const LC_VERSION_MIN_MACOSX = 0x24;1002 VERSION_MIN_MACOSX = 0x24,
9961003
997/// build for iPhoneOS min OS version1004 /// build for iPhoneOS min OS version
998pub const LC_VERSION_MIN_IPHONEOS = 0x25;1005 VERSION_MIN_IPHONEOS = 0x25,
9991006
1000/// compressed table of function start addresses1007 /// compressed table of function start addresses
1001pub const LC_FUNCTION_STARTS = 0x26;1008 FUNCTION_STARTS = 0x26,
10021009
1003/// string for dyld to treat like environment variable1010 /// string for dyld to treat like environment variable
1004pub const LC_DYLD_ENVIRONMENT = 0x27;1011 DYLD_ENVIRONMENT = 0x27,
10051012
1006/// replacement for LC_UNIXTHREAD1013 /// replacement for LC_UNIXTHREAD
1007pub const LC_MAIN = (0x28 | LC_REQ_DYLD);1014 MAIN = (0x28 | LC_REQ_DYLD),
10081015
1009/// table of non-instructions in __text1016 /// table of non-instructions in __text
1010pub const LC_DATA_IN_CODE = 0x29;1017 DATA_IN_CODE = 0x29,
10111018
1012/// source version used to build binary1019 /// source version used to build binary
1013pub const LC_SOURCE_VERSION = 0x2A;1020 SOURCE_VERSION = 0x2A,
10141021
1015/// Code signing DRs copied from linked dylibs1022 /// Code signing DRs copied from linked dylibs
1016pub const LC_DYLIB_CODE_SIGN_DRS = 0x2B;1023 DYLIB_CODE_SIGN_DRS = 0x2B,
10171024
1018/// 64-bit encrypted segment information1025 /// 64-bit encrypted segment information
1019pub const LC_ENCRYPTION_INFO_64 = 0x2C;1026 ENCRYPTION_INFO_64 = 0x2C,
10201027
1021/// linker options in MH_OBJECT files1028 /// linker options in MH_OBJECT files
1022pub const LC_LINKER_OPTION = 0x2D;1029 LINKER_OPTION = 0x2D,
10231030
1024/// optimization hints in MH_OBJECT files1031 /// optimization hints in MH_OBJECT files
1025pub const LC_LINKER_OPTIMIZATION_HINT = 0x2E;1032 LINKER_OPTIMIZATION_HINT = 0x2E,
10261033
1027/// build for AppleTV min OS version1034 /// build for AppleTV min OS version
1028pub const LC_VERSION_MIN_TVOS = 0x2F;1035 VERSION_MIN_TVOS = 0x2F,
10291036
1030/// build for Watch min OS version1037 /// build for Watch min OS version
1031pub const LC_VERSION_MIN_WATCHOS = 0x30;1038 VERSION_MIN_WATCHOS = 0x30,
10321039
1033/// arbitrary data included within a Mach-O file1040 /// arbitrary data included within a Mach-O file
1034pub const LC_NOTE = 0x31;1041 NOTE = 0x31,
10351042
1036/// build for platform min OS version1043 /// build for platform min OS version
1037pub const LC_BUILD_VERSION = 0x32;1044 BUILD_VERSION = 0x32,
1045
1046 _,
1047};
10381048
1039/// the mach magic number1049/// the mach magic number
1040pub const MH_MAGIC = 0xfeedface;1050pub const MH_MAGIC = 0xfeedface;
...@@ -1537,7 +1547,7 @@ pub const reloc_type_x86_64 = enum(u4) {...@@ -1537,7 +1547,7 @@ pub const reloc_type_x86_64 = enum(u4) {
15371547
1538pub const reloc_type_arm64 = enum(u4) {1548pub const reloc_type_arm64 = enum(u4) {
1539 /// For pointers.1549 /// For pointers.
1540 ARM64_RELOC_UNSIGNED,1550 ARM64_RELOC_UNSIGNED = 0,
15411551
1542 /// Must be followed by a ARM64_RELOC_UNSIGNED.1552 /// Must be followed by a ARM64_RELOC_UNSIGNED.
1543 ARM64_RELOC_SUBTRACTOR,1553 ARM64_RELOC_SUBTRACTOR,
...@@ -1840,43 +1850,43 @@ pub const LoadCommand = union(enum) {...@@ -1840,43 +1850,43 @@ pub const LoadCommand = union(enum) {
1840 var stream = io.fixedBufferStream(buffer);1850 var stream = io.fixedBufferStream(buffer);
18411851
1842 return switch (header.cmd) {1852 return switch (header.cmd) {
1843 LC_SEGMENT_64 => LoadCommand{1853 .SEGMENT_64 => LoadCommand{
1844 .segment = try SegmentCommand.read(allocator, stream.reader()),1854 .segment = try SegmentCommand.read(allocator, stream.reader()),
1845 },1855 },
1846 LC_DYLD_INFO, LC_DYLD_INFO_ONLY => LoadCommand{1856 .DYLD_INFO, .DYLD_INFO_ONLY => LoadCommand{
1847 .dyld_info_only = try stream.reader().readStruct(dyld_info_command),1857 .dyld_info_only = try stream.reader().readStruct(dyld_info_command),
1848 },1858 },
1849 LC_SYMTAB => LoadCommand{1859 .SYMTAB => LoadCommand{
1850 .symtab = try stream.reader().readStruct(symtab_command),1860 .symtab = try stream.reader().readStruct(symtab_command),
1851 },1861 },
1852 LC_DYSYMTAB => LoadCommand{1862 .DYSYMTAB => LoadCommand{
1853 .dysymtab = try stream.reader().readStruct(dysymtab_command),1863 .dysymtab = try stream.reader().readStruct(dysymtab_command),
1854 },1864 },
1855 LC_ID_DYLINKER, LC_LOAD_DYLINKER, LC_DYLD_ENVIRONMENT => LoadCommand{1865 .ID_DYLINKER, .LOAD_DYLINKER, .DYLD_ENVIRONMENT => LoadCommand{
1856 .dylinker = try GenericCommandWithData(dylinker_command).read(allocator, stream.reader()),1866 .dylinker = try GenericCommandWithData(dylinker_command).read(allocator, stream.reader()),
1857 },1867 },
1858 LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_LOAD_DYLIB, LC_REEXPORT_DYLIB => LoadCommand{1868 .ID_DYLIB, .LOAD_WEAK_DYLIB, .LOAD_DYLIB, .REEXPORT_DYLIB => LoadCommand{
1859 .dylib = try GenericCommandWithData(dylib_command).read(allocator, stream.reader()),1869 .dylib = try GenericCommandWithData(dylib_command).read(allocator, stream.reader()),
1860 },1870 },
1861 LC_MAIN => LoadCommand{1871 .MAIN => LoadCommand{
1862 .main = try stream.reader().readStruct(entry_point_command),1872 .main = try stream.reader().readStruct(entry_point_command),
1863 },1873 },
1864 LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS => LoadCommand{1874 .VERSION_MIN_MACOSX, .VERSION_MIN_IPHONEOS, .VERSION_MIN_WATCHOS, .VERSION_MIN_TVOS => LoadCommand{
1865 .version_min = try stream.reader().readStruct(version_min_command),1875 .version_min = try stream.reader().readStruct(version_min_command),
1866 },1876 },
1867 LC_SOURCE_VERSION => LoadCommand{1877 .SOURCE_VERSION => LoadCommand{
1868 .source_version = try stream.reader().readStruct(source_version_command),1878 .source_version = try stream.reader().readStruct(source_version_command),
1869 },1879 },
1870 LC_BUILD_VERSION => LoadCommand{1880 .BUILD_VERSION => LoadCommand{
1871 .build_version = try GenericCommandWithData(build_version_command).read(allocator, stream.reader()),1881 .build_version = try GenericCommandWithData(build_version_command).read(allocator, stream.reader()),
1872 },1882 },
1873 LC_UUID => LoadCommand{1883 .UUID => LoadCommand{
1874 .uuid = try stream.reader().readStruct(uuid_command),1884 .uuid = try stream.reader().readStruct(uuid_command),
1875 },1885 },
1876 LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_CODE_SIGNATURE => LoadCommand{1886 .FUNCTION_STARTS, .DATA_IN_CODE, .CODE_SIGNATURE => LoadCommand{
1877 .linkedit_data = try stream.reader().readStruct(linkedit_data_command),1887 .linkedit_data = try stream.reader().readStruct(linkedit_data_command),
1878 },1888 },
1879 LC_RPATH => LoadCommand{1889 .RPATH => LoadCommand{
1880 .rpath = try GenericCommandWithData(rpath_command).read(allocator, stream.reader()),1890 .rpath = try GenericCommandWithData(rpath_command).read(allocator, stream.reader()),
1881 },1891 },
1882 else => LoadCommand{1892 else => LoadCommand{
...@@ -1904,7 +1914,7 @@ pub const LoadCommand = union(enum) {...@@ -1904,7 +1914,7 @@ pub const LoadCommand = union(enum) {
1904 };1914 };
1905 }1915 }
19061916
1907 pub fn cmd(self: LoadCommand) u32 {1917 pub fn cmd(self: LoadCommand) LC {
1908 return switch (self) {1918 return switch (self) {
1909 .dyld_info_only => |x| x.cmd,1919 .dyld_info_only => |x| x.cmd,
1910 .symtab => |x| x.cmd,1920 .symtab => |x| x.cmd,
...@@ -2078,7 +2088,7 @@ pub fn createLoadDylibCommand(...@@ -2078,7 +2088,7 @@ pub fn createLoadDylibCommand(
2078 ));2088 ));
20792089
2080 var dylib_cmd = emptyGenericCommandWithData(dylib_command{2090 var dylib_cmd = emptyGenericCommandWithData(dylib_command{
2081 .cmd = LC_LOAD_DYLIB,2091 .cmd = .LOAD_DYLIB,
2082 .cmdsize = cmdsize,2092 .cmdsize = cmdsize,
2083 .dylib = .{2093 .dylib = .{
2084 .name = @sizeOf(dylib_command),2094 .name = @sizeOf(dylib_command),
...@@ -2189,7 +2199,7 @@ test "read-write generic command with data" {...@@ -2189,7 +2199,7 @@ test "read-write generic command with data" {
2189 };2199 };
2190 var cmd = GenericCommandWithData(dylib_command){2200 var cmd = GenericCommandWithData(dylib_command){
2191 .inner = .{2201 .inner = .{
2192 .cmd = LC_LOAD_DYLIB,2202 .cmd = .LOAD_DYLIB,
2193 .cmdsize = 32,2203 .cmdsize = 32,
2194 .dylib = .{2204 .dylib = .{
2195 .name = 24,2205 .name = 24,
...@@ -2227,7 +2237,7 @@ test "read-write C struct command" {...@@ -2227,7 +2237,7 @@ test "read-write C struct command" {
2227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // stacksize2237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // stacksize
2228 };2238 };
2229 const cmd = .{2239 const cmd = .{
2230 .cmd = LC_MAIN,2240 .cmd = .MAIN,
2231 .cmdsize = 24,2241 .cmdsize = 24,
2232 .entryoff = 16644,2242 .entryoff = 16644,
2233 .stacksize = 0,2243 .stacksize = 0,
src/link/MachO.zig+95-33
...@@ -130,6 +130,7 @@ objc_imageinfo_section_index: ?u16 = null,...@@ -130,6 +130,7 @@ objc_imageinfo_section_index: ?u16 = null,
130tlv_section_index: ?u16 = null,130tlv_section_index: ?u16 = null,
131tlv_data_section_index: ?u16 = null,131tlv_data_section_index: ?u16 = null,
132tlv_bss_section_index: ?u16 = null,132tlv_bss_section_index: ?u16 = null,
133tlv_ptrs_section_index: ?u16 = null,
133la_symbol_ptr_section_index: ?u16 = null,134la_symbol_ptr_section_index: ?u16 = null,
134data_section_index: ?u16 = null,135data_section_index: ?u16 = null,
135bss_section_index: ?u16 = null,136bss_section_index: ?u16 = null,
...@@ -164,6 +165,9 @@ stub_helper_preamble_atom: ?*Atom = null,...@@ -164,6 +165,9 @@ stub_helper_preamble_atom: ?*Atom = null,
164strtab: std.ArrayListUnmanaged(u8) = .{},165strtab: std.ArrayListUnmanaged(u8) = .{},
165strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},166strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},
166167
168tlv_ptr_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{},
169tlv_ptr_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{},
170
167got_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{},171got_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{},
168got_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{},172got_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{},
169173
...@@ -783,7 +787,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -783,7 +787,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
783 @sizeOf(u64),787 @sizeOf(u64),
784 ));788 ));
785 var rpath_cmd = macho.emptyGenericCommandWithData(macho.rpath_command{789 var rpath_cmd = macho.emptyGenericCommandWithData(macho.rpath_command{
786 .cmd = macho.LC_RPATH,
787 .cmdsize = cmdsize,790 .cmdsize = cmdsize,
788 .path = @sizeOf(macho.rpath_command),791 .path = @sizeOf(macho.rpath_command),
789 });792 });
...@@ -1526,6 +1529,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1526,6 +1529,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1526 .sect = self.tlv_section_index.?,1529 .sect = self.tlv_section_index.?,
1527 };1530 };
1528 },1531 },
1532 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => {
1533 if (self.tlv_ptrs_section_index == null) {
1534 self.tlv_ptrs_section_index = try self.initSection(
1535 self.data_segment_cmd_index.?,
1536 "__thread_ptrs",
1537 sect.size,
1538 sect.@"align",
1539 .{
1540 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
1541 },
1542 );
1543 }
1544
1545 break :blk .{
1546 .seg = self.data_segment_cmd_index.?,
1547 .sect = self.tlv_ptrs_section_index.?,
1548 };
1549 },
1529 macho.S_THREAD_LOCAL_REGULAR => {1550 macho.S_THREAD_LOCAL_REGULAR => {
1530 if (self.tlv_data_section_index == null) {1551 if (self.tlv_data_section_index == null) {
1531 self.tlv_data_section_index = try self.initSection(1552 self.tlv_data_section_index = try self.initSection(
...@@ -2143,6 +2164,24 @@ pub fn createGotAtom(self: *MachO, target: Atom.Relocation.Target) !*Atom {...@@ -2143,6 +2164,24 @@ pub fn createGotAtom(self: *MachO, target: Atom.Relocation.Target) !*Atom {
2143 return atom;2164 return atom;
2144}2165}
21452166
2167pub fn createTlvPtrAtom(self: *MachO, target: Atom.Relocation.Target) !*Atom {
2168 const local_sym_index = @intCast(u32, self.locals.items.len);
2169 try self.locals.append(self.base.allocator, .{
2170 .n_strx = 0,
2171 .n_type = macho.N_SECT,
2172 .n_sect = 0,
2173 .n_desc = 0,
2174 .n_value = 0,
2175 });
2176 const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), 3);
2177 assert(target == .global);
2178 try atom.bindings.append(self.base.allocator, .{
2179 .n_strx = target.global,
2180 .offset = 0,
2181 });
2182 return atom;
2183}
2184
2146fn createDyldPrivateAtom(self: *MachO) !void {2185fn createDyldPrivateAtom(self: *MachO) !void {
2147 if (self.dyld_private_atom != null) return;2186 if (self.dyld_private_atom != null) return;
2148 const local_sym_index = @intCast(u32, self.locals.items.len);2187 const local_sym_index = @intCast(u32, self.locals.items.len);
...@@ -2164,7 +2203,7 @@ fn createDyldPrivateAtom(self: *MachO) !void {...@@ -2164,7 +2203,7 @@ fn createDyldPrivateAtom(self: *MachO) !void {
2164 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);2203 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);
2165 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });2204 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });
2166 sym.n_value = vaddr;2205 sym.n_value = vaddr;
2167 } else try self.addAtomAndBumpSectionSize(atom, match);2206 } else try self.addAtomToSection(atom, match);
21682207
2169 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);2208 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2170}2209}
...@@ -2298,7 +2337,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {...@@ -2298,7 +2337,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
2298 const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match);2337 const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match);
2299 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });2338 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });
2300 sym.n_value = vaddr;2339 sym.n_value = vaddr;
2301 } else try self.addAtomAndBumpSectionSize(atom, match);2340 } else try self.addAtomToSection(atom, match);
23022341
2303 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);2342 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2304}2343}
...@@ -2514,7 +2553,7 @@ fn createTentativeDefAtoms(self: *MachO) !void {...@@ -2514,7 +2553,7 @@ fn createTentativeDefAtoms(self: *MachO) !void {
2514 const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match);2553 const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match);
2515 local_sym.n_value = vaddr;2554 local_sym.n_value = vaddr;
2516 global_sym.n_value = vaddr;2555 global_sym.n_value = vaddr;
2517 } else try self.addAtomAndBumpSectionSize(atom, match);2556 } else try self.addAtomToSection(atom, match);
2518 }2557 }
2519}2558}
25202559
...@@ -2567,7 +2606,7 @@ fn createDsoHandleAtom(self: *MachO) !void {...@@ -2567,7 +2606,7 @@ fn createDsoHandleAtom(self: *MachO) !void {
2567 const sym = &self.locals.items[local_sym_index];2606 const sym = &self.locals.items[local_sym_index];
2568 const vaddr = try self.allocateAtom(atom, 0, 1, match);2607 const vaddr = try self.allocateAtom(atom, 0, 1, match);
2569 sym.n_value = vaddr;2608 sym.n_value = vaddr;
2570 } else try self.addAtomAndBumpSectionSize(atom, match);2609 } else try self.addAtomToSection(atom, match);
2571 }2610 }
2572}2611}
25732612
...@@ -2913,7 +2952,7 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void {...@@ -2913,7 +2952,7 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void {
2913 const sym = &self.locals.items[local_sym_index];2952 const sym = &self.locals.items[local_sym_index];
2914 const vaddr = try self.allocateAtom(atom, 0, 1, match);2953 const vaddr = try self.allocateAtom(atom, 0, 1, match);
2915 sym.n_value = vaddr;2954 sym.n_value = vaddr;
2916 } else try self.addAtomAndBumpSectionSize(atom, match);2955 } else try self.addAtomToSection(atom, match);
29172956
2918 self.mh_execute_header_index = local_sym_index;2957 self.mh_execute_header_index = local_sym_index;
2919}2958}
...@@ -2973,7 +3012,7 @@ fn resolveDyldStubBinder(self: *MachO) !void {...@@ -2973,7 +3012,7 @@ fn resolveDyldStubBinder(self: *MachO) !void {
2973 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);3012 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);
2974 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });3013 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });
2975 atom_sym.n_value = vaddr;3014 atom_sym.n_value = vaddr;
2976 } else try self.addAtomAndBumpSectionSize(atom, match);3015 } else try self.addAtomToSection(atom, match);
29773016
2978 atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);3017 atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2979}3018}
...@@ -3174,7 +3213,7 @@ fn addCodeSignatureLC(self: *MachO) !void {...@@ -3174,7 +3213,7 @@ fn addCodeSignatureLC(self: *MachO) !void {
3174 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);3213 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
3175 try self.load_commands.append(self.base.allocator, .{3214 try self.load_commands.append(self.base.allocator, .{
3176 .linkedit_data = .{3215 .linkedit_data = .{
3177 .cmd = macho.LC_CODE_SIGNATURE,3216 .cmd = .CODE_SIGNATURE,
3178 .cmdsize = @sizeOf(macho.linkedit_data_command),3217 .cmdsize = @sizeOf(macho.linkedit_data_command),
3179 .dataoff = 0,3218 .dataoff = 0,
3180 .datasize = 0,3219 .datasize = 0,
...@@ -3215,6 +3254,8 @@ pub fn deinit(self: *MachO) void {...@@ -3215,6 +3254,8 @@ pub fn deinit(self: *MachO) void {
3215 }3254 }
32163255
3217 self.section_ordinals.deinit(self.base.allocator);3256 self.section_ordinals.deinit(self.base.allocator);
3257 self.tlv_ptr_entries_map.deinit(self.base.allocator);
3258 self.tlv_ptr_entries_map_free_list.deinit(self.base.allocator);
3218 self.got_entries_map.deinit(self.base.allocator);3259 self.got_entries_map.deinit(self.base.allocator);
3219 self.got_entries_map_free_list.deinit(self.base.allocator);3260 self.got_entries_map_free_list.deinit(self.base.allocator);
3220 self.stubs_map.deinit(self.base.allocator);3261 self.stubs_map.deinit(self.base.allocator);
...@@ -4203,7 +4244,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4203,7 +4244,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4203 self.dyld_info_cmd_index = @intCast(u16, self.load_commands.items.len);4244 self.dyld_info_cmd_index = @intCast(u16, self.load_commands.items.len);
4204 try self.load_commands.append(self.base.allocator, .{4245 try self.load_commands.append(self.base.allocator, .{
4205 .dyld_info_only = .{4246 .dyld_info_only = .{
4206 .cmd = macho.LC_DYLD_INFO_ONLY,4247 .cmd = .DYLD_INFO_ONLY,
4207 .cmdsize = @sizeOf(macho.dyld_info_command),4248 .cmdsize = @sizeOf(macho.dyld_info_command),
4208 .rebase_off = 0,4249 .rebase_off = 0,
4209 .rebase_size = 0,4250 .rebase_size = 0,
...@@ -4224,7 +4265,6 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4224,7 +4265,6 @@ fn populateMissingMetadata(self: *MachO) !void {
4224 self.symtab_cmd_index = @intCast(u16, self.load_commands.items.len);4265 self.symtab_cmd_index = @intCast(u16, self.load_commands.items.len);
4225 try self.load_commands.append(self.base.allocator, .{4266 try self.load_commands.append(self.base.allocator, .{
4226 .symtab = .{4267 .symtab = .{
4227 .cmd = macho.LC_SYMTAB,
4228 .cmdsize = @sizeOf(macho.symtab_command),4268 .cmdsize = @sizeOf(macho.symtab_command),
4229 .symoff = 0,4269 .symoff = 0,
4230 .nsyms = 0,4270 .nsyms = 0,
...@@ -4239,7 +4279,6 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4239,7 +4279,6 @@ fn populateMissingMetadata(self: *MachO) !void {
4239 self.dysymtab_cmd_index = @intCast(u16, self.load_commands.items.len);4279 self.dysymtab_cmd_index = @intCast(u16, self.load_commands.items.len);
4240 try self.load_commands.append(self.base.allocator, .{4280 try self.load_commands.append(self.base.allocator, .{
4241 .dysymtab = .{4281 .dysymtab = .{
4242 .cmd = macho.LC_DYSYMTAB,
4243 .cmdsize = @sizeOf(macho.dysymtab_command),4282 .cmdsize = @sizeOf(macho.dysymtab_command),
4244 .ilocalsym = 0,4283 .ilocalsym = 0,
4245 .nlocalsym = 0,4284 .nlocalsym = 0,
...@@ -4272,7 +4311,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4272,7 +4311,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4272 @sizeOf(u64),4311 @sizeOf(u64),
4273 ));4312 ));
4274 var dylinker_cmd = macho.emptyGenericCommandWithData(macho.dylinker_command{4313 var dylinker_cmd = macho.emptyGenericCommandWithData(macho.dylinker_command{
4275 .cmd = macho.LC_LOAD_DYLINKER,4314 .cmd = .LOAD_DYLINKER,
4276 .cmdsize = cmdsize,4315 .cmdsize = cmdsize,
4277 .name = @sizeOf(macho.dylinker_command),4316 .name = @sizeOf(macho.dylinker_command),
4278 });4317 });
...@@ -4287,7 +4326,6 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4287,7 +4326,6 @@ fn populateMissingMetadata(self: *MachO) !void {
4287 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);4326 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);
4288 try self.load_commands.append(self.base.allocator, .{4327 try self.load_commands.append(self.base.allocator, .{
4289 .main = .{4328 .main = .{
4290 .cmd = macho.LC_MAIN,
4291 .cmdsize = @sizeOf(macho.entry_point_command),4329 .cmdsize = @sizeOf(macho.entry_point_command),
4292 .entryoff = 0x0,4330 .entryoff = 0x0,
4293 .stacksize = 0,4331 .stacksize = 0,
...@@ -4314,7 +4352,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4314,7 +4352,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4314 compat_version.major << 16 | compat_version.minor << 8 | compat_version.patch,4352 compat_version.major << 16 | compat_version.minor << 8 | compat_version.patch,
4315 );4353 );
4316 errdefer dylib_cmd.deinit(self.base.allocator);4354 errdefer dylib_cmd.deinit(self.base.allocator);
4317 dylib_cmd.inner.cmd = macho.LC_ID_DYLIB;4355 dylib_cmd.inner.cmd = .ID_DYLIB;
4318 try self.load_commands.append(self.base.allocator, .{ .dylib = dylib_cmd });4356 try self.load_commands.append(self.base.allocator, .{ .dylib = dylib_cmd });
4319 self.load_commands_dirty = true;4357 self.load_commands_dirty = true;
4320 }4358 }
...@@ -4323,7 +4361,6 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4323,7 +4361,6 @@ fn populateMissingMetadata(self: *MachO) !void {
4323 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);4361 self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
4324 try self.load_commands.append(self.base.allocator, .{4362 try self.load_commands.append(self.base.allocator, .{
4325 .source_version = .{4363 .source_version = .{
4326 .cmd = macho.LC_SOURCE_VERSION,
4327 .cmdsize = @sizeOf(macho.source_version_command),4364 .cmdsize = @sizeOf(macho.source_version_command),
4328 .version = 0x0,4365 .version = 0x0,
4329 },4366 },
...@@ -4350,13 +4387,12 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4350,13 +4387,12 @@ fn populateMissingMetadata(self: *MachO) !void {
4350 } else platform_version;4387 } else platform_version;
4351 const is_simulator_abi = self.base.options.target.abi == .simulator;4388 const is_simulator_abi = self.base.options.target.abi == .simulator;
4352 var cmd = macho.emptyGenericCommandWithData(macho.build_version_command{4389 var cmd = macho.emptyGenericCommandWithData(macho.build_version_command{
4353 .cmd = macho.LC_BUILD_VERSION,
4354 .cmdsize = cmdsize,4390 .cmdsize = cmdsize,
4355 .platform = switch (self.base.options.target.os.tag) {4391 .platform = switch (self.base.options.target.os.tag) {
4356 .macos => macho.PLATFORM_MACOS,4392 .macos => .MACOS,
4357 .ios => if (is_simulator_abi) macho.PLATFORM_IOSSIMULATOR else macho.PLATFORM_IOS,4393 .ios => if (is_simulator_abi) macho.PLATFORM.IOSSIMULATOR else macho.PLATFORM.IOS,
4358 .watchos => if (is_simulator_abi) macho.PLATFORM_WATCHOSSIMULATOR else macho.PLATFORM_WATCHOS,4394 .watchos => if (is_simulator_abi) macho.PLATFORM.WATCHOSSIMULATOR else macho.PLATFORM.WATCHOS,
4359 .tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,4395 .tvos => if (is_simulator_abi) macho.PLATFORM.TVOSSIMULATOR else macho.PLATFORM.TVOS,
4360 else => unreachable,4396 else => unreachable,
4361 },4397 },
4362 .minos = platform_version,4398 .minos = platform_version,
...@@ -4364,7 +4400,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4364,7 +4400,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4364 .ntools = 1,4400 .ntools = 1,
4365 });4401 });
4366 const ld_ver = macho.build_tool_version{4402 const ld_ver = macho.build_tool_version{
4367 .tool = macho.TOOL_LD,4403 .tool = .LD,
4368 .version = 0x0,4404 .version = 0x0,
4369 };4405 };
4370 cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command));4406 cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command));
...@@ -4377,7 +4413,6 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4377,7 +4413,6 @@ fn populateMissingMetadata(self: *MachO) !void {
4377 if (self.uuid_cmd_index == null) {4413 if (self.uuid_cmd_index == null) {
4378 self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);4414 self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
4379 var uuid_cmd: macho.uuid_command = .{4415 var uuid_cmd: macho.uuid_command = .{
4380 .cmd = macho.LC_UUID,
4381 .cmdsize = @sizeOf(macho.uuid_command),4416 .cmdsize = @sizeOf(macho.uuid_command),
4382 .uuid = undefined,4417 .uuid = undefined,
4383 };4418 };
...@@ -4390,7 +4425,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4390,7 +4425,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4390 self.function_starts_cmd_index = @intCast(u16, self.load_commands.items.len);4425 self.function_starts_cmd_index = @intCast(u16, self.load_commands.items.len);
4391 try self.load_commands.append(self.base.allocator, .{4426 try self.load_commands.append(self.base.allocator, .{
4392 .linkedit_data = .{4427 .linkedit_data = .{
4393 .cmd = macho.LC_FUNCTION_STARTS,4428 .cmd = .FUNCTION_STARTS,
4394 .cmdsize = @sizeOf(macho.linkedit_data_command),4429 .cmdsize = @sizeOf(macho.linkedit_data_command),
4395 .dataoff = 0,4430 .dataoff = 0,
4396 .datasize = 0,4431 .datasize = 0,
...@@ -4403,7 +4438,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4403,7 +4438,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4403 self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len);4438 self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len);
4404 try self.load_commands.append(self.base.allocator, .{4439 try self.load_commands.append(self.base.allocator, .{
4405 .linkedit_data = .{4440 .linkedit_data = .{
4406 .cmd = macho.LC_DATA_IN_CODE,4441 .cmd = .DATA_IN_CODE,
4407 .cmdsize = @sizeOf(macho.linkedit_data_command),4442 .cmdsize = @sizeOf(macho.linkedit_data_command),
4408 .dataoff = 0,4443 .dataoff = 0,
4409 .datasize = 0,4444 .datasize = 0,
...@@ -4480,13 +4515,36 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void {...@@ -4480,13 +4515,36 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void {
44804515
4481 // Allocate the sections according to their alignment at the beginning of the segment.4516 // Allocate the sections according to their alignment at the beginning of the segment.
4482 var start: u64 = offset;4517 var start: u64 = offset;
4483 for (seg.sections.items) |*sect| {4518 for (seg.sections.items) |*sect, sect_id| {
4484 const alignment = try math.powi(u32, 2, sect.@"align");4519 const alignment = try math.powi(u32, 2, sect.@"align");
4485 const start_aligned = mem.alignForwardGeneric(u64, start, alignment);4520 const start_aligned = mem.alignForwardGeneric(u64, start, alignment);
4486 const end = start_aligned + sect.size;
4487 sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned);4521 sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned);
4488 sect.addr = seg.inner.vmaddr + start_aligned;4522 sect.addr = seg.inner.vmaddr + start_aligned;
4489 start = end;4523
4524 // Recalculate section size given the allocated start address
4525 sect.size = if (self.atoms.get(.{
4526 .seg = index,
4527 .sect = @intCast(u16, sect_id),
4528 })) |last_atom| blk: {
4529 var atom = last_atom;
4530 while (atom.prev) |prev| {
4531 atom = prev;
4532 }
4533
4534 var base_addr = sect.addr;
4535
4536 while (true) {
4537 const atom_alignment = try math.powi(u32, 2, atom.alignment);
4538 base_addr = mem.alignForwardGeneric(u64, base_addr, atom_alignment) + atom.size;
4539 if (atom.next) |next| {
4540 atom = next;
4541 } else break;
4542 }
4543
4544 break :blk base_addr - sect.addr;
4545 } else 0;
4546
4547 start = start_aligned + sect.size;
4490 }4548 }
44914549
4492 const seg_size_aligned = mem.alignForwardGeneric(u64, start, self.page_size);4550 const seg_size_aligned = mem.alignForwardGeneric(u64, start, self.page_size);
...@@ -4834,12 +4892,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m...@@ -4834,12 +4892,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m
4834 return vaddr;4892 return vaddr;
4835}4893}
48364894
4837fn addAtomAndBumpSectionSize(self: *MachO, atom: *Atom, match: MatchingSection) !void {4895fn addAtomToSection(self: *MachO, atom: *Atom, match: MatchingSection) !void {
4838 const seg = &self.load_commands.items[match.seg].segment;
4839 const sect = &seg.sections.items[match.sect];
4840 const alignment = try math.powi(u32, 2, atom.alignment);
4841 sect.size = mem.alignForwardGeneric(u64, sect.size, alignment) + atom.size;
4842
4843 if (self.atoms.getPtr(match)) |last| {4896 if (self.atoms.getPtr(match)) |last| {
4844 last.*.next = atom;4897 last.*.next = atom;
4845 atom.prev = last.*;4898 atom.prev = last.*;
...@@ -4978,6 +5031,7 @@ fn sortSections(self: *MachO) !void {...@@ -4978,6 +5031,7 @@ fn sortSections(self: *MachO) !void {
4978 &self.objc_data_section_index,5031 &self.objc_data_section_index,
4979 &self.data_section_index,5032 &self.data_section_index,
4980 &self.tlv_section_index,5033 &self.tlv_section_index,
5034 &self.tlv_ptrs_section_index,
4981 &self.tlv_data_section_index,5035 &self.tlv_data_section_index,
4982 &self.tlv_bss_section_index,5036 &self.tlv_bss_section_index,
4983 &self.bss_section_index,5037 &self.bss_section_index,
...@@ -6205,6 +6259,14 @@ fn logSymtab(self: MachO) void {...@@ -6205,6 +6259,14 @@ fn logSymtab(self: MachO) void {
6205 }6259 }
6206 }6260 }
62076261
6262 log.debug("__thread_ptrs entries:", .{});
6263 for (self.tlv_ptr_entries_map.keys()) |key| {
6264 switch (key) {
6265 .local => unreachable,
6266 .global => |n_strx| log.debug(" {} => {s}", .{ key, self.getString(n_strx) }),
6267 }
6268 }
6269
6208 log.debug("stubs:", .{});6270 log.debug("stubs:", .{});
6209 for (self.stubs_map.keys()) |key| {6271 for (self.stubs_map.keys()) |key| {
6210 log.debug(" {} => {s}", .{ key, self.getString(key) });6272 log.debug(" {} => {s}", .{ key, self.getString(key) });
src/link/MachO/Atom.zig+84-9
...@@ -403,6 +403,13 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC...@@ -403,6 +403,13 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC
403 }403 }
404 try self.addPtrBindingOrRebase(rel, target, context);404 try self.addPtrBindingOrRebase(rel, target, context);
405 },405 },
406 .ARM64_RELOC_TLVP_LOAD_PAGE21,
407 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
408 => {
409 if (target == .global) {
410 try addTlvPtrEntry(target, context);
411 }
412 },
406 else => {},413 else => {},
407 }414 }
408 },415 },
...@@ -452,6 +459,11 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC...@@ -452,6 +459,11 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC
452 @intCast(i64, target_sect_base_addr);459 @intCast(i64, target_sect_base_addr);
453 }460 }
454 },461 },
462 .X86_64_RELOC_TLV => {
463 if (target == .global) {
464 try addTlvPtrEntry(target, context);
465 }
466 },
455 else => {},467 else => {},
456 }468 }
457 },469 },
...@@ -531,6 +543,47 @@ fn addPtrBindingOrRebase(...@@ -531,6 +543,47 @@ fn addPtrBindingOrRebase(
531 }543 }
532}544}
533545
546fn addTlvPtrEntry(target: Relocation.Target, context: RelocContext) !void {
547 if (context.macho_file.tlv_ptr_entries_map.contains(target)) return;
548
549 const value_ptr = blk: {
550 if (context.macho_file.tlv_ptr_entries_map_free_list.popOrNull()) |i| {
551 log.debug("reusing __thread_ptrs entry index {d} for {}", .{ i, target });
552 context.macho_file.tlv_ptr_entries_map.keys()[i] = target;
553 const value_ptr = context.macho_file.tlv_ptr_entries_map.getPtr(target).?;
554 break :blk value_ptr;
555 } else {
556 const res = try context.macho_file.tlv_ptr_entries_map.getOrPut(
557 context.macho_file.base.allocator,
558 target,
559 );
560 log.debug("creating new __thread_ptrs entry at index {d} for {}", .{
561 context.macho_file.tlv_ptr_entries_map.getIndex(target).?,
562 target,
563 });
564 break :blk res.value_ptr;
565 }
566 };
567 const atom = try context.macho_file.createTlvPtrAtom(target);
568 value_ptr.* = atom;
569
570 const match = (try context.macho_file.getMatchingSection(.{
571 .segname = MachO.makeStaticString("__DATA"),
572 .sectname = MachO.makeStaticString("__thread_ptrs"),
573 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
574 })).?;
575 if (!context.object.start_atoms.contains(match)) {
576 try context.object.start_atoms.putNoClobber(context.allocator, match, atom);
577 }
578 if (context.object.end_atoms.getPtr(match)) |last| {
579 last.*.next = atom;
580 atom.prev = last.*;
581 last.* = atom;
582 } else {
583 try context.object.end_atoms.putNoClobber(context.allocator, match, atom);
584 }
585}
586
534fn addGotEntry(target: Relocation.Target, context: RelocContext) !void {587fn addGotEntry(target: Relocation.Target, context: RelocContext) !void {
535 if (context.macho_file.got_entries_map.contains(target)) return;588 if (context.macho_file.got_entries_map.contains(target)) return;
536589
...@@ -667,6 +720,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -667,6 +720,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
667 const sym = macho_file.locals.items[self.local_sym_index];720 const sym = macho_file.locals.items[self.local_sym_index];
668 break :blk sym.n_value + rel.offset;721 break :blk sym.n_value + rel.offset;
669 };722 };
723 var is_via_thread_ptrs: bool = false;
670 const target_addr = blk: {724 const target_addr = blk: {
671 const is_via_got = got: {725 const is_via_got = got: {
672 switch (arch) {726 switch (arch) {
...@@ -742,8 +796,13 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -742,8 +796,13 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
742 .undef => {796 .undef => {
743 break :blk if (macho_file.stubs_map.get(n_strx)) |atom|797 break :blk if (macho_file.stubs_map.get(n_strx)) |atom|
744 macho_file.locals.items[atom.local_sym_index].n_value798 macho_file.locals.items[atom.local_sym_index].n_value
745 else799 else inner: {
746 0;800 if (macho_file.tlv_ptr_entries_map.get(rel.target)) |atom| {
801 is_via_thread_ptrs = true;
802 break :inner macho_file.locals.items[atom.local_sym_index].n_value;
803 }
804 break :inner 0;
805 };
747 },806 },
748 }807 }
749 },808 },
...@@ -854,10 +913,12 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -854,10 +913,12 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
854 },913 },
855 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {914 .ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {
856 const code = self.code.items[rel.offset..][0..4];915 const code = self.code.items[rel.offset..][0..4];
916 const actual_target_addr = @intCast(i64, target_addr) + rel.addend;
917
857 const RegInfo = struct {918 const RegInfo = struct {
858 rd: u5,919 rd: u5,
859 rn: u5,920 rn: u5,
860 size: u1,921 size: u2,
861 };922 };
862 const reg_info: RegInfo = blk: {923 const reg_info: RegInfo = blk: {
863 if (isArithmeticOp(code)) {924 if (isArithmeticOp(code)) {
...@@ -878,13 +939,25 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -878,13 +939,25 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
878 break :blk .{939 break :blk .{
879 .rd = inst.rt,940 .rd = inst.rt,
880 .rn = inst.rn,941 .rn = inst.rn,
881 .size = @truncate(u1, inst.size),942 .size = inst.size,
882 };943 };
883 }944 }
884 };945 };
885 const actual_target_addr = @intCast(i64, target_addr) + rel.addend;
886 const narrowed = @truncate(u12, @intCast(u64, actual_target_addr));946 const narrowed = @truncate(u12, @intCast(u64, actual_target_addr));
887 var inst = aarch64.Instruction{947 var inst = if (is_via_thread_ptrs) blk: {
948 const offset = try math.divExact(u12, narrowed, 8);
949 break :blk aarch64.Instruction{
950 .load_store_register = .{
951 .rt = reg_info.rd,
952 .rn = reg_info.rn,
953 .offset = offset,
954 .opc = 0b01,
955 .op1 = 0b01,
956 .v = 0,
957 .size = reg_info.size,
958 },
959 };
960 } else aarch64.Instruction{
888 .add_subtract_immediate = .{961 .add_subtract_immediate = .{
889 .rd = reg_info.rd,962 .rd = reg_info.rd,
890 .rn = reg_info.rn,963 .rn = reg_info.rn,
...@@ -892,7 +965,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -892,7 +965,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
892 .sh = 0,965 .sh = 0,
893 .s = 0,966 .s = 0,
894 .op = 0,967 .op = 0,
895 .sf = reg_info.size,968 .sf = @truncate(u1, reg_info.size),
896 },969 },
897 };970 };
898 mem.writeIntLittle(u32, code, inst.toU32());971 mem.writeIntLittle(u32, code, inst.toU32());
...@@ -942,8 +1015,10 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -942,8 +1015,10 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
942 mem.writeIntLittle(u32, self.code.items[rel.offset..][0..4], @bitCast(u32, displacement));1015 mem.writeIntLittle(u32, self.code.items[rel.offset..][0..4], @bitCast(u32, displacement));
943 },1016 },
944 .X86_64_RELOC_TLV => {1017 .X86_64_RELOC_TLV => {
945 // We need to rewrite the opcode from movq to leaq.1018 if (!is_via_thread_ptrs) {
946 self.code.items[rel.offset - 2] = 0x8d;1019 // We need to rewrite the opcode from movq to leaq.
1020 self.code.items[rel.offset - 2] = 0x8d;
1021 }
947 const displacement = try math.cast(1022 const displacement = try math.cast(
948 i32,1023 i32,
949 @intCast(i64, target_addr) - @intCast(i64, source_addr) - 4 + rel.addend,1024 @intCast(i64, target_addr) - @intCast(i64, source_addr) - 4 + rel.addend,
src/link/MachO/DebugSymbols.zig-1
...@@ -122,7 +122,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void...@@ -122,7 +122,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void
122122
123 try self.load_commands.append(allocator, .{123 try self.load_commands.append(allocator, .{
124 .symtab = .{124 .symtab = .{
125 .cmd = macho.LC_SYMTAB,
126 .cmdsize = @sizeOf(macho.symtab_command),125 .cmdsize = @sizeOf(macho.symtab_command),
127 .symoff = @intCast(u32, symtab_off),126 .symoff = @intCast(u32, symtab_off),
128 .nsyms = base_cmd.nsyms,127 .nsyms = base_cmd.nsyms,
src/link/MachO/Dylib.zig+4-4
...@@ -177,16 +177,16 @@ fn readLoadCommands(self: *Dylib, allocator: Allocator, reader: anytype, depende...@@ -177,16 +177,16 @@ fn readLoadCommands(self: *Dylib, allocator: Allocator, reader: anytype, depende
177 while (i < self.header.?.ncmds) : (i += 1) {177 while (i < self.header.?.ncmds) : (i += 1) {
178 var cmd = try macho.LoadCommand.read(allocator, reader);178 var cmd = try macho.LoadCommand.read(allocator, reader);
179 switch (cmd.cmd()) {179 switch (cmd.cmd()) {
180 macho.LC_SYMTAB => {180 .SYMTAB => {
181 self.symtab_cmd_index = i;181 self.symtab_cmd_index = i;
182 },182 },
183 macho.LC_DYSYMTAB => {183 .DYSYMTAB => {
184 self.dysymtab_cmd_index = i;184 self.dysymtab_cmd_index = i;
185 },185 },
186 macho.LC_ID_DYLIB => {186 .ID_DYLIB => {
187 self.id_cmd_index = i;187 self.id_cmd_index = i;
188 },188 },
189 macho.LC_REEXPORT_DYLIB => {189 .REEXPORT_DYLIB => {
190 if (should_lookup_reexports) {190 if (should_lookup_reexports) {
191 // Parse install_name to dependent dylib.191 // Parse install_name to dependent dylib.
192 var id = try Id.fromLoadCommand(allocator, cmd.dylib);192 var id = try Id.fromLoadCommand(allocator, cmd.dylib);
src/link/MachO/Object.zig+5-5
...@@ -269,7 +269,7 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v...@@ -269,7 +269,7 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v
269 while (i < header.ncmds) : (i += 1) {269 while (i < header.ncmds) : (i += 1) {
270 var cmd = try macho.LoadCommand.read(allocator, reader);270 var cmd = try macho.LoadCommand.read(allocator, reader);
271 switch (cmd.cmd()) {271 switch (cmd.cmd()) {
272 macho.LC_SEGMENT_64 => {272 .SEGMENT_64 => {
273 self.segment_cmd_index = i;273 self.segment_cmd_index = i;
274 var seg = cmd.segment;274 var seg = cmd.segment;
275 for (seg.sections.items) |*sect, j| {275 for (seg.sections.items) |*sect, j| {
...@@ -302,18 +302,18 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v...@@ -302,18 +302,18 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v
302302
303 seg.inner.fileoff += offset;303 seg.inner.fileoff += offset;
304 },304 },
305 macho.LC_SYMTAB => {305 .SYMTAB => {
306 self.symtab_cmd_index = i;306 self.symtab_cmd_index = i;
307 cmd.symtab.symoff += offset;307 cmd.symtab.symoff += offset;
308 cmd.symtab.stroff += offset;308 cmd.symtab.stroff += offset;
309 },309 },
310 macho.LC_DYSYMTAB => {310 .DYSYMTAB => {
311 self.dysymtab_cmd_index = i;311 self.dysymtab_cmd_index = i;
312 },312 },
313 macho.LC_BUILD_VERSION => {313 .BUILD_VERSION => {
314 self.build_version_cmd_index = i;314 self.build_version_cmd_index = i;
315 },315 },
316 macho.LC_DATA_IN_CODE => {316 .DATA_IN_CODE => {
317 self.data_in_code_cmd_index = i;317 self.data_in_code_cmd_index = i;
318 cmd.linkedit_data.dataoff += offset;318 cmd.linkedit_data.dataoff += offset;
319 },319 },
test/standalone.zig+4
...@@ -34,6 +34,10 @@ pub fn addCases(cases: *tests.StandaloneContext) void {...@@ -34,6 +34,10 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
34 cases.addBuildFile("test/standalone/link_frameworks/build.zig", .{34 cases.addBuildFile("test/standalone/link_frameworks/build.zig", .{
35 .requires_macos_sdk = true,35 .requires_macos_sdk = true,
36 });36 });
37 cases.addBuildFile("test/standalone/link_common_symbols_alignment/build.zig", .{});
38 if (builtin.os.tag == .macos) {
39 cases.addBuildFile("test/standalone/link_import_tls_dylib/build.zig", .{});
40 }
37 cases.addBuildFile("test/standalone/issue_339/build.zig", .{});41 cases.addBuildFile("test/standalone/issue_339/build.zig", .{});
38 cases.addBuildFile("test/standalone/issue_8550/build.zig", .{});42 cases.addBuildFile("test/standalone/issue_8550/build.zig", .{});
39 cases.addBuildFile("test/standalone/issue_794/build.zig", .{});43 cases.addBuildFile("test/standalone/issue_794/build.zig", .{});
test/standalone/link_common_symbols_alignment/a.c created+2
...@@ -0,0 +1,2 @@
1int foo;
2__attribute__((aligned(4096))) int bar;
test/standalone/link_common_symbols_alignment/build.zig created+16
...@@ -0,0 +1,16 @@
1const Builder = @import("std").build.Builder;
2
3pub fn build(b: *Builder) void {
4 const mode = b.standardReleaseOptions();
5
6 const lib_a = b.addStaticLibrary("a", null);
7 lib_a.addCSourceFiles(&.{"a.c"}, &.{"-fcommon"});
8 lib_a.setBuildMode(mode);
9
10 const test_exe = b.addTest("main.zig");
11 test_exe.setBuildMode(mode);
12 test_exe.linkLibrary(lib_a);
13
14 const test_step = b.step("test", "Test it");
15 test_step.dependOn(&test_exe.step);
16}
test/standalone/link_common_symbols_alignment/main.zig created+9
...@@ -0,0 +1,9 @@
1const std = @import("std");
2
3extern var foo: i32;
4extern var bar: i32;
5
6test {
7 try std.testing.expect(@ptrToInt(&foo) % 4 == 0);
8 try std.testing.expect(@ptrToInt(&bar) % 4096 == 0);
9}
test/standalone/link_import_tls_dylib/a.c created+1
...@@ -0,0 +1 @@
1_Thread_local int a;
test/standalone/link_import_tls_dylib/build.zig created+16
...@@ -0,0 +1,16 @@
1const Builder = @import("std").build.Builder;
2
3pub fn build(b: *Builder) void {
4 const mode = b.standardReleaseOptions();
5
6 const lib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
7 lib.setBuildMode(mode);
8 lib.addCSourceFile("a.c", &.{});
9
10 const test_exe = b.addTest("main.zig");
11 test_exe.setBuildMode(mode);
12 test_exe.linkLibrary(lib);
13
14 const test_step = b.step("test", "Test it");
15 test_step.dependOn(&test_exe.step);
16}
test/standalone/link_import_tls_dylib/main.zig created+7
...@@ -0,0 +1,7 @@
1const std = @import("std");
2
3extern threadlocal var a: i32;
4
5test {
6 try std.testing.expect(a == 0);
7}