| 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,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; |
| 1076 | 1076 | ||
| 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 | }; |
| 44 | 44 | ||
| 45 | pub const load_command = extern struct { | 45 | pub const load_command = extern struct { |
| 46 | cmd: u32, | 46 | cmd: LC, |
| 47 | cmdsize: u32, | 47 | cmdsize: u32, |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| ... | @@ -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. |
| 52 | pub const uuid_command = extern struct { | 52 | pub const uuid_command = extern struct { |
| 53 | /// LC_UUID | 53 | /// LC_UUID |
| 54 | cmd: u32, | 54 | cmd: LC = .UUID, |
| 55 | 55 | ||
| 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. |
| 65 | pub const version_min_command = extern struct { | 65 | pub 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_TVOS | 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 | /// 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. |
| 81 | pub const source_version_command = extern struct { | 81 | pub const source_version_command = extern struct { |
| 82 | /// LC_SOURCE_VERSION | 82 | /// LC_SOURCE_VERSION |
| 83 | cmd: u32, | 83 | cmd: LC = .SOURCE_VERSION, |
| 84 | 84 | ||
| 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. |
| 95 | pub const build_version_command = extern struct { | 95 | pub const build_version_command = extern struct { |
| 96 | /// LC_BUILD_VERSION | 96 | /// LC_BUILD_VERSION |
| 97 | cmd: u32, | 97 | cmd: LC = .BUILD_VERSION, |
| 98 | 98 | ||
| 99 | /// sizeof(struct build_version_command) plus | 99 | /// 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, |
| 102 | 102 | ||
| 103 | /// platform | 103 | /// platform |
| 104 | platform: u32, | 104 | platform: PLATFORM, |
| 105 | 105 | ||
| 106 | /// X.Y.Z is encoded in nibbles xxxx.yy.zz | 106 | /// 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 { |
| 115 | 115 | ||
| 116 | pub const build_tool_version = extern struct { | 116 | pub const build_tool_version = extern struct { |
| 117 | /// enum for the tool | 117 | /// enum for the tool |
| 118 | tool: u32, | 118 | tool: TOOL, |
| 119 | 119 | ||
| 120 | /// version number of the tool | 120 | /// version number of the tool |
| 121 | version: u32, | 121 | version: u32, |
| 122 | }; | 122 | }; |
| 123 | 123 | ||
| 124 | pub const PLATFORM_MACOS: u32 = 0x1; | 124 | pub const PLATFORM = enum(u32) { |
| 125 | pub const PLATFORM_IOS: u32 = 0x2; | 125 | MACOS = 0x1, |
| 126 | pub const PLATFORM_TVOS: u32 = 0x3; | 126 | IOS = 0x2, |
| 127 | pub const PLATFORM_WATCHOS: u32 = 0x4; | 127 | TVOS = 0x3, |
| 128 | pub const PLATFORM_BRIDGEOS: u32 = 0x5; | 128 | WATCHOS = 0x4, |
| 129 | pub const PLATFORM_MACCATALYST: u32 = 0x6; | 129 | BRIDGEOS = 0x5, |
| 130 | pub const PLATFORM_IOSSIMULATOR: u32 = 0x7; | 130 | MACCATALYST = 0x6, |
| 131 | pub const PLATFORM_TVOSSIMULATOR: u32 = 0x8; | 131 | IOSSIMULATOR = 0x7, |
| 132 | pub const PLATFORM_WATCHOSSIMULATOR: u32 = 0x9; | 132 | TVOSSIMULATOR = 0x8, |
| 133 | pub const PLATFORM_DRIVERKIT: u32 = 0x10; | 133 | WATCHOSSIMULATOR = 0x9, |
| 134 | 134 | DRIVERKIT = 0x10, | |
| 135 | pub const TOOL_CLANG: u32 = 0x1; | 135 | _, |
| 136 | pub const TOOL_SWIFT: u32 = 0x2; | 136 | }; |
| 137 | pub const TOOL_LD: u32 = 0x3; | 137 | |
| 138 | pub const TOOL = enum(u32) { | ||
| 139 | CLANG = 0x1, | ||
| 140 | SWIFT = 0x2, | ||
| 141 | LD = 0x3, | ||
| 142 | _, | ||
| 143 | }; | ||
| 138 | 144 | ||
| 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. |
| 143 | pub const entry_point_command = extern struct { | 149 | pub const entry_point_command = extern struct { |
| 144 | /// LC_MAIN only used in MH_EXECUTE filetypes | 150 | /// LC_MAIN only used in MH_EXECUTE filetypes |
| 145 | cmd: u32, | 151 | cmd: LC = .MAIN, |
| 146 | 152 | ||
| 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>. |
| 160 | pub const symtab_command = extern struct { | 166 | pub const symtab_command = extern struct { |
| 161 | /// LC_SYMTAB | 167 | /// LC_SYMTAB |
| 162 | cmd: u32, | 168 | cmd: LC = .SYMTAB, |
| 163 | 169 | ||
| 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. |
| 218 | pub const dysymtab_command = extern struct { | 224 | pub const dysymtab_command = extern struct { |
| 219 | /// LC_DYSYMTAB | 225 | /// LC_DYSYMTAB |
| 220 | cmd: u32, | 226 | cmd: LC = .DYSYMTAB, |
| 221 | 227 | ||
| 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. |
| 358 | pub const linkedit_data_command = extern struct { | 364 | pub 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, |
| 361 | 367 | ||
| 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. |
| 378 | pub const dyld_info_command = extern struct { | 384 | pub const dyld_info_command = extern struct { |
| 379 | /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY | 385 | /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY |
| 380 | cmd: u32, | 386 | cmd: LC, |
| 381 | 387 | ||
| 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. |
| 499 | pub const dylinker_command = extern struct { | 505 | pub const dylinker_command = extern struct { |
| 500 | /// LC_ID_DYLINKER, LC_LOAD_DYLINKER, or LC_DYLD_ENVIRONMENT | 506 | /// LC_ID_DYLINKER, LC_LOAD_DYLINKER, or LC_DYLD_ENVIRONMENT |
| 501 | cmd: u32, | 507 | cmd: LC, |
| 502 | 508 | ||
| 503 | /// includes pathname string | 509 | /// 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. |
| 520 | pub const dylib_command = extern struct { | 526 | pub const dylib_command = extern struct { |
| 521 | /// LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_LOAD_DYLIB, LC_REEXPORT_DYLIB | 527 | /// LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_LOAD_DYLIB, LC_REEXPORT_DYLIB |
| 522 | cmd: u32, | 528 | cmd: LC, |
| 523 | 529 | ||
| 524 | /// includes pathname string | 530 | /// 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. |
| 554 | pub const rpath_command = extern struct { | 560 | pub const rpath_command = extern struct { |
| 555 | /// LC_RPATH | 561 | /// LC_RPATH |
| 556 | cmd: u32, | 562 | cmd: LC = .RPATH, |
| 557 | 563 | ||
| 558 | /// includes string | 564 | /// 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. |
| 575 | pub const segment_command = extern struct { | 581 | pub const segment_command = extern struct { |
| 576 | /// LC_SEGMENT | 582 | /// LC_SEGMENT |
| 577 | cmd: u32, | 583 | cmd: LC = .SEGMENT, |
| 578 | 584 | ||
| 579 | /// includes sizeof section structs | 585 | /// 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. |
| 612 | pub const segment_command_64 = extern struct { | 618 | pub const segment_command_64 = extern struct { |
| 613 | /// LC_SEGMENT_64 | 619 | /// LC_SEGMENT_64 |
| 614 | cmd: u32 = LC_SEGMENT_64, | 620 | cmd: LC = .SEGMENT_64, |
| 615 | 621 | ||
| 616 | /// includes sizeof section_64 structs | 622 | /// 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. |
| 883 | pub const LC_REQ_DYLD = 0x80000000; | 889 | pub const LC_REQ_DYLD = 0x80000000; |
| 884 | 890 | ||
| 885 | /// segment of this file to be mapped | 891 | pub const LC = enum(u32) { |
| 886 | pub const LC_SEGMENT = 0x1; | 892 | /// segment of this file to be mapped |
| 893 | SEGMENT = 0x1, | ||
| 887 | 894 | ||
| 888 | /// link-edit stab symbol table info | 895 | /// link-edit stab symbol table info |
| 889 | pub const LC_SYMTAB = 0x2; | 896 | SYMTAB = 0x2, |
| 890 | 897 | ||
| 891 | /// link-edit gdb symbol table info (obsolete) | 898 | /// link-edit gdb symbol table info (obsolete) |
| 892 | pub const LC_SYMSEG = 0x3; | 899 | SYMSEG = 0x3, |
| 893 | 900 | ||
| 894 | /// thread | 901 | /// thread |
| 895 | pub const LC_THREAD = 0x4; | 902 | THREAD = 0x4, |
| 896 | 903 | ||
| 897 | /// unix thread (includes a stack) | 904 | /// unix thread (includes a stack) |
| 898 | pub const LC_UNIXTHREAD = 0x5; | 905 | UNIXTHREAD = 0x5, |
| 899 | 906 | ||
| 900 | /// load a specified fixed VM shared library | 907 | /// load a specified fixed VM shared library |
| 901 | pub const LC_LOADFVMLIB = 0x6; | 908 | LOADFVMLIB = 0x6, |
| 902 | 909 | ||
| 903 | /// fixed VM shared library identification | 910 | /// fixed VM shared library identification |
| 904 | pub const LC_IDFVMLIB = 0x7; | 911 | IDFVMLIB = 0x7, |
| 905 | 912 | ||
| 906 | /// object identification info (obsolete) | 913 | /// object identification info (obsolete) |
| 907 | pub const LC_IDENT = 0x8; | 914 | IDENT = 0x8, |
| 908 | 915 | ||
| 909 | /// fixed VM file inclusion (internal use) | 916 | /// fixed VM file inclusion (internal use) |
| 910 | pub const LC_FVMFILE = 0x9; | 917 | FVMFILE = 0x9, |
| 911 | 918 | ||
| 912 | /// prepage command (internal use) | 919 | /// prepage command (internal use) |
| 913 | pub const LC_PREPAGE = 0xa; | 920 | PREPAGE = 0xa, |
| 914 | 921 | ||
| 915 | /// dynamic link-edit symbol table info | 922 | /// dynamic link-edit symbol table info |
| 916 | pub const LC_DYSYMTAB = 0xb; | 923 | DYSYMTAB = 0xb, |
| 917 | 924 | ||
| 918 | /// load a dynamically linked shared library | 925 | /// load a dynamically linked shared library |
| 919 | pub const LC_LOAD_DYLIB = 0xc; | 926 | LOAD_DYLIB = 0xc, |
| 920 | 927 | ||
| 921 | /// dynamically linked shared lib ident | 928 | /// dynamically linked shared lib ident |
| 922 | pub const LC_ID_DYLIB = 0xd; | 929 | ID_DYLIB = 0xd, |
| 923 | 930 | ||
| 924 | /// load a dynamic linker | 931 | /// load a dynamic linker |
| 925 | pub const LC_LOAD_DYLINKER = 0xe; | 932 | LOAD_DYLINKER = 0xe, |
| 926 | 933 | ||
| 927 | /// dynamic linker identification | 934 | /// dynamic linker identification |
| 928 | pub const LC_ID_DYLINKER = 0xf; | 935 | ID_DYLINKER = 0xf, |
| 929 | 936 | ||
| 930 | /// modules prebound for a dynamically | 937 | /// modules prebound for a dynamically |
| 931 | pub const LC_PREBOUND_DYLIB = 0x10; | 938 | PREBOUND_DYLIB = 0x10, |
| 932 | 939 | ||
| 933 | /// image routines | 940 | /// image routines |
| 934 | pub const LC_ROUTINES = 0x11; | 941 | ROUTINES = 0x11, |
| 935 | 942 | ||
| 936 | /// sub framework | 943 | /// sub framework |
| 937 | pub const LC_SUB_FRAMEWORK = 0x12; | 944 | SUB_FRAMEWORK = 0x12, |
| 938 | 945 | ||
| 939 | /// sub umbrella | 946 | /// sub umbrella |
| 940 | pub const LC_SUB_UMBRELLA = 0x13; | 947 | SUB_UMBRELLA = 0x13, |
| 941 | 948 | ||
| 942 | /// sub client | 949 | /// sub client |
| 943 | pub const LC_SUB_CLIENT = 0x14; | 950 | SUB_CLIENT = 0x14, |
| 944 | 951 | ||
| 945 | /// sub library | 952 | /// sub library |
| 946 | pub const LC_SUB_LIBRARY = 0x15; | 953 | SUB_LIBRARY = 0x15, |
| 947 | 954 | ||
| 948 | /// two-level namespace lookup hints | 955 | /// two-level namespace lookup hints |
| 949 | pub const LC_TWOLEVEL_HINTS = 0x16; | 956 | TWOLEVEL_HINTS = 0x16, |
| 950 | 957 | ||
| 951 | /// prebind checksum | 958 | /// prebind checksum |
| 952 | pub const LC_PREBIND_CKSUM = 0x17; | 959 | PREBIND_CKSUM = 0x17, |
| 953 | 960 | ||
| 954 | /// load a dynamically linked shared library that is allowed to be missing | 961 | /// load a dynamically linked shared library that is allowed to be missing |
| 955 | /// (all symbols are weak imported). | 962 | /// (all symbols are weak imported). |
| 956 | pub const LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD); | 963 | LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD), |
| 957 | 964 | ||
| 958 | /// 64-bit segment of this file to be mapped | 965 | /// 64-bit segment of this file to be mapped |
| 959 | pub const LC_SEGMENT_64 = 0x19; | 966 | SEGMENT_64 = 0x19, |
| 960 | 967 | ||
| 961 | /// 64-bit image routines | 968 | /// 64-bit image routines |
| 962 | pub const LC_ROUTINES_64 = 0x1a; | 969 | ROUTINES_64 = 0x1a, |
| 963 | 970 | ||
| 964 | /// the uuid | 971 | /// the uuid |
| 965 | pub const LC_UUID = 0x1b; | 972 | UUID = 0x1b, |
| 966 | 973 | ||
| 967 | /// runpath additions | 974 | /// runpath additions |
| 968 | pub const LC_RPATH = (0x1c | LC_REQ_DYLD); | 975 | RPATH = (0x1c | LC_REQ_DYLD), |
| 969 | 976 | ||
| 970 | /// local of code signature | 977 | /// local of code signature |
| 971 | pub const LC_CODE_SIGNATURE = 0x1d; | 978 | CODE_SIGNATURE = 0x1d, |
| 972 | 979 | ||
| 973 | /// local of info to split segments | 980 | /// local of info to split segments |
| 974 | pub const LC_SEGMENT_SPLIT_INFO = 0x1e; | 981 | SEGMENT_SPLIT_INFO = 0x1e, |
| 975 | 982 | ||
| 976 | /// load and re-export dylib | 983 | /// load and re-export dylib |
| 977 | pub const LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD); | 984 | REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD), |
| 978 | 985 | ||
| 979 | /// delay load of dylib until first use | 986 | /// delay load of dylib until first use |
| 980 | pub const LC_LAZY_LOAD_DYLIB = 0x20; | 987 | LAZY_LOAD_DYLIB = 0x20, |
| 981 | 988 | ||
| 982 | /// encrypted segment information | 989 | /// encrypted segment information |
| 983 | pub const LC_ENCRYPTION_INFO = 0x21; | 990 | ENCRYPTION_INFO = 0x21, |
| 984 | 991 | ||
| 985 | /// compressed dyld information | 992 | /// compressed dyld information |
| 986 | pub const LC_DYLD_INFO = 0x22; | 993 | DYLD_INFO = 0x22, |
| 987 | 994 | ||
| 988 | /// compressed dyld information only | 995 | /// compressed dyld information only |
| 989 | pub const LC_DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD); | 996 | DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD), |
| 990 | 997 | ||
| 991 | /// load upward dylib | 998 | /// load upward dylib |
| 992 | pub const LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD); | 999 | LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD), |
| 993 | 1000 | ||
| 994 | /// build for MacOSX min OS version | 1001 | /// build for MacOSX min OS version |
| 995 | pub const LC_VERSION_MIN_MACOSX = 0x24; | 1002 | VERSION_MIN_MACOSX = 0x24, |
| 996 | 1003 | ||
| 997 | /// build for iPhoneOS min OS version | 1004 | /// build for iPhoneOS min OS version |
| 998 | pub const LC_VERSION_MIN_IPHONEOS = 0x25; | 1005 | VERSION_MIN_IPHONEOS = 0x25, |
| 999 | 1006 | ||
| 1000 | /// compressed table of function start addresses | 1007 | /// compressed table of function start addresses |
| 1001 | pub const LC_FUNCTION_STARTS = 0x26; | 1008 | FUNCTION_STARTS = 0x26, |
| 1002 | 1009 | ||
| 1003 | /// string for dyld to treat like environment variable | 1010 | /// string for dyld to treat like environment variable |
| 1004 | pub const LC_DYLD_ENVIRONMENT = 0x27; | 1011 | DYLD_ENVIRONMENT = 0x27, |
| 1005 | 1012 | ||
| 1006 | /// replacement for LC_UNIXTHREAD | 1013 | /// replacement for LC_UNIXTHREAD |
| 1007 | pub const LC_MAIN = (0x28 | LC_REQ_DYLD); | 1014 | MAIN = (0x28 | LC_REQ_DYLD), |
| 1008 | 1015 | ||
| 1009 | /// table of non-instructions in __text | 1016 | /// table of non-instructions in __text |
| 1010 | pub const LC_DATA_IN_CODE = 0x29; | 1017 | DATA_IN_CODE = 0x29, |
| 1011 | 1018 | ||
| 1012 | /// source version used to build binary | 1019 | /// source version used to build binary |
| 1013 | pub const LC_SOURCE_VERSION = 0x2A; | 1020 | SOURCE_VERSION = 0x2A, |
| 1014 | 1021 | ||
| 1015 | /// Code signing DRs copied from linked dylibs | 1022 | /// Code signing DRs copied from linked dylibs |
| 1016 | pub const LC_DYLIB_CODE_SIGN_DRS = 0x2B; | 1023 | DYLIB_CODE_SIGN_DRS = 0x2B, |
| 1017 | 1024 | ||
| 1018 | /// 64-bit encrypted segment information | 1025 | /// 64-bit encrypted segment information |
| 1019 | pub const LC_ENCRYPTION_INFO_64 = 0x2C; | 1026 | ENCRYPTION_INFO_64 = 0x2C, |
| 1020 | 1027 | ||
| 1021 | /// linker options in MH_OBJECT files | 1028 | /// linker options in MH_OBJECT files |
| 1022 | pub const LC_LINKER_OPTION = 0x2D; | 1029 | LINKER_OPTION = 0x2D, |
| 1023 | 1030 | ||
| 1024 | /// optimization hints in MH_OBJECT files | 1031 | /// optimization hints in MH_OBJECT files |
| 1025 | pub const LC_LINKER_OPTIMIZATION_HINT = 0x2E; | 1032 | LINKER_OPTIMIZATION_HINT = 0x2E, |
| 1026 | 1033 | ||
| 1027 | /// build for AppleTV min OS version | 1034 | /// build for AppleTV min OS version |
| 1028 | pub const LC_VERSION_MIN_TVOS = 0x2F; | 1035 | VERSION_MIN_TVOS = 0x2F, |
| 1029 | 1036 | ||
| 1030 | /// build for Watch min OS version | 1037 | /// build for Watch min OS version |
| 1031 | pub const LC_VERSION_MIN_WATCHOS = 0x30; | 1038 | VERSION_MIN_WATCHOS = 0x30, |
| 1032 | 1039 | ||
| 1033 | /// arbitrary data included within a Mach-O file | 1040 | /// arbitrary data included within a Mach-O file |
| 1034 | pub const LC_NOTE = 0x31; | 1041 | NOTE = 0x31, |
| 1035 | 1042 | ||
| 1036 | /// build for platform min OS version | 1043 | /// build for platform min OS version |
| 1037 | pub const LC_BUILD_VERSION = 0x32; | 1044 | BUILD_VERSION = 0x32, |
| 1045 | |||
| 1046 | _, | ||
| 1047 | }; | ||
| 1038 | 1048 | ||
| 1039 | /// the mach magic number | 1049 | /// the mach magic number |
| 1040 | pub const MH_MAGIC = 0xfeedface; | 1050 | pub 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) { |
| 1537 | 1547 | ||
| 1538 | pub const reloc_type_arm64 = enum(u4) { | 1548 | pub const reloc_type_arm64 = enum(u4) { |
| 1539 | /// For pointers. | 1549 | /// For pointers. |
| 1540 | ARM64_RELOC_UNSIGNED, | 1550 | ARM64_RELOC_UNSIGNED = 0, |
| 1541 | 1551 | ||
| 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); |
| 1841 | 1851 | ||
| 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 | } |
| 1906 | 1916 | ||
| 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 | )); |
| 2079 | 2089 | ||
| 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, // stacksize | 2237 | 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, |
| 130 | tlv_section_index: ?u16 = null, | 130 | tlv_section_index: ?u16 = null, |
| 131 | tlv_data_section_index: ?u16 = null, | 131 | tlv_data_section_index: ?u16 = null, |
| 132 | tlv_bss_section_index: ?u16 = null, | 132 | tlv_bss_section_index: ?u16 = null, |
| 133 | tlv_ptrs_section_index: ?u16 = null, | ||
| 133 | la_symbol_ptr_section_index: ?u16 = null, | 134 | la_symbol_ptr_section_index: ?u16 = null, |
| 134 | data_section_index: ?u16 = null, | 135 | data_section_index: ?u16 = null, |
| 135 | bss_section_index: ?u16 = null, | 136 | bss_section_index: ?u16 = null, |
| ... | @@ -164,6 +165,9 @@ stub_helper_preamble_atom: ?*Atom = null, | ... | @@ -164,6 +165,9 @@ stub_helper_preamble_atom: ?*Atom = null, |
| 164 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 165 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 165 | strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, | 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 | got_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{}, | 171 | got_entries_map: std.AutoArrayHashMapUnmanaged(Atom.Relocation.Target, *Atom) = .{}, |
| 168 | got_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{}, | 172 | got_entries_map_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 169 | 173 | ||
| ... | @@ -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 | } |
| 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 | fn createDyldPrivateAtom(self: *MachO) !void { | 2185 | fn 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); |
| 2168 | 2207 | ||
| 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); |
| 2302 | 2341 | ||
| 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 | } |
| 2520 | 2559 | ||
| ... | @@ -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 | } |
| 2573 | 2612 | ||
| ... | @@ -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); |
| 2917 | 2956 | ||
| 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); |
| 2977 | 3016 | ||
| 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 | } |
| 3216 | 3255 | ||
| 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 { |
| 4480 | 4515 | ||
| 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 | } |
| 4491 | 4549 | ||
| 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 | } |
| 4836 | 4894 | ||
| 4837 | fn addAtomAndBumpSectionSize(self: *MachO, atom: *Atom, match: MatchingSection) !void { | 4895 | fn 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 | } |
| 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 | 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 | } |
| 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 | fn addGotEntry(target: Relocation.Target, context: RelocContext) !void { | 587 | fn 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; |
| 536 | 589 | ||
| ... | @@ -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_value | 798 | macho_file.locals.items[atom.local_sym_index].n_value |
| 745 | else | 799 | 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 |
| 122 | 122 | ||
| 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 |
| 302 | 302 | ||
| 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 @@ | ||
| 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 | } | ||