| ... | @@ -2082,10 +2082,7 @@ fn loadObject( | ... | @@ -2082,10 +2082,7 @@ fn loadObject( |
| 2082 | | 2082 | |
| 2083 | const ii: Node.InputIndex = @enumFromInt(elf.inputs.items.len); | 2083 | const ii: Node.InputIndex = @enumFromInt(elf.inputs.items.len); |
| 2084 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) }); | 2084 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) }); |
| 2085 | const ident = try r.peek(std.elf.EI.OSABI); | 2085 | try elf.checkInputIdent(path, r); |
| 2086 | if (!std.mem.eql(u8, ident[0..std.elf.MAGIC.len], std.elf.MAGIC)) return error.BadMagic; | | |
| 2087 | if (!std.mem.eql(u8, ident[std.elf.MAGIC.len..], elf.mf.memory_map.memory[std.elf.MAGIC.len..ident.len])) | | |
| 2088 | return diags.failParse(path, "bad ident", .{}); | | |
| 2089 | try elf.symtab.ensureUnusedCapacity(gpa, 1); | 2086 | try elf.symtab.ensureUnusedCapacity(gpa, 1); |
| 2090 | try elf.inputs.ensureUnusedCapacity(gpa, 1); | 2087 | try elf.inputs.ensureUnusedCapacity(gpa, 1); |
| 2091 | elf.inputs.addOneAssumeCapacity().* = .{ | 2088 | elf.inputs.addOneAssumeCapacity().* = .{ |
| ... | @@ -2321,10 +2318,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { | ... | @@ -2321,10 +2318,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { |
| 2321 | const r = &fr.interface; | 2318 | const r = &fr.interface; |
| 2322 | | 2319 | |
| 2323 | log.debug("loadDso({f})", .{path.fmtEscapeString()}); | 2320 | log.debug("loadDso({f})", .{path.fmtEscapeString()}); |
| 2324 | const ident = try r.peek(std.elf.EI.NIDENT); | 2321 | try elf.checkInputIdent(path, r); |
| 2325 | if (!std.mem.eql(u8, ident[0..std.elf.MAGIC.len], std.elf.MAGIC)) return error.BadMagic; | | |
| 2326 | if (!std.mem.eql(u8, ident[std.elf.MAGIC.len..], elf.mf.memory_map.memory[std.elf.MAGIC.len..ident.len])) | | |
| 2327 | return diags.failParse(path, "bad ident", .{}); | | |
| 2328 | const target_endian = elf.targetEndian(); | 2322 | const target_endian = elf.targetEndian(); |
| 2329 | switch (elf.identClass()) { | 2323 | switch (elf.identClass()) { |
| 2330 | .NONE, _ => unreachable, | 2324 | .NONE, _ => unreachable, |
| ... | @@ -2395,6 +2389,59 @@ fn loadDsoExact(elf: *Elf, name: []const u8) !void { | ... | @@ -2395,6 +2389,59 @@ fn loadDsoExact(elf: *Elf, name: []const u8) !void { |
| 2395 | try elf.needed.put(elf.base.comp.gpa, try elf.string(.dynstr, name), {}); | 2389 | try elf.needed.put(elf.base.comp.gpa, try elf.string(.dynstr, name), {}); |
| 2396 | } | 2390 | } |
| 2397 | | 2391 | |
| | 2392 | /// Validates that the `std.elf.Ident` present at the start of `r` is a compatible link input. |
| | 2393 | /// |
| | 2394 | /// Returns an error if it is incompatible, or if the ident is broken or missing. |
| | 2395 | /// |
| | 2396 | /// Does not advance the position of `r`. Requires `r` to have a 16-byte buffer. |
| | 2397 | fn checkInputIdent( |
| | 2398 | elf: *const Elf, |
| | 2399 | path: std.Build.Cache.Path, |
| | 2400 | r: *Io.Reader, |
| | 2401 | ) !void { |
| | 2402 | const diags = &elf.base.comp.link_diags; |
| | 2403 | |
| | 2404 | const ident = try r.peekStructPointer(std.elf.Ident); |
| | 2405 | const target: *const std.elf.Ident = @ptrCast(elf.mf.memory_map.memory[0..@sizeOf(std.elf.Ident)]); |
| | 2406 | |
| | 2407 | if (!std.mem.eql(u8, &ident.magic, std.elf.MAGIC)) { |
| | 2408 | return error.BadMagic; |
| | 2409 | } |
| | 2410 | |
| | 2411 | if (ident.class != target.class) return diags.failParse( |
| | 2412 | path, |
| | 2413 | "bad ELF class ({?s})", |
| | 2414 | .{std.enums.tagName(std.elf.CLASS, ident.class)}, |
| | 2415 | ); |
| | 2416 | if (ident.data != target.data) return diags.failParse( |
| | 2417 | path, |
| | 2418 | "bad ELF data encoding ({?s})", |
| | 2419 | .{std.enums.tagName(std.elf.DATA, ident.data)}, |
| | 2420 | ); |
| | 2421 | if (ident.version != target.version) return diags.failParse( |
| | 2422 | path, |
| | 2423 | "bad ELF version ({d})", |
| | 2424 | .{ident.version}, |
| | 2425 | ); |
| | 2426 | |
| | 2427 | // OSABI is a bit more complex. On Linux, `.NONE` and `.GNU` are both valid and both common. |
| | 2428 | // It sounds reasonable to allow the value we chose *and* allow `.NONE`. |
| | 2429 | const expect_abiversion: u8 = abiver: { |
| | 2430 | if (ident.osabi == .NONE) break :abiver 0; |
| | 2431 | if (ident.osabi == target.osabi) break :abiver target.abiversion; |
| | 2432 | return diags.failParse( |
| | 2433 | path, |
| | 2434 | "bad ELF OS/ABI ({?s})", |
| | 2435 | .{std.enums.tagName(std.elf.OSABI, ident.osabi)}, |
| | 2436 | ); |
| | 2437 | }; |
| | 2438 | if (ident.abiversion != expect_abiversion) return diags.failParse( |
| | 2439 | path, |
| | 2440 | "bad ELF ABI version ({d})", |
| | 2441 | .{ident.abiversion}, |
| | 2442 | ); |
| | 2443 | } |
| | 2444 | |
| 2398 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { | 2445 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { |
| 2399 | _ = prog_node; | 2446 | _ = prog_node; |
| 2400 | elf.prelinkInner() catch |err| switch (err) { | 2447 | elf.prelinkInner() catch |err| switch (err) { |