| author | |
| committer | |
| log | 87b843ef08426e1b14b2128987dfb52bb7de6788 |
| tree | 463e9a1c77ad8cf0d9dce57ee4dbb47b9c62c0d8 |
| parent | ff93486d0cbf032cbbf8b7953a072d448400ba2a |
| parent | bd926e5ea0f9b27677a270a4e8253b6a6f77379c |
| signature |
macho: refactor consts in std.macho, and fix two bugs in MachO linker backend14 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 | 843 | const symtab = while (ncmd != 0) : (ncmd -= 1) { |
| 844 | 844 | const lc = @ptrCast(*const std.macho.load_command, ptr); |
| 845 | 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 | 847 | else => {}, |
| 848 | 848 | } |
| 849 | 849 | ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize); |
| ... | ... | @@ -1072,7 +1072,7 @@ pub const DebugInfo = struct { |
| 1072 | 1072 | @alignCast(@alignOf(macho.load_command), cmd_ptr), |
| 1073 | 1073 | ); |
| 1074 | 1074 | cmd_ptr += lc.cmdsize; |
| 1075 | if (lc.cmd != macho.LC_SEGMENT_64) continue; | |
| 1075 | if (lc.cmd != .SEGMENT_64) continue; | |
| 1076 | 1076 | |
| 1077 | 1077 | const segment_cmd = @ptrCast( |
| 1078 | 1078 | *const std.macho.segment_command_64, |
| ... | ... | @@ -1303,14 +1303,14 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1303 | 1303 | while (ncmd != 0) : (ncmd -= 1) { |
| 1304 | 1304 | const lc = @ptrCast(*const std.macho.load_command, ptr); |
| 1305 | 1305 | switch (lc.cmd) { |
| 1306 | std.macho.LC_SEGMENT_64 => { | |
| 1306 | .SEGMENT_64 => { | |
| 1307 | 1307 | segcmd = @ptrCast( |
| 1308 | 1308 | *const std.macho.segment_command_64, |
| 1309 | 1309 | @alignCast(@alignOf(std.macho.segment_command_64), ptr), |
| 1310 | 1310 | ); |
| 1311 | 1311 | segptr = ptr; |
| 1312 | 1312 | }, |
| 1313 | std.macho.LC_SYMTAB => { | |
| 1313 | .SYMTAB => { | |
| 1314 | 1314 | symtabcmd = @ptrCast( |
| 1315 | 1315 | *const std.macho.symtab_command, |
| 1316 | 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 | 43 | }; |
| 44 | 44 | |
| 45 | 45 | pub const load_command = extern struct { |
| 46 | cmd: u32, | |
| 46 | cmd: LC, | |
| 47 | 47 | cmdsize: u32, |
| 48 | 48 | }; |
| 49 | 49 | |
| ... | ... | @@ -51,7 +51,7 @@ pub const load_command = extern struct { |
| 51 | 51 | /// identifies an object produced by the static link editor. |
| 52 | 52 | pub const uuid_command = extern struct { |
| 53 | 53 | /// LC_UUID |
| 54 | cmd: u32, | |
| 54 | cmd: LC = .UUID, | |
| 55 | 55 | |
| 56 | 56 | /// sizeof(struct uuid_command) |
| 57 | 57 | cmdsize: u32, |
| ... | ... | @@ -64,7 +64,7 @@ pub const uuid_command = extern struct { |
| 64 | 64 | /// binary was built to run. |
| 65 | 65 | pub const version_min_command = extern struct { |
| 66 | 66 | /// 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, | |
| 68 | 68 | |
| 69 | 69 | /// sizeof(struct version_min_command) |
| 70 | 70 | cmdsize: u32, |
| ... | ... | @@ -80,7 +80,7 @@ pub const version_min_command = extern struct { |
| 80 | 80 | /// the version of the sources used to build the binary. |
| 81 | 81 | pub const source_version_command = extern struct { |
| 82 | 82 | /// LC_SOURCE_VERSION |
| 83 | cmd: u32, | |
| 83 | cmd: LC = .SOURCE_VERSION, | |
| 84 | 84 | |
| 85 | 85 | /// sizeof(source_version_command) |
| 86 | 86 | cmdsize: u32, |
| ... | ... | @@ -94,14 +94,14 @@ pub const source_version_command = extern struct { |
| 94 | 94 | /// tool values following it. |
| 95 | 95 | pub const build_version_command = extern struct { |
| 96 | 96 | /// LC_BUILD_VERSION |
| 97 | cmd: u32, | |
| 97 | cmd: LC = .BUILD_VERSION, | |
| 98 | 98 | |
| 99 | 99 | /// sizeof(struct build_version_command) plus |
| 100 | 100 | /// ntools * sizeof(struct build_version_command) |
| 101 | 101 | cmdsize: u32, |
| 102 | 102 | |
| 103 | 103 | /// platform |
| 104 | platform: u32, | |
| 104 | platform: PLATFORM, | |
| 105 | 105 | |
| 106 | 106 | /// X.Y.Z is encoded in nibbles xxxx.yy.zz |
| 107 | 107 | minos: u32, |
| ... | ... | @@ -115,26 +115,32 @@ pub const build_version_command = extern struct { |
| 115 | 115 | |
| 116 | 116 | pub const build_tool_version = extern struct { |
| 117 | 117 | /// enum for the tool |
| 118 | tool: u32, | |
| 118 | tool: TOOL, | |
| 119 | 119 | |
| 120 | 120 | /// version number of the tool |
| 121 | 121 | version: u32, |
| 122 | 122 | }; |
| 123 | 123 | |
| 124 | pub const PLATFORM_MACOS: u32 = 0x1; | |
| 125 | pub const PLATFORM_IOS: u32 = 0x2; | |
| 126 | pub const PLATFORM_TVOS: u32 = 0x3; | |
| 127 | pub const PLATFORM_WATCHOS: u32 = 0x4; | |
| 128 | pub const PLATFORM_BRIDGEOS: u32 = 0x5; | |
| 129 | pub const PLATFORM_MACCATALYST: u32 = 0x6; | |
| 130 | pub const PLATFORM_IOSSIMULATOR: u32 = 0x7; | |
| 131 | pub const PLATFORM_TVOSSIMULATOR: u32 = 0x8; | |
| 132 | pub const PLATFORM_WATCHOSSIMULATOR: u32 = 0x9; | |
| 133 | pub const PLATFORM_DRIVERKIT: u32 = 0x10; | |
| 134 | ||
| 135 | pub const TOOL_CLANG: u32 = 0x1; | |
| 136 | pub const TOOL_SWIFT: u32 = 0x2; | |
| 137 | pub const TOOL_LD: u32 = 0x3; | |
| 124 | pub const PLATFORM = enum(u32) { | |
| 125 | MACOS = 0x1, | |
| 126 | IOS = 0x2, | |
| 127 | TVOS = 0x3, | |
| 128 | WATCHOS = 0x4, | |
| 129 | BRIDGEOS = 0x5, | |
| 130 | MACCATALYST = 0x6, | |
| 131 | IOSSIMULATOR = 0x7, | |
| 132 | TVOSSIMULATOR = 0x8, | |
| 133 | WATCHOSSIMULATOR = 0x9, | |
| 134 | DRIVERKIT = 0x10, | |
| 135 | _, | |
| 136 | }; | |
| 137 | ||
| 138 | pub const TOOL = enum(u32) { | |
| 139 | CLANG = 0x1, | |
| 140 | SWIFT = 0x2, | |
| 141 | LD = 0x3, | |
| 142 | _, | |
| 143 | }; | |
| 138 | 144 | |
| 139 | 145 | /// The entry_point_command is a replacement for thread_command. |
| 140 | 146 | /// It is used for main executables to specify the location (file offset) |
| ... | ... | @@ -142,7 +148,7 @@ pub const TOOL_LD: u32 = 0x3; |
| 142 | 148 | /// field will contain the stack size needed for the main thread. |
| 143 | 149 | pub const entry_point_command = extern struct { |
| 144 | 150 | /// LC_MAIN only used in MH_EXECUTE filetypes |
| 145 | cmd: u32, | |
| 151 | cmd: LC = .MAIN, | |
| 146 | 152 | |
| 147 | 153 | /// sizeof(struct entry_point_command) |
| 148 | 154 | cmdsize: u32, |
| ... | ... | @@ -159,7 +165,7 @@ pub const entry_point_command = extern struct { |
| 159 | 165 | /// <nlist.h> and <stab.h>. |
| 160 | 166 | pub const symtab_command = extern struct { |
| 161 | 167 | /// LC_SYMTAB |
| 162 | cmd: u32, | |
| 168 | cmd: LC = .SYMTAB, | |
| 163 | 169 | |
| 164 | 170 | /// sizeof(struct symtab_command) |
| 165 | 171 | cmdsize: u32, |
| ... | ... | @@ -217,7 +223,7 @@ pub const symtab_command = extern struct { |
| 217 | 223 | /// off the section structures. |
| 218 | 224 | pub const dysymtab_command = extern struct { |
| 219 | 225 | /// LC_DYSYMTAB |
| 220 | cmd: u32, | |
| 226 | cmd: LC = .DYSYMTAB, | |
| 221 | 227 | |
| 222 | 228 | /// sizeof(struct dysymtab_command) |
| 223 | 229 | cmdsize: u32, |
| ... | ... | @@ -357,7 +363,7 @@ pub const dysymtab_command = extern struct { |
| 357 | 363 | /// of data in the __LINKEDIT segment. |
| 358 | 364 | pub const linkedit_data_command = extern struct { |
| 359 | 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, | |
| 361 | 367 | |
| 362 | 368 | /// sizeof(struct linkedit_data_command) |
| 363 | 369 | cmdsize: u32, |
| ... | ... | @@ -377,7 +383,7 @@ pub const linkedit_data_command = extern struct { |
| 377 | 383 | /// to interpret it. |
| 378 | 384 | pub const dyld_info_command = extern struct { |
| 379 | 385 | /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY |
| 380 | cmd: u32, | |
| 386 | cmd: LC, | |
| 381 | 387 | |
| 382 | 388 | /// sizeof(struct dyld_info_command) |
| 383 | 389 | cmdsize: u32, |
| ... | ... | @@ -498,7 +504,7 @@ pub const dyld_info_command = extern struct { |
| 498 | 504 | /// string for dyld to treat like an environment variable. |
| 499 | 505 | pub const dylinker_command = extern struct { |
| 500 | 506 | /// LC_ID_DYLINKER, LC_LOAD_DYLINKER, or LC_DYLD_ENVIRONMENT |
| 501 | cmd: u32, | |
| 507 | cmd: LC, | |
| 502 | 508 | |
| 503 | 509 | /// includes pathname string |
| 504 | 510 | cmdsize: u32, |
| ... | ... | @@ -519,7 +525,7 @@ pub const dylinker_command = extern struct { |
| 519 | 525 | /// LC_REEXPORT_DYLIB) for each library it uses. |
| 520 | 526 | pub const dylib_command = extern struct { |
| 521 | 527 | /// LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_LOAD_DYLIB, LC_REEXPORT_DYLIB |
| 522 | cmd: u32, | |
| 528 | cmd: LC, | |
| 523 | 529 | |
| 524 | 530 | /// includes pathname string |
| 525 | 531 | cmdsize: u32, |
| ... | ... | @@ -553,7 +559,7 @@ pub const dylib = extern struct { |
| 553 | 559 | /// run path used to find @rpath prefixed dylibs. |
| 554 | 560 | pub const rpath_command = extern struct { |
| 555 | 561 | /// LC_RPATH |
| 556 | cmd: u32, | |
| 562 | cmd: LC = .RPATH, | |
| 557 | 563 | |
| 558 | 564 | /// includes string |
| 559 | 565 | cmdsize: u32, |
| ... | ... | @@ -574,7 +580,7 @@ pub const rpath_command = extern struct { |
| 574 | 580 | /// reflected in cmdsize. |
| 575 | 581 | pub const segment_command = extern struct { |
| 576 | 582 | /// LC_SEGMENT |
| 577 | cmd: u32, | |
| 583 | cmd: LC = .SEGMENT, | |
| 578 | 584 | |
| 579 | 585 | /// includes sizeof section structs |
| 580 | 586 | cmdsize: u32, |
| ... | ... | @@ -611,7 +617,7 @@ pub const segment_command = extern struct { |
| 611 | 617 | /// command and their size is reflected in cmdsize. |
| 612 | 618 | pub const segment_command_64 = extern struct { |
| 613 | 619 | /// LC_SEGMENT_64 |
| 614 | cmd: u32 = LC_SEGMENT_64, | |
| 620 | cmd: LC = .SEGMENT_64, | |
| 615 | 621 | |
| 616 | 622 | /// includes sizeof section_64 structs |
| 617 | 623 | cmdsize: u32 = @sizeOf(segment_command_64), |
| ... | ... | @@ -882,159 +888,163 @@ pub const relocation_info = packed struct { |
| 882 | 888 | /// simply be ignored. |
| 883 | 889 | pub const LC_REQ_DYLD = 0x80000000; |
| 884 | 890 | |
| 885 | /// segment of this file to be mapped | |
| 886 | pub const LC_SEGMENT = 0x1; | |
| 891 | pub const LC = enum(u32) { | |
| 892 | /// segment of this file to be mapped | |
| 893 | SEGMENT = 0x1, | |
| 887 | 894 | |
| 888 | /// link-edit stab symbol table info | |
| 889 | pub const LC_SYMTAB = 0x2; | |
| 895 | /// link-edit stab symbol table info | |
| 896 | SYMTAB = 0x2, | |
| 890 | 897 | |
| 891 | /// link-edit gdb symbol table info (obsolete) | |
| 892 | pub const LC_SYMSEG = 0x3; | |
| 898 | /// link-edit gdb symbol table info (obsolete) | |
| 899 | SYMSEG = 0x3, | |
| 893 | 900 | |
| 894 | /// thread | |
| 895 | pub const LC_THREAD = 0x4; | |
| 901 | /// thread | |
| 902 | THREAD = 0x4, | |
| 896 | 903 | |
| 897 | /// unix thread (includes a stack) | |
| 898 | pub const LC_UNIXTHREAD = 0x5; | |
| 904 | /// unix thread (includes a stack) | |
| 905 | UNIXTHREAD = 0x5, | |
| 899 | 906 | |
| 900 | /// load a specified fixed VM shared library | |
| 901 | pub const LC_LOADFVMLIB = 0x6; | |
| 907 | /// load a specified fixed VM shared library | |
| 908 | LOADFVMLIB = 0x6, | |
| 902 | 909 | |
| 903 | /// fixed VM shared library identification | |
| 904 | pub const LC_IDFVMLIB = 0x7; | |
| 910 | /// fixed VM shared library identification | |
| 911 | IDFVMLIB = 0x7, | |
| 905 | 912 | |
| 906 | /// object identification info (obsolete) | |
| 907 | pub const LC_IDENT = 0x8; | |
| 913 | /// object identification info (obsolete) | |
| 914 | IDENT = 0x8, | |
| 908 | 915 | |
| 909 | /// fixed VM file inclusion (internal use) | |
| 910 | pub const LC_FVMFILE = 0x9; | |
| 916 | /// fixed VM file inclusion (internal use) | |
| 917 | FVMFILE = 0x9, | |
| 911 | 918 | |
| 912 | /// prepage command (internal use) | |
| 913 | pub const LC_PREPAGE = 0xa; | |
| 919 | /// prepage command (internal use) | |
| 920 | PREPAGE = 0xa, | |
| 914 | 921 | |
| 915 | /// dynamic link-edit symbol table info | |
| 916 | pub const LC_DYSYMTAB = 0xb; | |
| 922 | /// dynamic link-edit symbol table info | |
| 923 | DYSYMTAB = 0xb, | |
| 917 | 924 | |
| 918 | /// load a dynamically linked shared library | |
| 919 | pub const LC_LOAD_DYLIB = 0xc; | |
| 925 | /// load a dynamically linked shared library | |
| 926 | LOAD_DYLIB = 0xc, | |
| 920 | 927 | |
| 921 | /// dynamically linked shared lib ident | |
| 922 | pub const LC_ID_DYLIB = 0xd; | |
| 928 | /// dynamically linked shared lib ident | |
| 929 | ID_DYLIB = 0xd, | |
| 923 | 930 | |
| 924 | /// load a dynamic linker | |
| 925 | pub const LC_LOAD_DYLINKER = 0xe; | |
| 931 | /// load a dynamic linker | |
| 932 | LOAD_DYLINKER = 0xe, | |
| 926 | 933 | |
| 927 | /// dynamic linker identification | |
| 928 | pub const LC_ID_DYLINKER = 0xf; | |
| 934 | /// dynamic linker identification | |
| 935 | ID_DYLINKER = 0xf, | |
| 929 | 936 | |
| 930 | /// modules prebound for a dynamically | |
| 931 | pub const LC_PREBOUND_DYLIB = 0x10; | |
| 937 | /// modules prebound for a dynamically | |
| 938 | PREBOUND_DYLIB = 0x10, | |
| 932 | 939 | |
| 933 | /// image routines | |
| 934 | pub const LC_ROUTINES = 0x11; | |
| 940 | /// image routines | |
| 941 | ROUTINES = 0x11, | |
| 935 | 942 | |
| 936 | /// sub framework | |
| 937 | pub const LC_SUB_FRAMEWORK = 0x12; | |
| 943 | /// sub framework | |
| 944 | SUB_FRAMEWORK = 0x12, | |
| 938 | 945 | |
| 939 | /// sub umbrella | |
| 940 | pub const LC_SUB_UMBRELLA = 0x13; | |
| 946 | /// sub umbrella | |
| 947 | SUB_UMBRELLA = 0x13, | |
| 941 | 948 | |
| 942 | /// sub client | |
| 943 | pub const LC_SUB_CLIENT = 0x14; | |
| 949 | /// sub client | |
| 950 | SUB_CLIENT = 0x14, | |
| 944 | 951 | |
| 945 | /// sub library | |
| 946 | pub const LC_SUB_LIBRARY = 0x15; | |
| 952 | /// sub library | |
| 953 | SUB_LIBRARY = 0x15, | |
| 947 | 954 | |
| 948 | /// two-level namespace lookup hints | |
| 949 | pub const LC_TWOLEVEL_HINTS = 0x16; | |
| 955 | /// two-level namespace lookup hints | |
| 956 | TWOLEVEL_HINTS = 0x16, | |
| 950 | 957 | |
| 951 | /// prebind checksum | |
| 952 | pub const LC_PREBIND_CKSUM = 0x17; | |
| 958 | /// prebind checksum | |
| 959 | PREBIND_CKSUM = 0x17, | |
| 953 | 960 | |
| 954 | /// load a dynamically linked shared library that is allowed to be missing | |
| 955 | /// (all symbols are weak imported). | |
| 956 | pub const LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD); | |
| 961 | /// load a dynamically linked shared library that is allowed to be missing | |
| 962 | /// (all symbols are weak imported). | |
| 963 | LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD), | |
| 957 | 964 | |
| 958 | /// 64-bit segment of this file to be mapped | |
| 959 | pub const LC_SEGMENT_64 = 0x19; | |
| 965 | /// 64-bit segment of this file to be mapped | |
| 966 | SEGMENT_64 = 0x19, | |
| 960 | 967 | |
| 961 | /// 64-bit image routines | |
| 962 | pub const LC_ROUTINES_64 = 0x1a; | |
| 968 | /// 64-bit image routines | |
| 969 | ROUTINES_64 = 0x1a, | |
| 963 | 970 | |
| 964 | /// the uuid | |
| 965 | pub const LC_UUID = 0x1b; | |
| 971 | /// the uuid | |
| 972 | UUID = 0x1b, | |
| 966 | 973 | |
| 967 | /// runpath additions | |
| 968 | pub const LC_RPATH = (0x1c | LC_REQ_DYLD); | |
| 974 | /// runpath additions | |
| 975 | RPATH = (0x1c | LC_REQ_DYLD), | |
| 969 | 976 | |
| 970 | /// local of code signature | |
| 971 | pub const LC_CODE_SIGNATURE = 0x1d; | |
| 977 | /// local of code signature | |
| 978 | CODE_SIGNATURE = 0x1d, | |
| 972 | 979 | |
| 973 | /// local of info to split segments | |
| 974 | pub const LC_SEGMENT_SPLIT_INFO = 0x1e; | |
| 980 | /// local of info to split segments | |
| 981 | SEGMENT_SPLIT_INFO = 0x1e, | |
| 975 | 982 | |
| 976 | /// load and re-export dylib | |
| 977 | pub const LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD); | |
| 983 | /// load and re-export dylib | |
| 984 | REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD), | |
| 978 | 985 | |
| 979 | /// delay load of dylib until first use | |
| 980 | pub const LC_LAZY_LOAD_DYLIB = 0x20; | |
| 986 | /// delay load of dylib until first use | |
| 987 | LAZY_LOAD_DYLIB = 0x20, | |
| 981 | 988 | |
| 982 | /// encrypted segment information | |
| 983 | pub const LC_ENCRYPTION_INFO = 0x21; | |
| 989 | /// encrypted segment information | |
| 990 | ENCRYPTION_INFO = 0x21, | |
| 984 | 991 | |
| 985 | /// compressed dyld information | |
| 986 | pub const LC_DYLD_INFO = 0x22; | |
| 992 | /// compressed dyld information | |
| 993 | DYLD_INFO = 0x22, | |
| 987 | 994 | |
| 988 | /// compressed dyld information only | |
| 989 | pub const LC_DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD); | |
| 995 | /// compressed dyld information only | |
| 996 | DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD), | |
| 990 | 997 | |
| 991 | /// load upward dylib | |
| 992 | pub const LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD); | |
| 998 | /// load upward dylib | |
| 999 | LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD), | |
| 993 | 1000 | |
| 994 | /// build for MacOSX min OS version | |
| 995 | pub const LC_VERSION_MIN_MACOSX = 0x24; | |
| 1001 | /// build for MacOSX min OS version | |
| 1002 | VERSION_MIN_MACOSX = 0x24, | |
| 996 | 1003 | |
| 997 | /// build for iPhoneOS min OS version | |
| 998 | pub const LC_VERSION_MIN_IPHONEOS = 0x25; | |
| 1004 | /// build for iPhoneOS min OS version | |
| 1005 | VERSION_MIN_IPHONEOS = 0x25, | |
| 999 | 1006 | |
| 1000 | /// compressed table of function start addresses | |
| 1001 | pub const LC_FUNCTION_STARTS = 0x26; | |
| 1007 | /// compressed table of function start addresses | |
| 1008 | FUNCTION_STARTS = 0x26, | |
| 1002 | 1009 | |
| 1003 | /// string for dyld to treat like environment variable | |
| 1004 | pub const LC_DYLD_ENVIRONMENT = 0x27; | |
| 1010 | /// string for dyld to treat like environment variable | |
| 1011 | DYLD_ENVIRONMENT = 0x27, | |
| 1005 | 1012 | |
| 1006 | /// replacement for LC_UNIXTHREAD | |
| 1007 | pub const LC_MAIN = (0x28 | LC_REQ_DYLD); | |
| 1013 | /// replacement for LC_UNIXTHREAD | |
| 1014 | MAIN = (0x28 | LC_REQ_DYLD), | |
| 1008 | 1015 | |
| 1009 | /// table of non-instructions in __text | |
| 1010 | pub const LC_DATA_IN_CODE = 0x29; | |
| 1016 | /// table of non-instructions in __text | |
| 1017 | DATA_IN_CODE = 0x29, | |
| 1011 | 1018 | |
| 1012 | /// source version used to build binary | |
| 1013 | pub const LC_SOURCE_VERSION = 0x2A; | |
| 1019 | /// source version used to build binary | |
| 1020 | SOURCE_VERSION = 0x2A, | |
| 1014 | 1021 | |
| 1015 | /// Code signing DRs copied from linked dylibs | |
| 1016 | pub const LC_DYLIB_CODE_SIGN_DRS = 0x2B; | |
| 1022 | /// Code signing DRs copied from linked dylibs | |
| 1023 | DYLIB_CODE_SIGN_DRS = 0x2B, | |
| 1017 | 1024 | |
| 1018 | /// 64-bit encrypted segment information | |
| 1019 | pub const LC_ENCRYPTION_INFO_64 = 0x2C; | |
| 1025 | /// 64-bit encrypted segment information | |
| 1026 | ENCRYPTION_INFO_64 = 0x2C, | |
| 1020 | 1027 | |
| 1021 | /// linker options in MH_OBJECT files | |
| 1022 | pub const LC_LINKER_OPTION = 0x2D; | |
| 1028 | /// linker options in MH_OBJECT files | |
| 1029 | LINKER_OPTION = 0x2D, | |
| 1023 | 1030 | |
| 1024 | /// optimization hints in MH_OBJECT files | |
| 1025 | pub const LC_LINKER_OPTIMIZATION_HINT = 0x2E; | |
| 1031 | /// optimization hints in MH_OBJECT files | |
| 1032 | LINKER_OPTIMIZATION_HINT = 0x2E, | |
| 1026 | 1033 | |
| 1027 | /// build for AppleTV min OS version | |
| 1028 | pub const LC_VERSION_MIN_TVOS = 0x2F; | |
| 1034 | /// build for AppleTV min OS version | |
| 1035 | VERSION_MIN_TVOS = 0x2F, | |
| 1029 | 1036 | |
| 1030 | /// build for Watch min OS version | |
| 1031 | pub const LC_VERSION_MIN_WATCHOS = 0x30; | |
| 1037 | /// build for Watch min OS version | |
| 1038 | VERSION_MIN_WATCHOS = 0x30, | |
| 1032 | 1039 | |
| 1033 | /// arbitrary data included within a Mach-O file | |
| 1034 | pub const LC_NOTE = 0x31; | |
| 1040 | /// arbitrary data included within a Mach-O file | |
| 1041 | NOTE = 0x31, | |
| 1035 | 1042 | |
| 1036 | /// build for platform min OS version | |
| 1037 | pub const LC_BUILD_VERSION = 0x32; | |
| 1043 | /// build for platform min OS version | |
| 1044 | BUILD_VERSION = 0x32, | |
| 1045 | ||
| 1046 | _, | |
| 1047 | }; | |
| 1038 | 1048 | |
| 1039 | 1049 | /// the mach magic number |
| 1040 | 1050 | pub const MH_MAGIC = 0xfeedface; |
| ... | ... | @@ -1537,7 +1547,7 @@ pub const reloc_type_x86_64 = enum(u4) { |
| 1537 | 1547 | |
| 1538 | 1548 | pub const reloc_type_arm64 = enum(u4) { |
| 1539 | 1549 | /// For pointers. |
| 1540 | ARM64_RELOC_UNSIGNED, | |
| 1550 | ARM64_RELOC_UNSIGNED = 0, | |
| 1541 | 1551 | |
| 1542 | 1552 | /// Must be followed by a ARM64_RELOC_UNSIGNED. |
| 1543 | 1553 | ARM64_RELOC_SUBTRACTOR, |
| ... | ... | @@ -1840,43 +1850,43 @@ pub const LoadCommand = union(enum) { |
| 1840 | 1850 | var stream = io.fixedBufferStream(buffer); |
| 1841 | 1851 | |
| 1842 | 1852 | return switch (header.cmd) { |
| 1843 | LC_SEGMENT_64 => LoadCommand{ | |
| 1853 | .SEGMENT_64 => LoadCommand{ | |
| 1844 | 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 | 1857 | .dyld_info_only = try stream.reader().readStruct(dyld_info_command), |
| 1848 | 1858 | }, |
| 1849 | LC_SYMTAB => LoadCommand{ | |
| 1859 | .SYMTAB => LoadCommand{ | |
| 1850 | 1860 | .symtab = try stream.reader().readStruct(symtab_command), |
| 1851 | 1861 | }, |
| 1852 | LC_DYSYMTAB => LoadCommand{ | |
| 1862 | .DYSYMTAB => LoadCommand{ | |
| 1853 | 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 | 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 | 1869 | .dylib = try GenericCommandWithData(dylib_command).read(allocator, stream.reader()), |
| 1860 | 1870 | }, |
| 1861 | LC_MAIN => LoadCommand{ | |
| 1871 | .MAIN => LoadCommand{ | |
| 1862 | 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 | 1875 | .version_min = try stream.reader().readStruct(version_min_command), |
| 1866 | 1876 | }, |
| 1867 | LC_SOURCE_VERSION => LoadCommand{ | |
| 1877 | .SOURCE_VERSION => LoadCommand{ | |
| 1868 | 1878 | .source_version = try stream.reader().readStruct(source_version_command), |
| 1869 | 1879 | }, |
| 1870 | LC_BUILD_VERSION => LoadCommand{ | |
| 1880 | .BUILD_VERSION => LoadCommand{ | |
| 1871 | 1881 | .build_version = try GenericCommandWithData(build_version_command).read(allocator, stream.reader()), |
| 1872 | 1882 | }, |
| 1873 | LC_UUID => LoadCommand{ | |
| 1883 | .UUID => LoadCommand{ | |
| 1874 | 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 | 1887 | .linkedit_data = try stream.reader().readStruct(linkedit_data_command), |
| 1878 | 1888 | }, |
| 1879 | LC_RPATH => LoadCommand{ | |
| 1889 | .RPATH => LoadCommand{ | |
| 1880 | 1890 | .rpath = try GenericCommandWithData(rpath_command).read(allocator, stream.reader()), |
| 1881 | 1891 | }, |
| 1882 | 1892 | else => LoadCommand{ |
| ... | ... | @@ -1904,7 +1914,7 @@ pub const LoadCommand = union(enum) { |
| 1904 | 1914 | }; |
| 1905 | 1915 | } |
| 1906 | 1916 | |
| 1907 | pub fn cmd(self: LoadCommand) u32 { | |
| 1917 | pub fn cmd(self: LoadCommand) LC { | |
| 1908 | 1918 | return switch (self) { |
| 1909 | 1919 | .dyld_info_only => |x| x.cmd, |
| 1910 | 1920 | .symtab => |x| x.cmd, |
| ... | ... | @@ -2078,7 +2088,7 @@ pub fn createLoadDylibCommand( |
| 2078 | 2088 | )); |
| 2079 | 2089 | |
| 2080 | 2090 | var dylib_cmd = emptyGenericCommandWithData(dylib_command{ |
| 2081 | .cmd = LC_LOAD_DYLIB, | |
| 2091 | .cmd = .LOAD_DYLIB, | |
| 2082 | 2092 | .cmdsize = cmdsize, |
| 2083 | 2093 | .dylib = .{ |
| 2084 | 2094 | .name = @sizeOf(dylib_command), |
| ... | ... | @@ -2189,7 +2199,7 @@ test "read-write generic command with data" { |
| 2189 | 2199 | }; |
| 2190 | 2200 | var cmd = GenericCommandWithData(dylib_command){ |
| 2191 | 2201 | .inner = .{ |
| 2192 | .cmd = LC_LOAD_DYLIB, | |
| 2202 | .cmd = .LOAD_DYLIB, | |
| 2193 | 2203 | .cmdsize = 32, |
| 2194 | 2204 | .dylib = .{ |
| 2195 | 2205 | .name = 24, |
| ... | ... | @@ -2227,7 +2237,7 @@ test "read-write C struct command" { |
| 2227 | 2237 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // stacksize |
| 2228 | 2238 | }; |
| 2229 | 2239 | const cmd = .{ |
| 2230 | .cmd = LC_MAIN, | |
| 2240 | .cmd = .MAIN, | |
| 2231 | 2241 | .cmdsize = 24, |
| 2232 | 2242 | .entryoff = 16644, |
| 2233 | 2243 | .stacksize = 0, |
src/link/MachO.zig+95-33| ... | ... | @@ -130,6 +130,7 @@ objc_imageinfo_section_index: ?u16 = null, |
| 130 | 130 | tlv_section_index: ?u16 = null, |
| 131 | 131 | tlv_data_section_index: ?u16 = null, |
| 132 | 132 | tlv_bss_section_index: ?u16 = null, |
| 133 | tlv_ptrs_section_index: ?u16 = null, | |
| 133 | 134 | la_symbol_ptr_section_index: ?u16 = null, |
| 134 | 135 | data_section_index: ?u16 = null, |
| 135 | 136 | bss_section_index: ?u16 = null, |
| ... | ... | @@ -164,6 +165,9 @@ stub_helper_preamble_atom: ?*Atom = null, |
| 164 | 165 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 165 | 166 | strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 166 | 167 | |
| 168 | tlv_ptr_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{}, | |
| 169 | tlv_ptr_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{}, | |
| 170 | ||
| 167 | 171 | got_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{}, |
| 168 | 172 | got_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 169 | 173 | |
| ... | ... | @@ -783,7 +787,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 783 | 787 | @sizeOf(u64), |
| 784 | 788 | )); |
| 785 | 789 | var rpath_cmd = macho.emptyGenericCommandWithData(macho.rpath_command{ |
| 786 | .cmd = macho.LC_RPATH, | |
| 787 | 790 | .cmdsize = cmdsize, |
| 788 | 791 | .path = @sizeOf(macho.rpath_command), |
| 789 | 792 | }); |
| ... | ... | @@ -1526,6 +1529,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1526 | 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 | 1550 | macho.S_THREAD_LOCAL_REGULAR => { |
| 1530 | 1551 | if (self.tlv_data_section_index == null) { |
| 1531 | 1552 | self.tlv_data_section_index = try self.initSection( |
| ... | ... | @@ -2143,6 +2164,24 @@ pub fn createGotAtom(self: *MachO, target: Atom.Relocation.Target) !*Atom { |
| 2143 | 2164 | return atom; |
| 2144 | 2165 | } |
| 2145 | 2166 | |
| 2167 | pub 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 | ||
| 2146 | 2185 | fn createDyldPrivateAtom(self: *MachO) !void { |
| 2147 | 2186 | if (self.dyld_private_atom != null) return; |
| 2148 | 2187 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| ... | ... | @@ -2164,7 +2203,7 @@ fn createDyldPrivateAtom(self: *MachO) !void { |
| 2164 | 2203 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| 2165 | 2204 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2166 | 2205 | sym.n_value = vaddr; |
| 2167 | } else try self.addAtomAndBumpSectionSize(atom, match); | |
| 2206 | } else try self.addAtomToSection(atom, match); | |
| 2168 | 2207 | |
| 2169 | 2208 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2170 | 2209 | } |
| ... | ... | @@ -2298,7 +2337,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2298 | 2337 | const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match); |
| 2299 | 2338 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2300 | 2339 | sym.n_value = vaddr; |
| 2301 | } else try self.addAtomAndBumpSectionSize(atom, match); | |
| 2340 | } else try self.addAtomToSection(atom, match); | |
| 2302 | 2341 | |
| 2303 | 2342 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2304 | 2343 | } |
| ... | ... | @@ -2514,7 +2553,7 @@ fn createTentativeDefAtoms(self: *MachO) !void { |
| 2514 | 2553 | const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match); |
| 2515 | 2554 | local_sym.n_value = vaddr; |
| 2516 | 2555 | global_sym.n_value = vaddr; |
| 2517 | } else try self.addAtomAndBumpSectionSize(atom, match); | |
| 2556 | } else try self.addAtomToSection(atom, match); | |
| 2518 | 2557 | } |
| 2519 | 2558 | } |
| 2520 | 2559 | |
| ... | ... | @@ -2567,7 +2606,7 @@ fn createDsoHandleAtom(self: *MachO) !void { |
| 2567 | 2606 | const sym = &self.locals.items[local_sym_index]; |
| 2568 | 2607 | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| 2569 | 2608 | sym.n_value = vaddr; |
| 2570 | } else try self.addAtomAndBumpSectionSize(atom, match); | |
| 2609 | } else try self.addAtomToSection(atom, match); | |
| 2571 | 2610 | } |
| 2572 | 2611 | } |
| 2573 | 2612 | |
| ... | ... | @@ -2913,7 +2952,7 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void { |
| 2913 | 2952 | const sym = &self.locals.items[local_sym_index]; |
| 2914 | 2953 | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| 2915 | 2954 | sym.n_value = vaddr; |
| 2916 | } else try self.addAtomAndBumpSectionSize(atom, match); | |
| 2955 | } else try self.addAtomToSection(atom, match); | |
| 2917 | 2956 | |
| 2918 | 2957 | self.mh_execute_header_index = local_sym_index; |
| 2919 | 2958 | } |
| ... | ... | @@ -2973,7 +3012,7 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2973 | 3012 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| 2974 | 3013 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2975 | 3014 | atom_sym.n_value = vaddr; |
| 2976 | } else try self.addAtomAndBumpSectionSize(atom, match); | |
| 3015 | } else try self.addAtomToSection(atom, match); | |
| 2977 | 3016 | |
| 2978 | 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 | 3213 | self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3175 | 3214 | try self.load_commands.append(self.base.allocator, .{ |
| 3176 | 3215 | .linkedit_data = .{ |
| 3177 | .cmd = macho.LC_CODE_SIGNATURE, | |
| 3216 | .cmd = .CODE_SIGNATURE, | |
| 3178 | 3217 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| 3179 | 3218 | .dataoff = 0, |
| 3180 | 3219 | .datasize = 0, |
| ... | ... | @@ -3215,6 +3254,8 @@ pub fn deinit(self: *MachO) void { |
| 3215 | 3254 | } |
| 3216 | 3255 | |
| 3217 | 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 | 3259 | self.got_entries_map.deinit(self.base.allocator); |
| 3219 | 3260 | self.got_entries_map_free_list.deinit(self.base.allocator); |
| 3220 | 3261 | self.stubs_map.deinit(self.base.allocator); |
| ... | ... | @@ -4203,7 +4244,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4203 | 4244 | self.dyld_info_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4204 | 4245 | try self.load_commands.append(self.base.allocator, .{ |
| 4205 | 4246 | .dyld_info_only = .{ |
| 4206 | .cmd = macho.LC_DYLD_INFO_ONLY, | |
| 4247 | .cmd = .DYLD_INFO_ONLY, | |
| 4207 | 4248 | .cmdsize = @sizeOf(macho.dyld_info_command), |
| 4208 | 4249 | .rebase_off = 0, |
| 4209 | 4250 | .rebase_size = 0, |
| ... | ... | @@ -4224,7 +4265,6 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4224 | 4265 | self.symtab_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4225 | 4266 | try self.load_commands.append(self.base.allocator, .{ |
| 4226 | 4267 | .symtab = .{ |
| 4227 | .cmd = macho.LC_SYMTAB, | |
| 4228 | 4268 | .cmdsize = @sizeOf(macho.symtab_command), |
| 4229 | 4269 | .symoff = 0, |
| 4230 | 4270 | .nsyms = 0, |
| ... | ... | @@ -4239,7 +4279,6 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4239 | 4279 | self.dysymtab_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4240 | 4280 | try self.load_commands.append(self.base.allocator, .{ |
| 4241 | 4281 | .dysymtab = .{ |
| 4242 | .cmd = macho.LC_DYSYMTAB, | |
| 4243 | 4282 | .cmdsize = @sizeOf(macho.dysymtab_command), |
| 4244 | 4283 | .ilocalsym = 0, |
| 4245 | 4284 | .nlocalsym = 0, |
| ... | ... | @@ -4272,7 +4311,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4272 | 4311 | @sizeOf(u64), |
| 4273 | 4312 | )); |
| 4274 | 4313 | var dylinker_cmd = macho.emptyGenericCommandWithData(macho.dylinker_command{ |
| 4275 | .cmd = macho.LC_LOAD_DYLINKER, | |
| 4314 | .cmd = .LOAD_DYLINKER, | |
| 4276 | 4315 | .cmdsize = cmdsize, |
| 4277 | 4316 | .name = @sizeOf(macho.dylinker_command), |
| 4278 | 4317 | }); |
| ... | ... | @@ -4287,7 +4326,6 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4287 | 4326 | self.main_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4288 | 4327 | try self.load_commands.append(self.base.allocator, .{ |
| 4289 | 4328 | .main = .{ |
| 4290 | .cmd = macho.LC_MAIN, | |
| 4291 | 4329 | .cmdsize = @sizeOf(macho.entry_point_command), |
| 4292 | 4330 | .entryoff = 0x0, |
| 4293 | 4331 | .stacksize = 0, |
| ... | ... | @@ -4314,7 +4352,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4314 | 4352 | compat_version.major << 16 | compat_version.minor << 8 | compat_version.patch, |
| 4315 | 4353 | ); |
| 4316 | 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 | 4356 | try self.load_commands.append(self.base.allocator, .{ .dylib = dylib_cmd }); |
| 4319 | 4357 | self.load_commands_dirty = true; |
| 4320 | 4358 | } |
| ... | ... | @@ -4323,7 +4361,6 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4323 | 4361 | self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4324 | 4362 | try self.load_commands.append(self.base.allocator, .{ |
| 4325 | 4363 | .source_version = .{ |
| 4326 | .cmd = macho.LC_SOURCE_VERSION, | |
| 4327 | 4364 | .cmdsize = @sizeOf(macho.source_version_command), |
| 4328 | 4365 | .version = 0x0, |
| 4329 | 4366 | }, |
| ... | ... | @@ -4350,13 +4387,12 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4350 | 4387 | } else platform_version; |
| 4351 | 4388 | const is_simulator_abi = self.base.options.target.abi == .simulator; |
| 4352 | 4389 | var cmd = macho.emptyGenericCommandWithData(macho.build_version_command{ |
| 4353 | .cmd = macho.LC_BUILD_VERSION, | |
| 4354 | 4390 | .cmdsize = cmdsize, |
| 4355 | 4391 | .platform = switch (self.base.options.target.os.tag) { |
| 4356 | .macos => macho.PLATFORM_MACOS, | |
| 4357 | .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, | |
| 4359 | .tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS, | |
| 4392 | .macos => .MACOS, | |
| 4393 | .ios => if (is_simulator_abi) macho.PLATFORM.IOSSIMULATOR else macho.PLATFORM.IOS, | |
| 4394 | .watchos => if (is_simulator_abi) macho.PLATFORM.WATCHOSSIMULATOR else macho.PLATFORM.WATCHOS, | |
| 4395 | .tvos => if (is_simulator_abi) macho.PLATFORM.TVOSSIMULATOR else macho.PLATFORM.TVOS, | |
| 4360 | 4396 | else => unreachable, |
| 4361 | 4397 | }, |
| 4362 | 4398 | .minos = platform_version, |
| ... | ... | @@ -4364,7 +4400,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4364 | 4400 | .ntools = 1, |
| 4365 | 4401 | }); |
| 4366 | 4402 | const ld_ver = macho.build_tool_version{ |
| 4367 | .tool = macho.TOOL_LD, | |
| 4403 | .tool = .LD, | |
| 4368 | 4404 | .version = 0x0, |
| 4369 | 4405 | }; |
| 4370 | 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 | 4413 | if (self.uuid_cmd_index == null) { |
| 4378 | 4414 | self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4379 | 4415 | var uuid_cmd: macho.uuid_command = .{ |
| 4380 | .cmd = macho.LC_UUID, | |
| 4381 | 4416 | .cmdsize = @sizeOf(macho.uuid_command), |
| 4382 | 4417 | .uuid = undefined, |
| 4383 | 4418 | }; |
| ... | ... | @@ -4390,7 +4425,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4390 | 4425 | self.function_starts_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4391 | 4426 | try self.load_commands.append(self.base.allocator, .{ |
| 4392 | 4427 | .linkedit_data = .{ |
| 4393 | .cmd = macho.LC_FUNCTION_STARTS, | |
| 4428 | .cmd = .FUNCTION_STARTS, | |
| 4394 | 4429 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| 4395 | 4430 | .dataoff = 0, |
| 4396 | 4431 | .datasize = 0, |
| ... | ... | @@ -4403,7 +4438,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4403 | 4438 | self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4404 | 4439 | try self.load_commands.append(self.base.allocator, .{ |
| 4405 | 4440 | .linkedit_data = .{ |
| 4406 | .cmd = macho.LC_DATA_IN_CODE, | |
| 4441 | .cmd = .DATA_IN_CODE, | |
| 4407 | 4442 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| 4408 | 4443 | .dataoff = 0, |
| 4409 | 4444 | .datasize = 0, |
| ... | ... | @@ -4480,13 +4515,36 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void { |
| 4480 | 4515 | |
| 4481 | 4516 | // Allocate the sections according to their alignment at the beginning of the segment. |
| 4482 | 4517 | var start: u64 = offset; |
| 4483 | for (seg.sections.items) |*sect| { | |
| 4518 | for (seg.sections.items) |*sect, sect_id| { | |
| 4484 | 4519 | const alignment = try math.powi(u32, 2, sect.@"align"); |
| 4485 | 4520 | const start_aligned = mem.alignForwardGeneric(u64, start, alignment); |
| 4486 | const end = start_aligned + sect.size; | |
| 4487 | 4521 | sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned); |
| 4488 | 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 | } |
| 4491 | 4549 | |
| 4492 | 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 | 4892 | return vaddr; |
| 4835 | 4893 | } |
| 4836 | 4894 | |
| 4837 | fn addAtomAndBumpSectionSize(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 | ||
| 4895 | fn addAtomToSection(self: *MachO, atom: *Atom, match: MatchingSection) !void { | |
| 4843 | 4896 | if (self.atoms.getPtr(match)) |last| { |
| 4844 | 4897 | last.*.next = atom; |
| 4845 | 4898 | atom.prev = last.*; |
| ... | ... | @@ -4978,6 +5031,7 @@ fn sortSections(self: *MachO) !void { |
| 4978 | 5031 | &self.objc_data_section_index, |
| 4979 | 5032 | &self.data_section_index, |
| 4980 | 5033 | &self.tlv_section_index, |
| 5034 | &self.tlv_ptrs_section_index, | |
| 4981 | 5035 | &self.tlv_data_section_index, |
| 4982 | 5036 | &self.tlv_bss_section_index, |
| 4983 | 5037 | &self.bss_section_index, |
| ... | ... | @@ -6205,6 +6259,14 @@ fn logSymtab(self: MachO) void { |
| 6205 | 6259 | } |
| 6206 | 6260 | } |
| 6207 | 6261 | |
| 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 | 6270 | log.debug("stubs:", .{}); |
| 6209 | 6271 | for (self.stubs_map.keys()) |key| { |
| 6210 | 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 | 403 | } |
| 404 | 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 | 413 | else => {}, |
| 407 | 414 | } |
| 408 | 415 | }, |
| ... | ... | @@ -452,6 +459,11 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC |
| 452 | 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 | 467 | else => {}, |
| 456 | 468 | } |
| 457 | 469 | }, |
| ... | ... | @@ -531,6 +543,47 @@ fn addPtrBindingOrRebase( |
| 531 | 543 | } |
| 532 | 544 | } |
| 533 | 545 | |
| 546 | fn 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 | ||
| 534 | 587 | fn addGotEntry(target: Relocation.Target, context: RelocContext) !void { |
| 535 | 588 | if (context.macho_file.got_entries_map.contains(target)) return; |
| 536 | 589 | |
| ... | ... | @@ -667,6 +720,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 667 | 720 | const sym = macho_file.locals.items[self.local_sym_index]; |
| 668 | 721 | break :blk sym.n_value + rel.offset; |
| 669 | 722 | }; |
| 723 | var is_via_thread_ptrs: bool = false; | |
| 670 | 724 | const target_addr = blk: { |
| 671 | 725 | const is_via_got = got: { |
| 672 | 726 | switch (arch) { |
| ... | ... | @@ -742,8 +796,13 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 742 | 796 | .undef => { |
| 743 | 797 | break :blk if (macho_file.stubs_map.get(n_strx)) |atom| |
| 744 | 798 | macho_file.locals.items[atom.local_sym_index].n_value |
| 745 | else | |
| 746 | 0; | |
| 799 | else inner: { | |
| 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 | 913 | }, |
| 855 | 914 | .ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => { |
| 856 | 915 | const code = self.code.items[rel.offset..][0..4]; |
| 916 | const actual_target_addr = @intCast(i64, target_addr) + rel.addend; | |
| 917 | ||
| 857 | 918 | const RegInfo = struct { |
| 858 | 919 | rd: u5, |
| 859 | 920 | rn: u5, |
| 860 | size: u1, | |
| 921 | size: u2, | |
| 861 | 922 | }; |
| 862 | 923 | const reg_info: RegInfo = blk: { |
| 863 | 924 | if (isArithmeticOp(code)) { |
| ... | ... | @@ -878,13 +939,25 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 878 | 939 | break :blk .{ |
| 879 | 940 | .rd = inst.rt, |
| 880 | 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 | 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 | 961 | .add_subtract_immediate = .{ |
| 889 | 962 | .rd = reg_info.rd, |
| 890 | 963 | .rn = reg_info.rn, |
| ... | ... | @@ -892,7 +965,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 892 | 965 | .sh = 0, |
| 893 | 966 | .s = 0, |
| 894 | 967 | .op = 0, |
| 895 | .sf = reg_info.size, | |
| 968 | .sf = @truncate(u1, reg_info.size), | |
| 896 | 969 | }, |
| 897 | 970 | }; |
| 898 | 971 | mem.writeIntLittle(u32, code, inst.toU32()); |
| ... | ... | @@ -942,8 +1015,10 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 942 | 1015 | mem.writeIntLittle(u32, self.code.items[rel.offset..][0..4], @bitCast(u32, displacement)); |
| 943 | 1016 | }, |
| 944 | 1017 | .X86_64_RELOC_TLV => { |
| 945 | // We need to rewrite the opcode from movq to leaq. | |
| 946 | self.code.items[rel.offset - 2] = 0x8d; | |
| 1018 | if (!is_via_thread_ptrs) { | |
| 1019 | // We need to rewrite the opcode from movq to leaq. | |
| 1020 | self.code.items[rel.offset - 2] = 0x8d; | |
| 1021 | } | |
| 947 | 1022 | const displacement = try math.cast( |
| 948 | 1023 | i32, |
| 949 | 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 | 122 | |
| 123 | 123 | try self.load_commands.append(allocator, .{ |
| 124 | 124 | .symtab = .{ |
| 125 | .cmd = macho.LC_SYMTAB, | |
| 126 | 125 | .cmdsize = @sizeOf(macho.symtab_command), |
| 127 | 126 | .symoff = @intCast(u32, symtab_off), |
| 128 | 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 | 177 | while (i < self.header.?.ncmds) : (i += 1) { |
| 178 | 178 | var cmd = try macho.LoadCommand.read(allocator, reader); |
| 179 | 179 | switch (cmd.cmd()) { |
| 180 | macho.LC_SYMTAB => { | |
| 180 | .SYMTAB => { | |
| 181 | 181 | self.symtab_cmd_index = i; |
| 182 | 182 | }, |
| 183 | macho.LC_DYSYMTAB => { | |
| 183 | .DYSYMTAB => { | |
| 184 | 184 | self.dysymtab_cmd_index = i; |
| 185 | 185 | }, |
| 186 | macho.LC_ID_DYLIB => { | |
| 186 | .ID_DYLIB => { | |
| 187 | 187 | self.id_cmd_index = i; |
| 188 | 188 | }, |
| 189 | macho.LC_REEXPORT_DYLIB => { | |
| 189 | .REEXPORT_DYLIB => { | |
| 190 | 190 | if (should_lookup_reexports) { |
| 191 | 191 | // Parse install_name to dependent dylib. |
| 192 | 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 | 269 | while (i < header.ncmds) : (i += 1) { |
| 270 | 270 | var cmd = try macho.LoadCommand.read(allocator, reader); |
| 271 | 271 | switch (cmd.cmd()) { |
| 272 | macho.LC_SEGMENT_64 => { | |
| 272 | .SEGMENT_64 => { | |
| 273 | 273 | self.segment_cmd_index = i; |
| 274 | 274 | var seg = cmd.segment; |
| 275 | 275 | for (seg.sections.items) |*sect, j| { |
| ... | ... | @@ -302,18 +302,18 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v |
| 302 | 302 | |
| 303 | 303 | seg.inner.fileoff += offset; |
| 304 | 304 | }, |
| 305 | macho.LC_SYMTAB => { | |
| 305 | .SYMTAB => { | |
| 306 | 306 | self.symtab_cmd_index = i; |
| 307 | 307 | cmd.symtab.symoff += offset; |
| 308 | 308 | cmd.symtab.stroff += offset; |
| 309 | 309 | }, |
| 310 | macho.LC_DYSYMTAB => { | |
| 310 | .DYSYMTAB => { | |
| 311 | 311 | self.dysymtab_cmd_index = i; |
| 312 | 312 | }, |
| 313 | macho.LC_BUILD_VERSION => { | |
| 313 | .BUILD_VERSION => { | |
| 314 | 314 | self.build_version_cmd_index = i; |
| 315 | 315 | }, |
| 316 | macho.LC_DATA_IN_CODE => { | |
| 316 | .DATA_IN_CODE => { | |
| 317 | 317 | self.data_in_code_cmd_index = i; |
| 318 | 318 | cmd.linkedit_data.dataoff += offset; |
| 319 | 319 | }, |
test/standalone.zig+4| ... | ... | @@ -34,6 +34,10 @@ pub fn addCases(cases: *tests.StandaloneContext) void { |
| 34 | 34 | cases.addBuildFile("test/standalone/link_frameworks/build.zig", .{ |
| 35 | 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 | 41 | cases.addBuildFile("test/standalone/issue_339/build.zig", .{}); |
| 38 | 42 | cases.addBuildFile("test/standalone/issue_8550/build.zig", .{}); |
| 39 | 43 | cases.addBuildFile("test/standalone/issue_794/build.zig", .{}); |
test/standalone/link_common_symbols_alignment/a.c created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | int foo; | |
| 2 | __attribute__((aligned(4096))) int bar; |
test/standalone/link_common_symbols_alignment/build.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const Builder = @import("std").build.Builder; | |
| 2 | ||
| 3 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | extern var foo: i32; | |
| 4 | extern var bar: i32; | |
| 5 | ||
| 6 | test { | |
| 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 @@ |
| 1 | const Builder = @import("std").build.Builder; | |
| 2 | ||
| 3 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | extern threadlocal var a: i32; | |
| 4 | ||
| 5 | test { | |
| 6 | try std.testing.expect(a == 0); | |
| 7 | } |