authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-27 16:38:10-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-28 14:51:55-05:00
log60f2f3457dd73772e7cd60bf5d90358079361d11
treed86ce4af1ccd7ecc12cfb59507e38900f046331e
parent662b5f7c6045ba857d0d9abd72350a82f0b7ddf3
signaturelock-open Commit is signed but in an unrecognized format.

getStandardDynamicLinkerPath renamed and no allocator

* `std.Target.getStandardDynamicLinkerPath` => `std.Target.standardDynamicLinkerPath` * it now takes a pointer to fixed size array rather than an allocator * `std.zig.system.NativeTargetInfo.detect` now supports reading PT_INTERP from /usr/bin/env

3 files changed, 158 insertions(+), 113 deletions(-)

lib/std/target.zig+71-69
...@@ -1084,65 +1084,59 @@ pub const Target = struct {...@@ -1084,65 +1084,59 @@ pub const Target = struct {
1084 }1084 }
1085 }1085 }
10861086
1087 /// Caller owns returned memory.1087 /// The result will be a slice of `buffer`, pointing at position 0.
1088 pub fn getStandardDynamicLinkerPath(1088 /// A return value of `null` means the concept of a dynamic linker is not meaningful for that target.
1089 self: Target,1089 pub fn standardDynamicLinkerPath(self: Target, buffer: *[255]u8) ?[]u8 {
1090 allocator: *mem.Allocator,1090 const S = struct {
1091 ) error{1091 fn print(b: *[255]u8, comptime fmt: []const u8, args: var) []u8 {
1092 OutOfMemory,1092 return std.fmt.bufPrint(b, fmt, args) catch unreachable;
1093 UnknownDynamicLinkerPath,1093 }
1094 TargetHasNoDynamicLinker,1094 fn copy(b: *[255]u8, s: []const u8) []u8 {
1095 }![:0]u8 {1095 mem.copy(u8, b, s);
1096 const a = allocator;1096 return b[0..s.len];
1097 }
1098 };
1099 const print = S.print;
1100 const copy = S.copy;
1101
1097 if (self.isAndroid()) {1102 if (self.isAndroid()) {
1098 return mem.dupeZ(a, u8, if (self.cpu.arch.ptrBitWidth() == 64)1103 const suffix = if (self.cpu.arch.ptrBitWidth() == 64) "64" else "";
1099 "/system/bin/linker64"1104 return print(buffer, "/system/bin/linker{}", .{suffix});
1100 else
1101 "/system/bin/linker");
1102 }1105 }
11031106
1104 if (self.isMusl()) {1107 if (self.isMusl()) {
1105 var result = try std.Buffer.init(allocator, "/lib/ld-musl-");1108 const is_arm = switch (self.cpu.arch) {
1106 defer result.deinit();1109 .arm, .armeb, .thumb, .thumbeb => true,
11071110 else => false,
1108 var is_arm = false;1111 };
1109 switch (self.cpu.arch) {1112 const arch_part = switch (self.cpu.arch) {
1110 .arm, .thumb => {1113 .arm, .thumb => "arm",
1111 try result.append("arm");1114 .armeb, .thumbeb => "armeb",
1112 is_arm = true;1115 else => |arch| @tagName(arch),
1113 },1116 };
1114 .armeb, .thumbeb => {1117 const arch_suffix = if (is_arm and self.getFloatAbi() == .hard) "hf" else "";
1115 try result.append("armeb");1118 return print(buffer, "/lib/ld-musl-{}{}.so.1", .{ arch_part, arch_suffix });
1116 is_arm = true;
1117 },
1118 else => |arch| try result.append(@tagName(arch)),
1119 }
1120 if (is_arm and self.getFloatAbi() == .hard) {
1121 try result.append("hf");
1122 }
1123 try result.append(".so.1");
1124 return result.toOwnedSlice();
1125 }1119 }
11261120
1127 switch (self.os.tag) {1121 switch (self.os.tag) {
1128 .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"),1122 .freebsd => return copy(buffer, "/libexec/ld-elf.so.1"),
1129 .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"),1123 .netbsd => return copy(buffer, "/libexec/ld.elf_so"),
1130 .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"),1124 .dragonfly => return copy(buffer, "/libexec/ld-elf.so.2"),
1131 .linux => switch (self.cpu.arch) {1125 .linux => switch (self.cpu.arch) {
1132 .i386,1126 .i386,
1133 .sparc,1127 .sparc,
1134 .sparcel,1128 .sparcel,
1135 => return mem.dupeZ(a, u8, "/lib/ld-linux.so.2"),1129 => return copy(buffer, "/lib/ld-linux.so.2"),
11361130
1137 .aarch64 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64.so.1"),1131 .aarch64 => return copy(buffer, "/lib/ld-linux-aarch64.so.1"),
1138 .aarch64_be => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_be.so.1"),1132 .aarch64_be => return copy(buffer, "/lib/ld-linux-aarch64_be.so.1"),
1139 .aarch64_32 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_32.so.1"),1133 .aarch64_32 => return copy(buffer, "/lib/ld-linux-aarch64_32.so.1"),
11401134
1141 .arm,1135 .arm,
1142 .armeb,1136 .armeb,
1143 .thumb,1137 .thumb,
1144 .thumbeb,1138 .thumbeb,
1145 => return mem.dupeZ(a, u8, switch (self.getFloatAbi()) {1139 => return copy(buffer, switch (self.getFloatAbi()) {
1146 .hard => "/lib/ld-linux-armhf.so.3",1140 .hard => "/lib/ld-linux-armhf.so.3",
1147 else => "/lib/ld-linux.so.3",1141 else => "/lib/ld-linux.so.3",
1148 }),1142 }),
...@@ -1159,29 +1153,35 @@ pub const Target = struct {...@@ -1159,29 +1153,35 @@ pub const Target = struct {
1159 };1153 };
1160 const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008);1154 const is_nan_2008 = mips.featureSetHas(self.cpu.features, .nan2008);
1161 const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";1155 const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";
1162 return std.fmt.allocPrint0(a, "/lib{}/{}", .{ lib_suffix, loader });1156 return print(buffer, "/lib{}/{}", .{ lib_suffix, loader });
1163 },1157 },
11641158
1165 .powerpc => return mem.dupeZ(a, u8, "/lib/ld.so.1"),1159 .powerpc => return copy(buffer, "/lib/ld.so.1"),
1166 .powerpc64, .powerpc64le => return mem.dupeZ(a, u8, "/lib64/ld64.so.2"),1160 .powerpc64, .powerpc64le => return copy(buffer, "/lib64/ld64.so.2"),
1167 .s390x => return mem.dupeZ(a, u8, "/lib64/ld64.so.1"),1161 .s390x => return copy(buffer, "/lib64/ld64.so.1"),
1168 .sparcv9 => return mem.dupeZ(a, u8, "/lib64/ld-linux.so.2"),1162 .sparcv9 => return copy(buffer, "/lib64/ld-linux.so.2"),
1169 .x86_64 => return mem.dupeZ(a, u8, switch (self.abi) {1163 .x86_64 => return copy(buffer, switch (self.abi) {
1170 .gnux32 => "/libx32/ld-linux-x32.so.2",1164 .gnux32 => "/libx32/ld-linux-x32.so.2",
1171 else => "/lib64/ld-linux-x86-64.so.2",1165 else => "/lib64/ld-linux-x86-64.so.2",
1172 }),1166 }),
11731167
1174 .riscv32 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv32-ilp32.so.1"),1168 .riscv32 => return copy(buffer, "/lib/ld-linux-riscv32-ilp32.so.1"),
1175 .riscv64 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv64-lp64.so.1"),1169 .riscv64 => return copy(buffer, "/lib/ld-linux-riscv64-lp64.so.1"),
11761170
1171 // Architectures in this list have been verified as not having a standard
1172 // dynamic linker path.
1177 .wasm32,1173 .wasm32,
1178 .wasm64,1174 .wasm64,
1179 => return error.TargetHasNoDynamicLinker,1175 .bpfel,
1176 .bpfeb,
1177 .nvptx,
1178 .nvptx64,
1179 => return null,
11801180
1181 // TODO go over each item in this list and either move it to the above list, or
1182 // implement the standard dynamic linker path code for it.
1181 .arc,1183 .arc,
1182 .avr,1184 .avr,
1183 .bpfel,
1184 .bpfeb,
1185 .hexagon,1185 .hexagon,
1186 .msp430,1186 .msp430,
1187 .r600,1187 .r600,
...@@ -1189,8 +1189,6 @@ pub const Target = struct {...@@ -1189,8 +1189,6 @@ pub const Target = struct {
1189 .tce,1189 .tce,
1190 .tcele,1190 .tcele,
1191 .xcore,1191 .xcore,
1192 .nvptx,
1193 .nvptx64,
1194 .le32,1192 .le32,
1195 .le64,1193 .le64,
1196 .amdil,1194 .amdil,
...@@ -1204,9 +1202,25 @@ pub const Target = struct {...@@ -1204,9 +1202,25 @@ pub const Target = struct {
1204 .lanai,1202 .lanai,
1205 .renderscript32,1203 .renderscript32,
1206 .renderscript64,1204 .renderscript64,
1207 => return error.UnknownDynamicLinkerPath,1205 => return null,
1208 },1206 },
12091207
1208 // Operating systems in this list have been verified as not having a standard
1209 // dynamic linker path.
1210 .freestanding,
1211 .ios,
1212 .tvos,
1213 .watchos,
1214 .macosx,
1215 .uefi,
1216 .windows,
1217 .emscripten,
1218 .other,
1219 .wasi,
1220 => return null,
1221
1222 // TODO go over each item in this list and either move it to the above list, or
1223 // implement the standard dynamic linker path code for it.
1210 .ananas,1224 .ananas,
1211 .cloudabi,1225 .cloudabi,
1212 .fuchsia,1226 .fuchsia,
...@@ -1230,19 +1244,7 @@ pub const Target = struct {...@@ -1230,19 +1244,7 @@ pub const Target = struct {
1230 .amdpal,1244 .amdpal,
1231 .hermit,1245 .hermit,
1232 .hurd,1246 .hurd,
1233 => return error.UnknownDynamicLinkerPath,1247 => return null,
1234
1235 .freestanding,
1236 .ios,
1237 .tvos,
1238 .watchos,
1239 .macosx,
1240 .uefi,
1241 .windows,
1242 .emscripten,
1243 .other,
1244 .wasi,
1245 => return error.TargetHasNoDynamicLinker,
1246 }1248 }
1247 }1249 }
1248};1250};
lib/std/zig/system.zig+80-35
...@@ -167,7 +167,15 @@ pub const NativePaths = struct {...@@ -167,7 +167,15 @@ pub const NativePaths = struct {
167167
168pub const NativeTargetInfo = struct {168pub const NativeTargetInfo = struct {
169 target: Target,169 target: Target,
170 dynamic_linker: ?[:0]u8,170
171 /// Contains the memory used to store the dynamic linker path. This field should
172 /// not be used directly. See `dynamicLinker` and `setDynamicLinker`. This field
173 /// exists so that this API requires no allocator.
174 dynamic_linker_buffer: [255]u8 = undefined,
175
176 /// Used to construct the dynamic linker path. This field should not be used
177 /// directly. See `dynamicLinker` and `setDynamicLinker`.
178 dynamic_linker_max: ?u8 = null,
171179
172 pub const DetectError = error{180 pub const DetectError = error{
173 OutOfMemory,181 OutOfMemory,
...@@ -181,6 +189,7 @@ pub const NativeTargetInfo = struct {...@@ -181,6 +189,7 @@ pub const NativeTargetInfo = struct {
181189
182 /// Detects the native CPU model & features, operating system & version, and C ABI & dynamic linker.190 /// Detects the native CPU model & features, operating system & version, and C ABI & dynamic linker.
183 /// On Linux, this is additionally responsible for detecting the native glibc version when applicable.191 /// On Linux, this is additionally responsible for detecting the native glibc version when applicable.
192 /// TODO Remove the allocator requirement from this.
184 pub fn detect(allocator: *Allocator) DetectError!NativeTargetInfo {193 pub fn detect(allocator: *Allocator) DetectError!NativeTargetInfo {
185 const arch = Target.current.cpu.arch;194 const arch = Target.current.cpu.arch;
186 const os_tag = Target.current.os.tag;195 const os_tag = Target.current.os.tag;
...@@ -188,8 +197,7 @@ pub const NativeTargetInfo = struct {...@@ -188,8 +197,7 @@ pub const NativeTargetInfo = struct {
188 // TODO Detect native CPU model & features. Until that is implemented we hard code baseline.197 // TODO Detect native CPU model & features. Until that is implemented we hard code baseline.
189 const cpu = Target.Cpu.baseline(arch);198 const cpu = Target.Cpu.baseline(arch);
190199
191 // TODO Detect native operating system version. Until that is implemented we use the minimum version200 // TODO Detect native operating system version. Until that is implemented we use the default range.
192 // of the default range.
193 const os = Target.Os.defaultVersionRange(os_tag);201 const os = Target.Os.defaultVersionRange(os_tag);
194202
195 return detectAbiAndDynamicLinker(allocator, cpu, os);203 return detectAbiAndDynamicLinker(allocator, cpu, os);
...@@ -201,6 +209,21 @@ pub const NativeTargetInfo = struct {...@@ -201,6 +209,21 @@ pub const NativeTargetInfo = struct {
201 self.* = undefined;209 self.* = undefined;
202 }210 }
203211
212 /// The returned memory has the same lifetime as the `NativeTargetInfo`.
213 pub fn dynamicLinker(self: *const NativeTargetInfo) ?[]const u8 {
214 const m = self.dynamic_linker_max orelse return null;
215 return self.dynamic_linker_buffer[0 .. m + 1];
216 }
217
218 pub fn setDynamicLinker(self: *NativeTargetInfo, dl_or_null: ?[]const u8) void {
219 if (dl_or_null) |dl| {
220 mem.copy(u8, &self.dynamic_linker_buffer, dl);
221 self.dynamic_linker_max = @intCast(u8, dl.len - 1);
222 } else {
223 self.dynamic_linker_max = null;
224 }
225 }
226
204 /// First we attempt to use the executable's own binary. If it is dynamically227 /// First we attempt to use the executable's own binary. If it is dynamically
205 /// linked, then it should answer both the C ABI question and the dynamic linker question.228 /// linked, then it should answer both the C ABI question and the dynamic linker question.
206 /// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then229 /// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then
...@@ -245,10 +268,11 @@ pub const NativeTargetInfo = struct {...@@ -245,10 +268,11 @@ pub const NativeTargetInfo = struct {
245 .os = os,268 .os = os,
246 .abi = abi,269 .abi = abi,
247 };270 };
248 const standard_ld_path = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) {271 var buf: [255]u8 = undefined;
249 error.OutOfMemory => return error.OutOfMemory,272 const standard_ld_path = if (target.standardDynamicLinkerPath(&buf)) |s|
250 error.UnknownDynamicLinkerPath, error.TargetHasNoDynamicLinker => continue,273 try mem.dupe(allocator, u8, s)
251 };274 else
275 continue;
252 errdefer allocator.free(standard_ld_path);276 errdefer allocator.free(standard_ld_path);
253 try ld_info_list.append(.{277 try ld_info_list.append(.{
254 .ld_path = standard_ld_path,278 .ld_path = standard_ld_path,
...@@ -294,28 +318,29 @@ pub const NativeTargetInfo = struct {...@@ -294,28 +318,29 @@ pub const NativeTargetInfo = struct {
294 }318 }
295 }319 }
296320
297 return NativeTargetInfo{321 var result: NativeTargetInfo = .{
298 .target = .{322 .target = .{
299 .cpu = cpu,323 .cpu = cpu,
300 .os = os_adjusted,324 .os = os_adjusted,
301 .abi = found_ld_info.abi,325 .abi = found_ld_info.abi,
302 },326 },
303 .dynamic_linker = try mem.dupeZ(allocator, u8, found_ld_path),
304 };327 };
328 result.setDynamicLinker(found_ld_path);
329 return result;
305 }330 }
306331
307 // If Zig is statically linked, such as via distributed binary static builds, the above332 // If Zig is statically linked, such as via distributed binary static builds, the above
308 // trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.333 // trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
309 // Since that path is hard-coded into the shebang line of many portable scripts, it's a334 // Since that path is hard-coded into the shebang line of many portable scripts, it's a
310 // reasonably reliable path to check for.335 // reasonably reliable path to check for.
311 return abiAndDynamicLinkerFromUsrBinEnv(allocator, cpu, os) catch |err| switch (err) {336 return abiAndDynamicLinkerFromUsrBinEnv(cpu, os) catch |err| switch (err) {
312 error.OutOfMemory => return error.OutOfMemory,337 error.FileSystem,
313 error.FileSystem => return error.FileSystem,338 error.SystemResources,
314 error.SystemResources => return error.SystemResources,339 error.SymLinkLoop,
315 error.SymLinkLoop => return error.SymLinkLoop,340 error.ProcessFdQuotaExceeded,
316 error.ProcessFdQuotaExceeded => return error.ProcessFdQuotaExceeded,341 error.SystemFdQuotaExceeded,
317 error.SystemFdQuotaExceeded => return error.SystemFdQuotaExceeded,342 error.DeviceBusy,
318 error.DeviceBusy => return error.DeviceBusy,343 => |e| return e,
319344
320 error.UnableToReadElfFile,345 error.UnableToReadElfFile,
321 error.ElfNotADynamicExecutable,346 error.ElfNotADynamicExecutable,
...@@ -327,6 +352,8 @@ pub const NativeTargetInfo = struct {...@@ -327,6 +352,8 @@ pub const NativeTargetInfo = struct {
327 error.InvalidElfMagic,352 error.InvalidElfMagic,
328 error.UsrBinEnvNotAvailable,353 error.UsrBinEnvNotAvailable,
329 error.Unexpected,354 error.Unexpected,
355 error.UnexpectedEndOfFile,
356 error.NameTooLong,
330 // Finally, we fall back on the standard path.357 // Finally, we fall back on the standard path.
331 => defaultAbiAndDynamicLinker(allocator, cpu, os),358 => defaultAbiAndDynamicLinker(allocator, cpu, os),
332 };359 };
...@@ -362,11 +389,7 @@ pub const NativeTargetInfo = struct {...@@ -362,11 +389,7 @@ pub const NativeTargetInfo = struct {
362 };389 };
363 }390 }
364391
365 fn abiAndDynamicLinkerFromUsrBinEnv(392 fn abiAndDynamicLinkerFromUsrBinEnv(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
366 allocator: *Allocator,
367 cpu: Target.Cpu,
368 os: Target.Os,
369 ) !NativeTargetInfo {
370 const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {393 const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
371 error.NoSpaceLeft => unreachable,394 error.NoSpaceLeft => unreachable,
372 error.NameTooLong => unreachable,395 error.NameTooLong => unreachable,
...@@ -409,6 +432,14 @@ pub const NativeTargetInfo = struct {...@@ -409,6 +432,14 @@ pub const NativeTargetInfo = struct {
409 const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);432 const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);
410 const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);433 const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);
411434
435 var result: NativeTargetInfo = .{
436 .target = .{
437 .cpu = cpu,
438 .os = os,
439 .abi = Target.Abi.default(cpu.arch, os),
440 },
441 };
442
412 const ph_total_size = std.math.mul(u32, phentsize, phnum) catch |err| switch (err) {443 const ph_total_size = std.math.mul(u32, phentsize, phnum) catch |err| switch (err) {
413 error.Overflow => return error.InvalidElfProgramHeaders,444 error.Overflow => return error.InvalidElfProgramHeaders,
414 };445 };
...@@ -430,7 +461,22 @@ pub const NativeTargetInfo = struct {...@@ -430,7 +461,22 @@ pub const NativeTargetInfo = struct {
430 const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);461 const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);
431 switch (p_type) {462 switch (p_type) {
432 elf.PT_INTERP => {463 elf.PT_INTERP => {
433 std.debug.warn("found PT_INTERP\n", .{});464 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
465 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
466 var interp_buf: [255]u8 = undefined;
467 if (p_filesz > interp_buf.len) return error.NameTooLong;
468 var read_offset: usize = 0;
469 while (true) {
470 const len = try wrapRead(env_file.pread(
471 interp_buf[read_offset .. p_filesz - read_offset],
472 p_offset + read_offset,
473 ));
474 if (len == 0) return error.UnexpectedEndOfFile;
475 read_offset += len;
476 if (read_offset == p_filesz) break;
477 }
478 // PT_INTERP includes a null byte in p_filesz.
479 result.setDynamicLinker(interp_buf[0 .. p_filesz - 1]);
434 },480 },
435 elf.PT_DYNAMIC => {481 elf.PT_DYNAMIC => {
436 std.debug.warn("found PT_DYNAMIC\n", .{});482 std.debug.warn("found PT_DYNAMIC\n", .{});
...@@ -440,7 +486,7 @@ pub const NativeTargetInfo = struct {...@@ -440,7 +486,7 @@ pub const NativeTargetInfo = struct {
440 }486 }
441 }487 }
442488
443 return error.OutOfMemory; // TODO489 return result;
444 }490 }
445491
446 fn wrapRead(res: std.os.ReadError!usize) !usize {492 fn wrapRead(res: std.os.ReadError!usize) !usize {
...@@ -457,18 +503,17 @@ pub const NativeTargetInfo = struct {...@@ -457,18 +503,17 @@ pub const NativeTargetInfo = struct {
457 }503 }
458504
459 fn defaultAbiAndDynamicLinker(allocator: *Allocator, cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {505 fn defaultAbiAndDynamicLinker(allocator: *Allocator, cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
460 const target: Target = .{506 var result: NativeTargetInfo = .{
461 .cpu = cpu,507 .target = .{
462 .os = os,508 .cpu = cpu,
463 .abi = Target.Abi.default(cpu.arch, os),509 .os = os,
464 };510 .abi = Target.Abi.default(cpu.arch, os),
465 return @as(NativeTargetInfo, .{
466 .target = target,
467 .dynamic_linker = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) {
468 error.OutOfMemory => return error.OutOfMemory,
469 error.UnknownDynamicLinkerPath, error.TargetHasNoDynamicLinker => null,
470 },511 },
471 });512 };
513 if (result.target.standardDynamicLinkerPath(&result.dynamic_linker_buffer)) |s| {
514 result.dynamic_linker_max = @intCast(u8, s.len - 1);
515 }
516 return result;
472 }517 }
473};518};
474519
src-self-hosted/stage2.zig+7-9
...@@ -1157,9 +1157,9 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)...@@ -1157,9 +1157,9 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)
1157 if (cross_target.os_tag == null) {1157 if (cross_target.os_tag == null) {
1158 adjusted_target.os = detected_info.target.os;1158 adjusted_target.os = detected_info.target.os;
11591159
1160 if (detected_info.dynamic_linker) |dl| {1160 if (detected_info.dynamicLinker()) |dl| {
1161 have_native_dl = true;1161 have_native_dl = true;
1162 dynamic_linker_ptr.* = dl.ptr;1162 dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);
1163 }1163 }
1164 if (cross_target.abi == null) {1164 if (cross_target.abi == null) {
1165 adjusted_target.abi = detected_info.target.abi;1165 adjusted_target.abi = detected_info.target.abi;
...@@ -1169,13 +1169,11 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)...@@ -1169,13 +1169,11 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)
1169 }1169 }
1170 }1170 }
1171 if (!have_native_dl) {1171 if (!have_native_dl) {
1172 dynamic_linker_ptr.* = adjusted_target.getStandardDynamicLinkerPath(1172 var buf: [255]u8 = undefined;
1173 std.heap.c_allocator,1173 dynamic_linker_ptr.* = if (adjusted_target.standardDynamicLinkerPath(&buf)) |s|
1174 ) catch |err| switch (err) {1174 try mem.dupeZ(std.heap.c_allocator, u8, s)
1175 error.TargetHasNoDynamicLinker => null,1175 else
1176 error.UnknownDynamicLinkerPath => null,1176 null;
1177 else => |e| return e,
1178 };
1179 }1177 }
1180 return adjusted_target;1178 return adjusted_target;
1181}1179}