| ... | ... | @@ -1268,62 +1268,29 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || |
| 1268 | 1268 | switch (input) { |
| 1269 | 1269 | else => {}, |
| 1270 | 1270 | .object => |object| { |
| 1271 | | var fsr: FileSliceReader = .init(object.file.reader(io, &.{})); |
| 1272 | | fsr.reset(try fsr.file.getSize(), &buf); |
| 1273 | | elf.loadObject(object.path, null, &fsr) catch |err| switch (err) { |
| 1274 | | error.ReadFailed => return fsr.file.err.?, |
| 1271 | var fr = object.file.reader(io, &buf); |
| 1272 | elf.loadObject(object.path, null, &fr, .{ |
| 1273 | .offset = fr.logicalPos(), |
| 1274 | .size = try fr.getSize(), |
| 1275 | }) catch |err| switch (err) { |
| 1276 | error.ReadFailed => return fr.err.?, |
| 1275 | 1277 | else => |e| return e, |
| 1276 | 1278 | }; |
| 1277 | 1279 | }, |
| 1278 | 1280 | .archive => |archive| { |
| 1279 | | var fsr: FileSliceReader = .init(archive.file.reader(io, &buf)); |
| 1280 | | elf.loadArchive(archive.path, &fsr) catch |err| switch (err) { |
| 1281 | | error.ReadFailed => return fsr.file.err.?, |
| 1281 | var fr = archive.file.reader(io, &buf); |
| 1282 | elf.loadArchive(archive.path, &fr) catch |err| switch (err) { |
| 1283 | error.ReadFailed => return fr.err.?, |
| 1282 | 1284 | else => |e| return e, |
| 1283 | 1285 | }; |
| 1284 | 1286 | }, |
| 1285 | 1287 | } |
| 1286 | 1288 | } |
| 1287 | | const FileSliceReader = struct { |
| 1288 | | file: std.Io.File.Reader, |
| 1289 | | file_location: MappedFile.Node.FileLocation, |
| 1290 | | reader: std.Io.Reader.Limited, |
| 1291 | | |
| 1292 | | pub fn init(file: std.Io.File.Reader) FileSliceReader { |
| 1293 | | return .{ .file = file, .file_location = undefined, .reader = undefined }; |
| 1294 | | } |
| 1295 | | |
| 1296 | | pub fn reset(fsr: *FileSliceReader, size: u64, buffer: []u8) void { |
| 1297 | | fsr.file_location = .{ |
| 1298 | | .offset = fsr.file.logicalPos(), |
| 1299 | | .size = size, |
| 1300 | | }; |
| 1301 | | fsr.reader = .init(&fsr.file.interface, .limited(@intCast(size)), buffer); |
| 1302 | | } |
| 1303 | | |
| 1304 | | pub fn pos(fsr: *const FileSliceReader) u64 { |
| 1305 | | return fsr.file.logicalPos() - fsr.file_location.offset; |
| 1306 | | } |
| 1307 | | |
| 1308 | | pub fn logicalPos(fsr: *const FileSliceReader) u64 { |
| 1309 | | return fsr.pos() - fsr.reader.interface.bufferedLen(); |
| 1310 | | } |
| 1311 | | |
| 1312 | | pub fn seekTo(fsr: *FileSliceReader, offset: u64) std.Io.File.Reader.SeekError!void { |
| 1313 | | if (offset > fsr.file_location.size) return error.EndOfStream; |
| 1314 | | const logical_pos = fsr.logicalPos(); |
| 1315 | | if (offset < logical_pos or offset >= fsr.pos()) { |
| 1316 | | fsr.reader.interface.tossBuffered(); |
| 1317 | | try fsr.file.seekTo(fsr.file_location.offset + offset); |
| 1318 | | fsr.reader.remaining = .limited(@intCast(fsr.file_location.size - offset)); |
| 1319 | | } else fsr.reader.interface.toss(@intCast(offset - logical_pos)); |
| 1320 | | } |
| 1321 | | }; |
| 1322 | | fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fsr: *FileSliceReader) !void { |
| 1289 | fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { |
| 1323 | 1290 | const comp = elf.base.comp; |
| 1324 | 1291 | const gpa = comp.gpa; |
| 1325 | 1292 | const diags = &comp.link_diags; |
| 1326 | | const r = &fsr.file.interface; |
| 1293 | const r = &fr.interface; |
| 1327 | 1294 | |
| 1328 | 1295 | log.debug("loadArchive({f})", .{path.fmtEscapeString()}); |
| 1329 | 1296 | if (!std.mem.eql(u8, try r.take(std.elf.ARMAG.len), std.elf.ARMAG)) |
| ... | ... | @@ -1333,6 +1300,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fsr: *FileSliceReader) !vo |
| 1333 | 1300 | while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| { |
| 1334 | 1301 | if (!std.mem.eql(u8, &header.ar_fmag, std.elf.ARFMAG)) |
| 1335 | 1302 | return diags.failParse(path, "bad file magic", .{}); |
| 1303 | const offset = fr.logicalPos(); |
| 1336 | 1304 | const size = header.size() catch |
| 1337 | 1305 | return diags.failParse(path, "bad member size", .{}); |
| 1338 | 1306 | if (std.mem.eql(u8, &header.ar_name, std.elf.STRNAME)) { |
| ... | ... | @@ -1361,15 +1329,11 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fsr: *FileSliceReader) !vo |
| 1361 | 1329 | error.Overflow => return diags.failParse(path, "bad member name offset", .{}), |
| 1362 | 1330 | }; |
| 1363 | 1331 | if (!std.mem.endsWith(u8, member, ".o")) break :load_object; |
| 1364 | | var buf: [4096]u8 = undefined; |
| 1365 | | fsr.reset(size, &buf); |
| 1366 | | try elf.loadObject(path, member, fsr); |
| 1367 | | try fsr.seekTo(size); |
| 1368 | | continue; |
| 1332 | try elf.loadObject(path, member, fr, .{ .offset = offset, .size = size }); |
| 1369 | 1333 | } |
| 1370 | | try r.discardAll(size); |
| 1334 | try fr.seekTo(std.mem.alignForward(u64, offset + size, 2)); |
| 1371 | 1335 | } else |err| switch (err) { |
| 1372 | | error.EndOfStream => if (!fsr.file.atEnd()) return error.EndOfStream, |
| 1336 | error.EndOfStream => if (!fr.atEnd()) return error.EndOfStream, |
| 1373 | 1337 | else => |e| return e, |
| 1374 | 1338 | } |
| 1375 | 1339 | } |
| ... | ... | @@ -1379,11 +1343,17 @@ fn fmtMemberString(member: ?[]const u8) std.fmt.Alt(?[]const u8, memberStringEsc |
| 1379 | 1343 | fn memberStringEscape(member: ?[]const u8, w: *std.Io.Writer) std.Io.Writer.Error!void { |
| 1380 | 1344 | try w.print("({f})", .{std.zig.fmtString(member orelse return)}); |
| 1381 | 1345 | } |
| 1382 | | fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: *FileSliceReader) !void { |
| 1346 | fn loadObject( |
| 1347 | elf: *Elf, |
| 1348 | path: std.Build.Cache.Path, |
| 1349 | member: ?[]const u8, |
| 1350 | fr: *std.Io.File.Reader, |
| 1351 | fl: MappedFile.Node.FileLocation, |
| 1352 | ) !void { |
| 1383 | 1353 | const comp = elf.base.comp; |
| 1384 | 1354 | const gpa = comp.gpa; |
| 1385 | 1355 | const diags = &comp.link_diags; |
| 1386 | | const r = &fsr.reader.interface; |
| 1356 | const r = &fr.interface; |
| 1387 | 1357 | |
| 1388 | 1358 | const ii: Node.InputIndex = @enumFromInt(elf.inputs.items.len); |
| 1389 | 1359 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) }); |
| ... | ... | @@ -1411,11 +1381,13 @@ fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: * |
| 1411 | 1381 | if (ehdr.machine != elf.ehdrField(.machine)) |
| 1412 | 1382 | return diags.failParse(path, "bad machine", .{}); |
| 1413 | 1383 | if (ehdr.shoff == 0 or ehdr.shnum <= 1) return; |
| 1384 | if (ehdr.shoff + ehdr.shentsize * ehdr.shnum > fl.size) |
| 1385 | return diags.failParse(path, "bad section header offset/size", .{}); |
| 1414 | 1386 | if (ehdr.shentsize < @sizeOf(ElfN.Shdr)) |
| 1415 | 1387 | return diags.failParse(path, "unsupported shentsize", .{}); |
| 1416 | 1388 | const sections = try gpa.alloc(struct { shdr: ElfN.Shdr, si: Symbol.Index }, ehdr.shnum); |
| 1417 | 1389 | defer gpa.free(sections); |
| 1418 | | try fsr.seekTo(ehdr.shoff); |
| 1390 | try fr.seekTo(fl.offset + ehdr.shoff); |
| 1419 | 1391 | for (sections) |*section| { |
| 1420 | 1392 | section.* = .{ |
| 1421 | 1393 | .shdr = try r.peekStruct(ElfN.Shdr, target_endian), |
| ... | ... | @@ -1424,7 +1396,7 @@ fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: * |
| 1424 | 1396 | try r.discardAll(ehdr.shentsize); |
| 1425 | 1397 | switch (section.shdr.type) { |
| 1426 | 1398 | std.elf.SHT_NULL, std.elf.SHT_NOBITS => {}, |
| 1427 | | else => if (section.shdr.offset + section.shdr.size > fsr.file_location.size) |
| 1399 | else => if (section.shdr.offset + section.shdr.size > fl.size) |
| 1428 | 1400 | return diags.failParse(path, "bad section offset/size", .{}), |
| 1429 | 1401 | } |
| 1430 | 1402 | } |
| ... | ... | @@ -1436,7 +1408,7 @@ fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: * |
| 1436 | 1408 | return diags.failParse(path, "invalid shstrtab type", .{}); |
| 1437 | 1409 | const shstrtab = try gpa.alloc(u8, @intCast(shdr.size)); |
| 1438 | 1410 | errdefer gpa.free(shstrtab); |
| 1439 | | try fsr.seekTo(shdr.offset); |
| 1411 | try fr.seekTo(fl.offset + shdr.offset); |
| 1440 | 1412 | try r.readSliceAll(shstrtab); |
| 1441 | 1413 | break :shstrtab shstrtab; |
| 1442 | 1414 | }; |
| ... | ... | @@ -1470,7 +1442,7 @@ fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: * |
| 1470 | 1442 | .ii = ii, |
| 1471 | 1443 | .si = section.si, |
| 1472 | 1444 | .file_location = .{ |
| 1473 | | .offset = fsr.file_location.offset + section.shdr.offset, |
| 1445 | .offset = fl.offset + section.shdr.offset, |
| 1474 | 1446 | .size = section.shdr.size, |
| 1475 | 1447 | }, |
| 1476 | 1448 | }; |
| ... | ... | @@ -1492,7 +1464,7 @@ fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: * |
| 1492 | 1464 | return diags.failParse(path, "invalid strtab type", .{}); |
| 1493 | 1465 | const strtab = try gpa.alloc(u8, @intCast(shdr.size)); |
| 1494 | 1466 | errdefer gpa.free(strtab); |
| 1495 | | try fsr.seekTo(shdr.offset); |
| 1467 | try fr.seekTo(fl.offset + shdr.offset); |
| 1496 | 1468 | try r.readSliceAll(strtab); |
| 1497 | 1469 | break :strtab strtab; |
| 1498 | 1470 | }; |
| ... | ... | @@ -1507,12 +1479,11 @@ fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: * |
| 1507 | 1479 | .{ symtab.shdr.size, symtab.shdr.entsize }, |
| 1508 | 1480 | ); |
| 1509 | 1481 | symmap.clearRetainingCapacity(); |
| 1510 | | try symmap.resize(gpa, symnum); |
| 1482 | try symmap.resize(gpa, std.math.sub(u32, symnum, 1) catch continue); |
| 1511 | 1483 | try elf.symtab.ensureUnusedCapacity(gpa, symnum); |
| 1512 | 1484 | try elf.globals.ensureUnusedCapacity(gpa, symnum); |
| 1513 | | try fsr.seekTo(symtab.shdr.offset + symtab.shdr.entsize); |
| 1514 | | symmap.items[0] = .null; |
| 1515 | | for (symmap.items[1..]) |*si| { |
| 1485 | try fr.seekTo(fl.offset + symtab.shdr.offset + symtab.shdr.entsize); |
| 1486 | for (symmap.items) |*si| { |
| 1516 | 1487 | si.* = .null; |
| 1517 | 1488 | const input_sym = try r.peekStruct(ElfN.Sym, target_endian); |
| 1518 | 1489 | try r.discardAll64(symtab.shdr.entsize); |
| ... | ... | @@ -1594,12 +1565,12 @@ fn loadObject(elf: *Elf, path: std.Build.Cache.Path, member: ?[]const u8, fsr: * |
| 1594 | 1565 | .{ rels.shdr.size, rels.shdr.entsize }, |
| 1595 | 1566 | ); |
| 1596 | 1567 | try elf.relocs.ensureUnusedCapacity(gpa, relnum); |
| 1597 | | try fsr.seekTo(rels.shdr.offset); |
| 1568 | try fr.seekTo(fl.offset + rels.shdr.offset); |
| 1598 | 1569 | for (0..relnum) |_| { |
| 1599 | 1570 | const rel = try r.peekStruct(Rel, target_endian); |
| 1600 | 1571 | try r.discardAll64(rels.shdr.entsize); |
| 1601 | 1572 | if (rel.info.sym >= symnum) continue; |
| 1602 | | const target_si = symmap.items[rel.info.sym]; |
| 1573 | const target_si = symmap.items[rel.info.sym - 1]; |
| 1603 | 1574 | if (target_si == .null) continue; |
| 1604 | 1575 | elf.addRelocAssumeCapacity( |
| 1605 | 1576 | loc_sec.si, |