| ... | @@ -2,6 +2,7 @@ const Elf = @This(); | ... | @@ -2,6 +2,7 @@ const Elf = @This(); |
| 2 | | 2 | |
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const builtin = @import("builtin"); | 4 | const builtin = @import("builtin"); |
| | 5 | const math = std.math; |
| 5 | const mem = std.mem; | 6 | const mem = std.mem; |
| 6 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 7 | const Allocator = std.mem.Allocator; | 8 | const Allocator = std.mem.Allocator; |
| ... | @@ -64,6 +65,7 @@ phdr_load_rw_index: ?u16 = null, | ... | @@ -64,6 +65,7 @@ phdr_load_rw_index: ?u16 = null, |
| 64 | phdr_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{}, | 65 | phdr_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{}, |
| 65 | | 66 | |
| 66 | entry_addr: ?u64 = null, | 67 | entry_addr: ?u64 = null, |
| | 68 | page_size: u16, |
| 67 | | 69 | |
| 68 | debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | 70 | debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, |
| 69 | shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | 71 | shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, |
| ... | @@ -334,6 +336,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { | ... | @@ -334,6 +336,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { |
| 334 | }; | 336 | }; |
| 335 | const self = try gpa.create(Elf); | 337 | const self = try gpa.create(Elf); |
| 336 | errdefer gpa.destroy(self); | 338 | errdefer gpa.destroy(self); |
| | 339 | const page_size: u16 = 0x1000; // TODO ppc64le requires 64KB |
| 337 | | 340 | |
| 338 | self.* = .{ | 341 | self.* = .{ |
| 339 | .base = .{ | 342 | .base = .{ |
| ... | @@ -343,6 +346,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { | ... | @@ -343,6 +346,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf { |
| 343 | .file = null, | 346 | .file = null, |
| 344 | }, | 347 | }, |
| 345 | .ptr_width = ptr_width, | 348 | .ptr_width = ptr_width, |
| | 349 | .page_size = page_size, |
| 346 | }; | 350 | }; |
| 347 | const use_llvm = build_options.have_llvm and options.use_llvm; | 351 | const use_llvm = build_options.have_llvm and options.use_llvm; |
| 348 | const use_stage1 = build_options.is_stage1 and options.use_stage1; | 352 | const use_stage1 = build_options.is_stage1 and options.use_stage1; |
| ... | @@ -523,10 +527,11 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -523,10 +527,11 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 523 | .p64 => false, | 527 | .p64 => false, |
| 524 | }; | 528 | }; |
| 525 | const ptr_size: u8 = self.ptrWidthBytes(); | 529 | const ptr_size: u8 = self.ptrWidthBytes(); |
| | 530 | |
| 526 | if (self.phdr_load_re_index == null) { | 531 | if (self.phdr_load_re_index == null) { |
| 527 | self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len); | 532 | self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len); |
| 528 | const file_size = self.base.options.program_code_size_hint; | 533 | const file_size = self.base.options.program_code_size_hint; |
| 529 | const p_align = 0x1000; | 534 | const p_align = self.page_size; |
| 530 | const off = self.findFreeSpace(file_size, p_align); | 535 | const off = self.findFreeSpace(file_size, p_align); |
| 531 | log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size }); | 536 | log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 532 | const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr; | 537 | const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr; |
| ... | @@ -544,12 +549,13 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -544,12 +549,13 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 544 | self.entry_addr = null; | 549 | self.entry_addr = null; |
| 545 | self.phdr_table_dirty = true; | 550 | self.phdr_table_dirty = true; |
| 546 | } | 551 | } |
| | 552 | |
| 547 | if (self.phdr_got_index == null) { | 553 | if (self.phdr_got_index == null) { |
| 548 | self.phdr_got_index = @intCast(u16, self.program_headers.items.len); | 554 | self.phdr_got_index = @intCast(u16, self.program_headers.items.len); |
| 549 | const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint; | 555 | const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint; |
| 550 | // We really only need ptr alignment but since we are using PROGBITS, linux requires | 556 | // We really only need ptr alignment but since we are using PROGBITS, linux requires |
| 551 | // page align. | 557 | // page align. |
| 552 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); | 558 | const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size); |
| 553 | const off = self.findFreeSpace(file_size, p_align); | 559 | const off = self.findFreeSpace(file_size, p_align); |
| 554 | log.debug("found PT_LOAD GOT free space 0x{x} to 0x{x}", .{ off, off + file_size }); | 560 | log.debug("found PT_LOAD GOT free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 555 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. | 561 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. |
| ... | @@ -568,16 +574,17 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -568,16 +574,17 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 568 | }); | 574 | }); |
| 569 | self.phdr_table_dirty = true; | 575 | self.phdr_table_dirty = true; |
| 570 | } | 576 | } |
| | 577 | |
| 571 | if (self.phdr_load_ro_index == null) { | 578 | if (self.phdr_load_ro_index == null) { |
| 572 | self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len); | 579 | self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len); |
| 573 | // TODO Find a hint about how much data need to be in rodata ? | 580 | // TODO Find a hint about how much data need to be in rodata ? |
| 574 | const file_size = 1024; | 581 | const file_size = 1024; |
| 575 | // Same reason as for GOT | 582 | // Same reason as for GOT |
| 576 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); | 583 | const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size); |
| 577 | const off = self.findFreeSpace(file_size, p_align); | 584 | const off = self.findFreeSpace(file_size, p_align); |
| 578 | log.debug("found PT_LOAD RO free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 585 | log.debug("found PT_LOAD RO free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 579 | // TODO Same as for GOT | 586 | // TODO Same as for GOT |
| 580 | const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x5000000 else 0xa000; | 587 | const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0xc000000 else 0xa000; |
| 581 | try self.program_headers.append(self.base.allocator, .{ | 588 | try self.program_headers.append(self.base.allocator, .{ |
| 582 | .p_type = elf.PT_LOAD, | 589 | .p_type = elf.PT_LOAD, |
| 583 | .p_offset = off, | 590 | .p_offset = off, |
| ... | @@ -591,16 +598,17 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -591,16 +598,17 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 591 | try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_ro_index.?, .{}); | 598 | try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_ro_index.?, .{}); |
| 592 | self.phdr_table_dirty = true; | 599 | self.phdr_table_dirty = true; |
| 593 | } | 600 | } |
| | 601 | |
| 594 | if (self.phdr_load_rw_index == null) { | 602 | if (self.phdr_load_rw_index == null) { |
| 595 | self.phdr_load_rw_index = @intCast(u16, self.program_headers.items.len); | 603 | self.phdr_load_rw_index = @intCast(u16, self.program_headers.items.len); |
| 596 | // TODO Find a hint about how much data need to be in data ? | 604 | // TODO Find a hint about how much data need to be in data ? |
| 597 | const file_size = 1024; | 605 | const file_size = 1024; |
| 598 | // Same reason as for GOT | 606 | // Same reason as for GOT |
| 599 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); | 607 | const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size); |
| 600 | const off = self.findFreeSpace(file_size, p_align); | 608 | const off = self.findFreeSpace(file_size, p_align); |
| 601 | log.debug("found PT_LOAD RW free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 609 | log.debug("found PT_LOAD RW free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 602 | // TODO Same as for GOT | 610 | // TODO Same as for GOT |
| 603 | const rwdata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x6000000 else 0xc000; | 611 | const rwdata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x10000000 else 0xc000; |
| 604 | try self.program_headers.append(self.base.allocator, .{ | 612 | try self.program_headers.append(self.base.allocator, .{ |
| 605 | .p_type = elf.PT_LOAD, | 613 | .p_type = elf.PT_LOAD, |
| 606 | .p_offset = off, | 614 | .p_offset = off, |
| ... | @@ -614,6 +622,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -614,6 +622,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 614 | try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_rw_index.?, .{}); | 622 | try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_rw_index.?, .{}); |
| 615 | self.phdr_table_dirty = true; | 623 | self.phdr_table_dirty = true; |
| 616 | } | 624 | } |
| | 625 | |
| 617 | if (self.shstrtab_index == null) { | 626 | if (self.shstrtab_index == null) { |
| 618 | self.shstrtab_index = @intCast(u16, self.sections.items.len); | 627 | self.shstrtab_index = @intCast(u16, self.sections.items.len); |
| 619 | assert(self.shstrtab.items.len == 0); | 628 | assert(self.shstrtab.items.len == 0); |
| ... | @@ -635,6 +644,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -635,6 +644,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 635 | self.shstrtab_dirty = true; | 644 | self.shstrtab_dirty = true; |
| 636 | self.shdr_table_dirty = true; | 645 | self.shdr_table_dirty = true; |
| 637 | } | 646 | } |
| | 647 | |
| 638 | if (self.text_section_index == null) { | 648 | if (self.text_section_index == null) { |
| 639 | self.text_section_index = @intCast(u16, self.sections.items.len); | 649 | self.text_section_index = @intCast(u16, self.sections.items.len); |
| 640 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | 650 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| ... | @@ -648,7 +658,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -648,7 +658,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 648 | .sh_size = phdr.p_filesz, | 658 | .sh_size = phdr.p_filesz, |
| 649 | .sh_link = 0, | 659 | .sh_link = 0, |
| 650 | .sh_info = 0, | 660 | .sh_info = 0, |
| 651 | .sh_addralign = phdr.p_align, | 661 | .sh_addralign = 1, |
| 652 | .sh_entsize = 0, | 662 | .sh_entsize = 0, |
| 653 | }); | 663 | }); |
| 654 | try self.phdr_shdr_table.putNoClobber( | 664 | try self.phdr_shdr_table.putNoClobber( |
| ... | @@ -658,6 +668,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -658,6 +668,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 658 | ); | 668 | ); |
| 659 | self.shdr_table_dirty = true; | 669 | self.shdr_table_dirty = true; |
| 660 | } | 670 | } |
| | 671 | |
| 661 | if (self.got_section_index == null) { | 672 | if (self.got_section_index == null) { |
| 662 | self.got_section_index = @intCast(u16, self.sections.items.len); | 673 | self.got_section_index = @intCast(u16, self.sections.items.len); |
| 663 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; | 674 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; |
| ... | @@ -671,7 +682,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -671,7 +682,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 671 | .sh_size = phdr.p_filesz, | 682 | .sh_size = phdr.p_filesz, |
| 672 | .sh_link = 0, | 683 | .sh_link = 0, |
| 673 | .sh_info = 0, | 684 | .sh_info = 0, |
| 674 | .sh_addralign = phdr.p_align, | 685 | .sh_addralign = @as(u16, ptr_size), |
| 675 | .sh_entsize = 0, | 686 | .sh_entsize = 0, |
| 676 | }); | 687 | }); |
| 677 | try self.phdr_shdr_table.putNoClobber( | 688 | try self.phdr_shdr_table.putNoClobber( |
| ... | @@ -681,6 +692,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -681,6 +692,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 681 | ); | 692 | ); |
| 682 | self.shdr_table_dirty = true; | 693 | self.shdr_table_dirty = true; |
| 683 | } | 694 | } |
| | 695 | |
| 684 | if (self.rodata_section_index == null) { | 696 | if (self.rodata_section_index == null) { |
| 685 | self.rodata_section_index = @intCast(u16, self.sections.items.len); | 697 | self.rodata_section_index = @intCast(u16, self.sections.items.len); |
| 686 | const phdr = &self.program_headers.items[self.phdr_load_ro_index.?]; | 698 | const phdr = &self.program_headers.items[self.phdr_load_ro_index.?]; |
| ... | @@ -694,7 +706,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -694,7 +706,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 694 | .sh_size = phdr.p_filesz, | 706 | .sh_size = phdr.p_filesz, |
| 695 | .sh_link = 0, | 707 | .sh_link = 0, |
| 696 | .sh_info = 0, | 708 | .sh_info = 0, |
| 697 | .sh_addralign = phdr.p_align, | 709 | .sh_addralign = 1, |
| 698 | .sh_entsize = 0, | 710 | .sh_entsize = 0, |
| 699 | }); | 711 | }); |
| 700 | try self.phdr_shdr_table.putNoClobber( | 712 | try self.phdr_shdr_table.putNoClobber( |
| ... | @@ -704,6 +716,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -704,6 +716,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 704 | ); | 716 | ); |
| 705 | self.shdr_table_dirty = true; | 717 | self.shdr_table_dirty = true; |
| 706 | } | 718 | } |
| | 719 | |
| 707 | if (self.data_section_index == null) { | 720 | if (self.data_section_index == null) { |
| 708 | self.data_section_index = @intCast(u16, self.sections.items.len); | 721 | self.data_section_index = @intCast(u16, self.sections.items.len); |
| 709 | const phdr = &self.program_headers.items[self.phdr_load_rw_index.?]; | 722 | const phdr = &self.program_headers.items[self.phdr_load_rw_index.?]; |
| ... | @@ -717,7 +730,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -717,7 +730,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 717 | .sh_size = phdr.p_filesz, | 730 | .sh_size = phdr.p_filesz, |
| 718 | .sh_link = 0, | 731 | .sh_link = 0, |
| 719 | .sh_info = 0, | 732 | .sh_info = 0, |
| 720 | .sh_addralign = phdr.p_align, | 733 | .sh_addralign = @as(u16, ptr_size), |
| 721 | .sh_entsize = 0, | 734 | .sh_entsize = 0, |
| 722 | }); | 735 | }); |
| 723 | try self.phdr_shdr_table.putNoClobber( | 736 | try self.phdr_shdr_table.putNoClobber( |
| ... | @@ -727,6 +740,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -727,6 +740,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 727 | ); | 740 | ); |
| 728 | self.shdr_table_dirty = true; | 741 | self.shdr_table_dirty = true; |
| 729 | } | 742 | } |
| | 743 | |
| 730 | if (self.symtab_section_index == null) { | 744 | if (self.symtab_section_index == null) { |
| 731 | self.symtab_section_index = @intCast(u16, self.sections.items.len); | 745 | self.symtab_section_index = @intCast(u16, self.sections.items.len); |
| 732 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); | 746 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); |
| ... | @@ -751,6 +765,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -751,6 +765,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 751 | self.shdr_table_dirty = true; | 765 | self.shdr_table_dirty = true; |
| 752 | try self.writeSymbol(0); | 766 | try self.writeSymbol(0); |
| 753 | } | 767 | } |
| | 768 | |
| 754 | if (self.debug_str_section_index == null) { | 769 | if (self.debug_str_section_index == null) { |
| 755 | self.debug_str_section_index = @intCast(u16, self.sections.items.len); | 770 | self.debug_str_section_index = @intCast(u16, self.sections.items.len); |
| 756 | assert(self.debug_strtab.items.len == 0); | 771 | assert(self.debug_strtab.items.len == 0); |
| ... | @@ -769,6 +784,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -769,6 +784,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 769 | self.debug_strtab_dirty = true; | 784 | self.debug_strtab_dirty = true; |
| 770 | self.shdr_table_dirty = true; | 785 | self.shdr_table_dirty = true; |
| 771 | } | 786 | } |
| | 787 | |
| 772 | if (self.debug_info_section_index == null) { | 788 | if (self.debug_info_section_index == null) { |
| 773 | self.debug_info_section_index = @intCast(u16, self.sections.items.len); | 789 | self.debug_info_section_index = @intCast(u16, self.sections.items.len); |
| 774 | | 790 | |
| ... | @@ -794,6 +810,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -794,6 +810,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 794 | self.shdr_table_dirty = true; | 810 | self.shdr_table_dirty = true; |
| 795 | self.debug_info_header_dirty = true; | 811 | self.debug_info_header_dirty = true; |
| 796 | } | 812 | } |
| | 813 | |
| 797 | if (self.debug_abbrev_section_index == null) { | 814 | if (self.debug_abbrev_section_index == null) { |
| 798 | self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len); | 815 | self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len); |
| 799 | | 816 | |
| ... | @@ -819,6 +836,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -819,6 +836,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 819 | self.shdr_table_dirty = true; | 836 | self.shdr_table_dirty = true; |
| 820 | self.debug_abbrev_section_dirty = true; | 837 | self.debug_abbrev_section_dirty = true; |
| 821 | } | 838 | } |
| | 839 | |
| 822 | if (self.debug_aranges_section_index == null) { | 840 | if (self.debug_aranges_section_index == null) { |
| 823 | self.debug_aranges_section_index = @intCast(u16, self.sections.items.len); | 841 | self.debug_aranges_section_index = @intCast(u16, self.sections.items.len); |
| 824 | | 842 | |
| ... | @@ -844,6 +862,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -844,6 +862,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 844 | self.shdr_table_dirty = true; | 862 | self.shdr_table_dirty = true; |
| 845 | self.debug_aranges_section_dirty = true; | 863 | self.debug_aranges_section_dirty = true; |
| 846 | } | 864 | } |
| | 865 | |
| 847 | if (self.debug_line_section_index == null) { | 866 | if (self.debug_line_section_index == null) { |
| 848 | self.debug_line_section_index = @intCast(u16, self.sections.items.len); | 867 | self.debug_line_section_index = @intCast(u16, self.sections.items.len); |
| 849 | | 868 | |
| ... | @@ -869,6 +888,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -869,6 +888,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 869 | self.shdr_table_dirty = true; | 888 | self.shdr_table_dirty = true; |
| 870 | self.debug_line_header_dirty = true; | 889 | self.debug_line_header_dirty = true; |
| 871 | } | 890 | } |
| | 891 | |
| 872 | const shsize: u64 = switch (self.ptr_width) { | 892 | const shsize: u64 = switch (self.ptr_width) { |
| 873 | .p32 => @sizeOf(elf.Elf32_Shdr), | 893 | .p32 => @sizeOf(elf.Elf32_Shdr), |
| 874 | .p64 => @sizeOf(elf.Elf64_Shdr), | 894 | .p64 => @sizeOf(elf.Elf64_Shdr), |
| ... | @@ -881,6 +901,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -881,6 +901,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 881 | self.shdr_table_offset = self.findFreeSpace(self.sections.items.len * shsize, shalign); | 901 | self.shdr_table_offset = self.findFreeSpace(self.sections.items.len * shsize, shalign); |
| 882 | self.shdr_table_dirty = true; | 902 | self.shdr_table_dirty = true; |
| 883 | } | 903 | } |
| | 904 | |
| 884 | const phsize: u64 = switch (self.ptr_width) { | 905 | const phsize: u64 = switch (self.ptr_width) { |
| 885 | .p32 => @sizeOf(elf.Elf32_Phdr), | 906 | .p32 => @sizeOf(elf.Elf32_Phdr), |
| 886 | .p64 => @sizeOf(elf.Elf64_Phdr), | 907 | .p64 => @sizeOf(elf.Elf64_Phdr), |
| ... | @@ -893,6 +914,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -893,6 +914,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 893 | self.phdr_table_offset = self.findFreeSpace(self.program_headers.items.len * phsize, phalign); | 914 | self.phdr_table_offset = self.findFreeSpace(self.program_headers.items.len * phsize, phalign); |
| 894 | self.phdr_table_dirty = true; | 915 | self.phdr_table_dirty = true; |
| 895 | } | 916 | } |
| | 917 | |
| 896 | { | 918 | { |
| 897 | // Iterate over symbols, populating free_list and last_text_block. | 919 | // Iterate over symbols, populating free_list and last_text_block. |
| 898 | if (self.local_symbols.items.len != 1) { | 920 | if (self.local_symbols.items.len != 1) { |
| ... | @@ -2378,12 +2400,13 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al | ... | @@ -2378,12 +2400,13 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2378 | const text_capacity = self.allocatedSize(shdr.sh_offset); | 2400 | const text_capacity = self.allocatedSize(shdr.sh_offset); |
| 2379 | const needed_size = (vaddr + new_block_size) - phdr.p_vaddr; | 2401 | const needed_size = (vaddr + new_block_size) - phdr.p_vaddr; |
| 2380 | if (needed_size > text_capacity) { | 2402 | if (needed_size > text_capacity) { |
| 2381 | // Must move the entire text section. | 2403 | // Must move the entire section. |
| 2382 | const new_offset = self.findFreeSpace(needed_size, 0x1000); | 2404 | const new_offset = self.findFreeSpace(needed_size, self.page_size); |
| 2383 | const text_size = if (self.atoms.get(phdr_index)) |last| blk: { | 2405 | const text_size = if (self.atoms.get(phdr_index)) |last| blk: { |
| 2384 | const sym = self.local_symbols.items[last.local_sym_index]; | 2406 | const sym = self.local_symbols.items[last.local_sym_index]; |
| 2385 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; | 2407 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; |
| 2386 | } else 0; | 2408 | } else 0; |
| | 2409 | log.debug("new PT_LOAD file offset 0x{x} to 0x{x}", .{ new_offset, new_offset + text_size }); |
| 2387 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, text_size); | 2410 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, text_size); |
| 2388 | if (amt != text_size) return error.InputOutput; | 2411 | if (amt != text_size) return error.InputOutput; |
| 2389 | shdr.sh_offset = new_offset; | 2412 | shdr.sh_offset = new_offset; |
| ... | @@ -2407,6 +2430,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al | ... | @@ -2407,6 +2430,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2407 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty | 2430 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty |
| 2408 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | 2431 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty |
| 2409 | } | 2432 | } |
| | 2433 | shdr.sh_addralign = math.max(shdr.sh_addralign, alignment); |
| 2410 | | 2434 | |
| 2411 | // This function can also reallocate a text block. | 2435 | // This function can also reallocate a text block. |
| 2412 | // In this case we need to "unplug" it from its previous location before | 2436 | // In this case we need to "unplug" it from its previous location before |
| ... | @@ -3478,7 +3502,7 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void { | ... | @@ -3478,7 +3502,7 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void { |
| 3478 | const needed_size = self.offset_table.items.len * entry_size; | 3502 | const needed_size = self.offset_table.items.len * entry_size; |
| 3479 | if (needed_size > allocated_size) { | 3503 | if (needed_size > allocated_size) { |
| 3480 | // Must move the entire got section. | 3504 | // Must move the entire got section. |
| 3481 | const new_offset = self.findFreeSpace(needed_size, entry_size); | 3505 | const new_offset = self.findFreeSpace(needed_size, self.page_size); |
| 3482 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, shdr.sh_size); | 3506 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, shdr.sh_size); |
| 3483 | if (amt != shdr.sh_size) return error.InputOutput; | 3507 | if (amt != shdr.sh_size) return error.InputOutput; |
| 3484 | shdr.sh_offset = new_offset; | 3508 | shdr.sh_offset = new_offset; |