| author | |
| committer | |
| log | 89c2151a97ca684924c5b29c0b78367e5ed11bcd |
| tree | 7dd5e5d6fb6bbc9aa33aa02e21f41e19741f429b |
| parent | 91f2e66bf9c010bd09a41e21aeb3e7eda80dd49f |
6 files changed, 237 insertions(+), 50 deletions(-)
src/link/Elf.zig+9-7| ... | ... | @@ -1321,16 +1321,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1321 | 1321 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 1322 | 1322 | // the relocations, and commit objects to file. |
| 1323 | 1323 | if (self.zig_module_index) |index| { |
| 1324 | for (self.file(index).?.zig_module.atoms.keys()) |atom_index| { | |
| 1324 | const zig_module = self.file(index).?.zig_module; | |
| 1325 | for (zig_module.atoms.keys()) |atom_index| { | |
| 1325 | 1326 | const atom_ptr = self.atom(atom_index).?; |
| 1326 | 1327 | if (!atom_ptr.flags.alive) continue; |
| 1328 | const code = try zig_module.codeAlloc(self, atom_index); | |
| 1329 | defer gpa.free(code); | |
| 1327 | 1330 | const shdr = &self.shdrs.items[atom_ptr.outputShndx().?]; |
| 1328 | 1331 | const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; |
| 1329 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | |
| 1330 | const code = try gpa.alloc(u8, size); | |
| 1331 | defer gpa.free(code); | |
| 1332 | const amt = try self.base.file.?.preadAll(code, file_offset); | |
| 1333 | if (amt != code.len) return error.InputOutput; | |
| 1334 | 1332 | try atom_ptr.resolveRelocs(self, code); |
| 1335 | 1333 | try self.base.file.?.pwriteAll(code, file_offset); |
| 1336 | 1334 | } |
| ... | ... | @@ -1864,7 +1862,7 @@ fn writeObjects(self: *Elf) !void { |
| 1864 | 1862 | |
| 1865 | 1863 | const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; |
| 1866 | 1864 | log.debug("writing atom({d}) at 0x{x}", .{ atom_ptr.atom_index, file_offset }); |
| 1867 | const code = try atom_ptr.codeInObjectUncompressAlloc(self); | |
| 1865 | const code = try object.codeDecompressAlloc(self, atom_ptr.atom_index); | |
| 1868 | 1866 | defer gpa.free(code); |
| 1869 | 1867 | |
| 1870 | 1868 | try atom_ptr.resolveRelocs(self, code); |
| ... | ... | @@ -3905,6 +3903,10 @@ pub fn calcImageBase(self: Elf) u64 { |
| 3905 | 3903 | }; |
| 3906 | 3904 | } |
| 3907 | 3905 | |
| 3906 | pub fn isStatic(self: Elf) bool { | |
| 3907 | return self.base.options.link_mode == .Static; | |
| 3908 | } | |
| 3909 | ||
| 3908 | 3910 | pub fn isDynLib(self: Elf) bool { |
| 3909 | 3911 | return self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic; |
| 3910 | 3912 | } |
src/link/Elf/Atom.zig+152-35| ... | ... | @@ -59,38 +59,6 @@ pub fn outputShndx(self: Atom) ?u16 { |
| 59 | 59 | return self.output_section_index; |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | pub fn codeInObject(self: Atom, elf_file: *Elf) error{Overflow}![]const u8 { | |
| 63 | const object = self.file(elf_file).?.object; | |
| 64 | return object.shdrContents(self.input_section_index); | |
| 65 | } | |
| 66 | ||
| 67 | /// Returns atom's code and optionally uncompresses data if required (for compressed sections). | |
| 68 | /// Caller owns the memory. | |
| 69 | pub fn codeInObjectUncompressAlloc(self: Atom, elf_file: *Elf) ![]u8 { | |
| 70 | const gpa = elf_file.base.allocator; | |
| 71 | const data = try self.codeInObject(elf_file); | |
| 72 | const shdr = self.inputShdr(elf_file); | |
| 73 | if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { | |
| 74 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; | |
| 75 | switch (chdr.ch_type) { | |
| 76 | .ZLIB => { | |
| 77 | var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]); | |
| 78 | var zlib_stream = std.compress.zlib.decompressStream(gpa, stream.reader()) catch | |
| 79 | return error.InputOutput; | |
| 80 | defer zlib_stream.deinit(); | |
| 81 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; | |
| 82 | const decomp = try gpa.alloc(u8, size); | |
| 83 | const nread = zlib_stream.reader().readAll(decomp) catch return error.InputOutput; | |
| 84 | if (nread != decomp.len) { | |
| 85 | return error.InputOutput; | |
| 86 | } | |
| 87 | return decomp; | |
| 88 | }, | |
| 89 | else => @panic("TODO unhandled compression scheme"), | |
| 90 | } | |
| 91 | } else return gpa.dupe(u8, data); | |
| 92 | } | |
| 93 | ||
| 94 | 62 | pub fn priority(self: Atom, elf_file: *Elf) u64 { |
| 95 | 63 | const index = self.file(elf_file).?.index(); |
| 96 | 64 | return (@as(u64, @intCast(index)) << 32) | @as(u64, @intCast(self.input_section_index)); |
| ... | ... | @@ -327,7 +295,15 @@ pub fn freeRelocs(self: Atom, elf_file: *Elf) void { |
| 327 | 295 | zig_module.relocs.items[self.relocs_section_index].clearRetainingCapacity(); |
| 328 | 296 | } |
| 329 | 297 | |
| 330 | pub fn scanRelocs(self: Atom, elf_file: *Elf, undefs: anytype) !void { | |
| 298 | pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) error{Overflow}!bool { | |
| 299 | for (try self.relocs(elf_file)) |rel| { | |
| 300 | if (rel.r_type() == elf.R_X86_64_GOTTPOFF) return true; | |
| 301 | } | |
| 302 | return false; | |
| 303 | } | |
| 304 | ||
| 305 | pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) !void { | |
| 306 | const is_dyn_lib = elf_file.isDynLib(); | |
| 331 | 307 | const file_ptr = self.file(elf_file).?; |
| 332 | 308 | const rels = try self.relocs(elf_file); |
| 333 | 309 | var i: usize = 0; |
| ... | ... | @@ -391,7 +367,38 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, undefs: anytype) !void { |
| 391 | 367 | elf.R_X86_64_TPOFF32, |
| 392 | 368 | elf.R_X86_64_TPOFF64, |
| 393 | 369 | => { |
| 394 | // if (is_shared) self.picError(symbol, rel, elf_file); | |
| 370 | if (is_dyn_lib) { | |
| 371 | // TODO | |
| 372 | // self.picError(symbol, rel, elf_file); | |
| 373 | } | |
| 374 | }, | |
| 375 | ||
| 376 | elf.R_X86_64_TLSGD => { | |
| 377 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr | |
| 378 | ||
| 379 | if (elf_file.isStatic() or | |
| 380 | (!symbol.flags.import and !is_dyn_lib)) | |
| 381 | { | |
| 382 | // Relax if building with -static flag as __tls_get_addr() will not be present in libc.a | |
| 383 | // We skip the next relocation. | |
| 384 | i += 1; | |
| 385 | } else if (!symbol.flags.import and is_dyn_lib) { | |
| 386 | symbol.flags.needs_gottp = true; | |
| 387 | i += 1; | |
| 388 | } else { | |
| 389 | symbol.flags.needs_tlsgd = true; | |
| 390 | } | |
| 391 | }, | |
| 392 | ||
| 393 | elf.R_X86_64_GOTTPOFF => { | |
| 394 | const should_relax = blk: { | |
| 395 | // if (!elf_file.options.relax or is_shared or symbol.flags.import) break :blk false; | |
| 396 | if (!x86_64.canRelaxGotTpOff(code.?[rel.r_offset - 3 ..])) break :blk false; | |
| 397 | break :blk true; | |
| 398 | }; | |
| 399 | if (!should_relax) { | |
| 400 | symbol.flags.needs_gottp = true; | |
| 401 | } | |
| 395 | 402 | }, |
| 396 | 403 | |
| 397 | 404 | else => { |
| ... | ... | @@ -446,7 +453,10 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void { |
| 446 | 453 | var stream = std.io.fixedBufferStream(code); |
| 447 | 454 | const cwriter = stream.writer(); |
| 448 | 455 | |
| 449 | for (try self.relocs(elf_file)) |rel| { | |
| 456 | const rels = try self.relocs(elf_file); | |
| 457 | var i: usize = 0; | |
| 458 | while (i < rels.len) : (i += 1) { | |
| 459 | const rel = rels[i]; | |
| 450 | 460 | const r_type = rel.r_type(); |
| 451 | 461 | if (r_type == elf.R_X86_64_NONE) continue; |
| 452 | 462 | |
| ... | ... | @@ -531,6 +541,39 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void { |
| 531 | 541 | elf.R_X86_64_TPOFF32 => try cwriter.writeIntLittle(i32, @as(i32, @truncate(S + A - TP))), |
| 532 | 542 | elf.R_X86_64_TPOFF64 => try cwriter.writeIntLittle(i64, S + A - TP), |
| 533 | 543 | |
| 544 | elf.R_X86_64_TLSGD => { | |
| 545 | if (target.flags.has_tlsgd) { | |
| 546 | // TODO | |
| 547 | // const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file))); | |
| 548 | // try cwriter.writeIntLittle(i32, @as(i32, @intCast(S_ + A - P))); | |
| 549 | } else if (target.flags.has_gottp) { | |
| 550 | // TODO | |
| 551 | // const S_ = @as(i64, @intCast(target.getGotTpAddress(elf_file))); | |
| 552 | // try relaxTlsGdToIe(relocs[i .. i + 2], @intCast(S_ - P), elf_file, &stream); | |
| 553 | i += 1; | |
| 554 | } else { | |
| 555 | try x86_64.relaxTlsGdToLe( | |
| 556 | self, | |
| 557 | rels[i .. i + 2], | |
| 558 | @as(i32, @intCast(S - TP)), | |
| 559 | elf_file, | |
| 560 | &stream, | |
| 561 | ); | |
| 562 | i += 1; | |
| 563 | } | |
| 564 | }, | |
| 565 | ||
| 566 | elf.R_X86_64_GOTTPOFF => { | |
| 567 | if (target.flags.has_gottp) { | |
| 568 | // TODO | |
| 569 | // const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file))); | |
| 570 | // try cwriter.writeIntLittle(i32, @as(i32, @intCast(S_ + A - P))); | |
| 571 | } else { | |
| 572 | x86_64.relaxGotTpOff(code[rel.r_offset - 3 ..]) catch unreachable; | |
| 573 | try cwriter.writeIntLittle(i32, @as(i32, @intCast(S - TP))); | |
| 574 | } | |
| 575 | }, | |
| 576 | ||
| 534 | 577 | else => {}, |
| 535 | 578 | } |
| 536 | 579 | } |
| ... | ... | @@ -697,6 +740,80 @@ const x86_64 = struct { |
| 697 | 740 | } |
| 698 | 741 | } |
| 699 | 742 | |
| 743 | pub fn canRelaxGotTpOff(code: []const u8) bool { | |
| 744 | const old_inst = disassemble(code) orelse return false; | |
| 745 | switch (old_inst.encoding.mnemonic) { | |
| 746 | .mov => if (Instruction.new(old_inst.prefix, .mov, &.{ | |
| 747 | old_inst.ops[0], | |
| 748 | // TODO: hack to force imm32s in the assembler | |
| 749 | .{ .imm = Immediate.s(-129) }, | |
| 750 | })) |inst| { | |
| 751 | inst.encode(std.io.null_writer, .{}) catch return false; | |
| 752 | return true; | |
| 753 | } else |_| return false, | |
| 754 | else => return false, | |
| 755 | } | |
| 756 | } | |
| 757 | ||
| 758 | pub fn relaxGotTpOff(code: []u8) !void { | |
| 759 | const old_inst = disassemble(code) orelse return error.RelaxFail; | |
| 760 | switch (old_inst.encoding.mnemonic) { | |
| 761 | .mov => { | |
| 762 | const inst = try Instruction.new(old_inst.prefix, .mov, &.{ | |
| 763 | old_inst.ops[0], | |
| 764 | // TODO: hack to force imm32s in the assembler | |
| 765 | .{ .imm = Immediate.s(-129) }, | |
| 766 | }); | |
| 767 | relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding }); | |
| 768 | encode(&.{inst}, code) catch return error.RelaxFail; | |
| 769 | }, | |
| 770 | else => return error.RelaxFail, | |
| 771 | } | |
| 772 | } | |
| 773 | ||
| 774 | pub fn relaxTlsGdToLe( | |
| 775 | self: Atom, | |
| 776 | rels: []align(1) const elf.Elf64_Rela, | |
| 777 | value: i32, | |
| 778 | elf_file: *Elf, | |
| 779 | stream: anytype, | |
| 780 | ) !void { | |
| 781 | assert(rels.len == 2); | |
| 782 | const writer = stream.writer(); | |
| 783 | switch (rels[1].r_type()) { | |
| 784 | elf.R_X86_64_PC32, | |
| 785 | elf.R_X86_64_PLT32, | |
| 786 | elf.R_X86_64_GOTPCREL, | |
| 787 | elf.R_X86_64_GOTPCRELX, | |
| 788 | => { | |
| 789 | var insts = [_]u8{ | |
| 790 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax | |
| 791 | 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax | |
| 792 | }; | |
| 793 | std.mem.writeIntLittle(i32, insts[12..][0..4], value); | |
| 794 | try stream.seekBy(-4); | |
| 795 | try writer.writeAll(&insts); | |
| 796 | relocs_log.debug(" relaxing {} and {}", .{ | |
| 797 | fmtRelocType(rels[0].r_type()), | |
| 798 | fmtRelocType(rels[1].r_type()), | |
| 799 | }); | |
| 800 | }, | |
| 801 | ||
| 802 | else => { | |
| 803 | var err = try elf_file.addErrorWithNotes(1); | |
| 804 | try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{ | |
| 805 | fmtRelocType(rels[0].r_type()), | |
| 806 | fmtRelocType(rels[1].r_type()), | |
| 807 | }); | |
| 808 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ | |
| 809 | self.file(elf_file).?.fmtPath(), | |
| 810 | self.name(elf_file), | |
| 811 | rels[0].r_offset, | |
| 812 | }); | |
| 813 | }, | |
| 814 | } | |
| 815 | } | |
| 816 | ||
| 700 | 817 | fn disassemble(code: []const u8) ?Instruction { |
| 701 | 818 | var disas = Disassembler.init(code); |
| 702 | 819 | const inst = disas.next() catch return null; |
src/link/Elf/Object.zig+40-3| ... | ... | @@ -208,6 +208,8 @@ fn getOutputSectionIndex(self: *Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) er |
| 208 | 208 | break :blk prefix; |
| 209 | 209 | } |
| 210 | 210 | } |
| 211 | if (std.mem.eql(u8, name, ".tcommon")) break :blk ".tbss"; | |
| 212 | if (std.mem.eql(u8, name, ".common")) break :blk ".bss"; | |
| 211 | 213 | break :blk name; |
| 212 | 214 | }; |
| 213 | 215 | const @"type" = switch (shdr.sh_type) { |
| ... | ... | @@ -427,7 +429,13 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 427 | 429 | const shdr = atom.inputShdr(elf_file); |
| 428 | 430 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 429 | 431 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 430 | try atom.scanRelocs(elf_file, undefs); | |
| 432 | if (try atom.scanRelocsRequiresCode(elf_file)) { | |
| 433 | // TODO ideally, we don't have to decompress at this stage (should already be done) | |
| 434 | // and we just fetch the code slice. | |
| 435 | const code = try self.codeDecompressAlloc(elf_file, atom_index); | |
| 436 | defer elf_file.base.allocator.free(code); | |
| 437 | try atom.scanRelocs(elf_file, code, undefs); | |
| 438 | } else try atom.scanRelocs(elf_file, null, undefs); | |
| 431 | 439 | } |
| 432 | 440 | |
| 433 | 441 | for (self.cies.items) |cie| { |
| ... | ... | @@ -590,7 +598,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 590 | 598 | try self.atoms.append(gpa, atom_index); |
| 591 | 599 | |
| 592 | 600 | const is_tls = global.getType(elf_file) == elf.STT_TLS; |
| 593 | const name = if (is_tls) ".tls_common" else ".common"; | |
| 601 | const name = if (is_tls) ".tbss" else ".bss"; | |
| 594 | 602 | |
| 595 | 603 | const atom = elf_file.atom(atom_index).?; |
| 596 | 604 | atom.atom_index = atom_index; |
| ... | ... | @@ -684,7 +692,7 @@ pub fn globals(self: *Object) []const Symbol.Index { |
| 684 | 692 | return self.symbols.items[start..]; |
| 685 | 693 | } |
| 686 | 694 | |
| 687 | pub fn shdrContents(self: *Object, index: u32) error{Overflow}![]const u8 { | |
| 695 | fn shdrContents(self: Object, index: u32) error{Overflow}![]const u8 { | |
| 688 | 696 | assert(index < self.shdrs.items.len); |
| 689 | 697 | const shdr = self.shdrs.items[index]; |
| 690 | 698 | const offset = math.cast(usize, shdr.sh_offset) orelse return error.Overflow; |
| ... | ... | @@ -692,6 +700,35 @@ pub fn shdrContents(self: *Object, index: u32) error{Overflow}![]const u8 { |
| 692 | 700 | return self.data[offset..][0..size]; |
| 693 | 701 | } |
| 694 | 702 | |
| 703 | /// Returns atom's code and optionally uncompresses data if required (for compressed sections). | |
| 704 | /// Caller owns the memory. | |
| 705 | pub fn codeDecompressAlloc(self: Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | |
| 706 | const gpa = elf_file.base.allocator; | |
| 707 | const atom_ptr = elf_file.atom(atom_index).?; | |
| 708 | assert(atom_ptr.file_index == self.index); | |
| 709 | const data = try self.shdrContents(atom_ptr.input_section_index); | |
| 710 | const shdr = atom_ptr.inputShdr(elf_file); | |
| 711 | if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) { | |
| 712 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; | |
| 713 | switch (chdr.ch_type) { | |
| 714 | .ZLIB => { | |
| 715 | var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]); | |
| 716 | var zlib_stream = std.compress.zlib.decompressStream(gpa, stream.reader()) catch | |
| 717 | return error.InputOutput; | |
| 718 | defer zlib_stream.deinit(); | |
| 719 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; | |
| 720 | const decomp = try gpa.alloc(u8, size); | |
| 721 | const nread = zlib_stream.reader().readAll(decomp) catch return error.InputOutput; | |
| 722 | if (nread != decomp.len) { | |
| 723 | return error.InputOutput; | |
| 724 | } | |
| 725 | return decomp; | |
| 726 | }, | |
| 727 | else => @panic("TODO unhandled compression scheme"), | |
| 728 | } | |
| 729 | } else return gpa.dupe(u8, data); | |
| 730 | } | |
| 731 | ||
| 695 | 732 | fn getString(self: *Object, off: u32) [:0]const u8 { |
| 696 | 733 | assert(off < self.strtab.len); |
| 697 | 734 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.ptr + off)), 0); |
src/link/Elf/Symbol.zig+4-2| ... | ... | @@ -327,10 +327,12 @@ pub const Flags = packed struct { |
| 327 | 327 | has_dynamic: bool = false, |
| 328 | 328 | |
| 329 | 329 | /// Whether the symbol contains TLSGD indirection. |
| 330 | tlsgd: bool = false, | |
| 330 | needs_tlsgd: bool = false, | |
| 331 | has_tlsgd: bool = false, | |
| 331 | 332 | |
| 332 | 333 | /// Whether the symbol contains GOTTP indirection. |
| 333 | gottp: bool = false, | |
| 334 | needs_gottp: bool = false, | |
| 335 | has_gottp: bool = false, | |
| 334 | 336 | |
| 335 | 337 | /// Whether the symbol contains TLSDESC indirection. |
| 336 | 338 | tlsdesc: bool = false, |
src/link/Elf/ZigModule.zig+24-1| ... | ... | @@ -144,7 +144,14 @@ pub fn scanRelocs(self: *ZigModule, elf_file: *Elf, undefs: anytype) !void { |
| 144 | 144 | for (self.atoms.keys()) |atom_index| { |
| 145 | 145 | const atom = elf_file.atom(atom_index) orelse continue; |
| 146 | 146 | if (!atom.flags.alive) continue; |
| 147 | try atom.scanRelocs(elf_file, undefs); | |
| 147 | if (try atom.scanRelocsRequiresCode(elf_file)) { | |
| 148 | // TODO ideally we don't have to fetch the code here. | |
| 149 | // Perhaps it would make sense to save the code until flushModule where we | |
| 150 | // would free all of generated code? | |
| 151 | const code = try self.codeAlloc(elf_file, atom_index); | |
| 152 | defer elf_file.base.allocator.free(code); | |
| 153 | try atom.scanRelocs(elf_file, code, undefs); | |
| 154 | } else try atom.scanRelocs(elf_file, null, undefs); | |
| 148 | 155 | } |
| 149 | 156 | } |
| 150 | 157 | |
| ... | ... | @@ -253,6 +260,22 @@ pub fn asFile(self: *ZigModule) File { |
| 253 | 260 | return .{ .zig_module = self }; |
| 254 | 261 | } |
| 255 | 262 | |
| 263 | /// Returns atom's code. | |
| 264 | /// Caller owns the memory. | |
| 265 | pub fn codeAlloc(self: ZigModule, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | |
| 266 | const gpa = elf_file.base.allocator; | |
| 267 | const atom = elf_file.atom(atom_index).?; | |
| 268 | assert(atom.file_index == self.index); | |
| 269 | const shdr = &elf_file.shdrs.items[atom.outputShndx().?]; | |
| 270 | const file_offset = shdr.sh_offset + atom.value - shdr.sh_addr; | |
| 271 | const size = std.math.cast(usize, atom.size) orelse return error.Overflow; | |
| 272 | const code = try gpa.alloc(u8, size); | |
| 273 | errdefer gpa.free(code); | |
| 274 | const amt = try elf_file.base.file.?.preadAll(code, file_offset); | |
| 275 | if (amt != code.len) return error.InputOutput; | |
| 276 | return code; | |
| 277 | } | |
| 278 | ||
| 256 | 279 | pub fn fmtSymtab(self: *ZigModule, elf_file: *Elf) std.fmt.Formatter(formatSymtab) { |
| 257 | 280 | return .{ .data = .{ |
| 258 | 281 | .self = self, |
test/link/elf.zig+8-2| ... | ... | @@ -158,19 +158,25 @@ fn addRunArtifact(comp: *Compile) *Run { |
| 158 | 158 | return run; |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | fn addZigSourceBytes(comp: *Compile, bytes: []const u8) void { | |
| 161 | fn addZigSourceBytes(comp: *Compile, comptime bytes: []const u8) void { | |
| 162 | 162 | const b = comp.step.owner; |
| 163 | 163 | const file = WriteFile.create(b).add("a.zig", bytes); |
| 164 | 164 | file.addStepDependencies(&comp.step); |
| 165 | 165 | comp.root_src = file; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | fn addCSourceBytes(comp: *Compile, bytes: []const u8) void { | |
| 168 | fn addCSourceBytes(comp: *Compile, comptime bytes: []const u8) void { | |
| 169 | 169 | const b = comp.step.owner; |
| 170 | 170 | const file = WriteFile.create(b).add("a.c", bytes); |
| 171 | 171 | comp.addCSourceFile(.{ .file = file, .flags = &.{} }); |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | fn addAsmSourceBytes(comp: *Compile, comptime bytes: []const u8) void { | |
| 175 | const b = comp.step.owner; | |
| 176 | const file = WriteFile.create(b).add("a.s", bytes ++ "\n"); | |
| 177 | comp.addAssemblyFile(file); | |
| 178 | } | |
| 179 | ||
| 174 | 180 | const std = @import("std"); |
| 175 | 181 | |
| 176 | 182 | const Build = std.Build; |