| ... | @@ -413,6 +413,7 @@ fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 { | ... | @@ -413,6 +413,7 @@ fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 { |
| 413 | const AllocateSegmentOpts = struct { | 413 | const AllocateSegmentOpts = struct { |
| 414 | size: u64, | 414 | size: u64, |
| 415 | alignment: u64, | 415 | alignment: u64, |
| | 416 | addr: ?u64 = null, |
| 416 | flags: u32 = elf.PF_R, | 417 | flags: u32 = elf.PF_R, |
| 417 | }; | 418 | }; |
| 418 | | 419 | |
| ... | @@ -423,8 +424,8 @@ pub fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory} | ... | @@ -423,8 +424,8 @@ pub fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory} |
| 423 | // Memory is always allocated in sequence. | 424 | // Memory is always allocated in sequence. |
| 424 | // TODO is this correct? Or should we implement something similar to `findFreeSpace`? | 425 | // TODO is this correct? Or should we implement something similar to `findFreeSpace`? |
| 425 | // How would that impact HCS? | 426 | // How would that impact HCS? |
| 426 | const addr = blk: { | 427 | const addr = opts.addr orelse blk: { |
| 427 | assert(self.phdr_table_load_index != null); | 428 | assert(index >= 1); |
| 428 | const phdr = &self.phdrs.items[index - 1]; | 429 | const phdr = &self.phdrs.items[index - 1]; |
| 429 | const increased_size = padToIdeal(phdr.p_vaddr + phdr.p_memsz); | 430 | const increased_size = padToIdeal(phdr.p_vaddr + phdr.p_memsz); |
| 430 | break :blk mem.alignForward(u64, increased_size, opts.alignment); | 431 | break :blk mem.alignForward(u64, increased_size, opts.alignment); |
| ... | @@ -532,6 +533,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -532,6 +533,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 532 | .p64 => false, | 533 | .p64 => false, |
| 533 | }; | 534 | }; |
| 534 | const ptr_size: u8 = self.ptrWidthBytes(); | 535 | const ptr_size: u8 = self.ptrWidthBytes(); |
| | 536 | const is_linux = self.base.options.target.os.tag == .linux; |
| 535 | const image_base = self.calcImageBase(); | 537 | const image_base = self.calcImageBase(); |
| 536 | | 538 | |
| 537 | if (self.phdr_table_index == null) { | 539 | if (self.phdr_table_index == null) { |
| ... | @@ -570,6 +572,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -570,6 +572,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 570 | | 572 | |
| 571 | if (self.phdr_load_re_index == null) { | 573 | if (self.phdr_load_re_index == null) { |
| 572 | self.phdr_load_re_index = try self.allocateSegment(.{ | 574 | self.phdr_load_re_index = try self.allocateSegment(.{ |
| | 575 | .addr = self.defaultEntryAddress(), |
| 573 | .size = self.base.options.program_code_size_hint, | 576 | .size = self.base.options.program_code_size_hint, |
| 574 | .alignment = self.page_size, | 577 | .alignment = self.page_size, |
| 575 | .flags = elf.PF_X | elf.PF_R | elf.PF_W, | 578 | .flags = elf.PF_X | elf.PF_R | elf.PF_W, |
| ... | @@ -578,10 +581,12 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -578,10 +581,12 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 578 | } | 581 | } |
| 579 | | 582 | |
| 580 | if (self.phdr_got_index == null) { | 583 | if (self.phdr_got_index == null) { |
| | 584 | const addr: u64 = if (ptr_size >= 4) 0x4000000 else 0x8000; |
| 581 | // We really only need ptr alignment but since we are using PROGBITS, linux requires | 585 | // We really only need ptr alignment but since we are using PROGBITS, linux requires |
| 582 | // page align. | 586 | // page align. |
| 583 | const alignment = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size); | 587 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); |
| 584 | self.phdr_got_index = try self.allocateSegment(.{ | 588 | self.phdr_got_index = try self.allocateSegment(.{ |
| | 589 | .addr = addr, |
| 585 | .size = @as(u64, ptr_size) * self.base.options.symbol_count_hint, | 590 | .size = @as(u64, ptr_size) * self.base.options.symbol_count_hint, |
| 586 | .alignment = alignment, | 591 | .alignment = alignment, |
| 587 | .flags = elf.PF_R | elf.PF_W, | 592 | .flags = elf.PF_R | elf.PF_W, |
| ... | @@ -589,9 +594,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -589,9 +594,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 589 | } | 594 | } |
| 590 | | 595 | |
| 591 | if (self.phdr_load_ro_index == null) { | 596 | if (self.phdr_load_ro_index == null) { |
| 592 | // Same reason as for GOT | 597 | const addr: u64 = if (ptr_size >= 4) 0xc000000 else 0xa000; |
| 593 | const alignment = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size); | 598 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); |
| 594 | self.phdr_load_ro_index = try self.allocateSegment(.{ | 599 | self.phdr_load_ro_index = try self.allocateSegment(.{ |
| | 600 | .addr = addr, |
| 595 | .size = 1024, | 601 | .size = 1024, |
| 596 | .alignment = alignment, | 602 | .alignment = alignment, |
| 597 | .flags = elf.PF_R | elf.PF_W, | 603 | .flags = elf.PF_R | elf.PF_W, |
| ... | @@ -599,9 +605,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -599,9 +605,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 599 | } | 605 | } |
| 600 | | 606 | |
| 601 | if (self.phdr_load_rw_index == null) { | 607 | if (self.phdr_load_rw_index == null) { |
| 602 | // Same reason as for GOT | 608 | const addr: u64 = if (ptr_size >= 4) 0x10000000 else 0xc000; |
| 603 | const alignment = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size); | 609 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); |
| 604 | self.phdr_load_rw_index = try self.allocateSegment(.{ | 610 | self.phdr_load_rw_index = try self.allocateSegment(.{ |
| | 611 | .addr = addr, |
| 605 | .size = 1024, | 612 | .size = 1024, |
| 606 | .alignment = alignment, | 613 | .alignment = alignment, |
| 607 | .flags = elf.PF_R | elf.PF_W, | 614 | .flags = elf.PF_R | elf.PF_W, |
| ... | @@ -609,8 +616,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -609,8 +616,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 609 | } | 616 | } |
| 610 | | 617 | |
| 611 | if (self.phdr_load_zerofill_index == null) { | 618 | if (self.phdr_load_zerofill_index == null) { |
| 612 | const alignment = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size); | 619 | const addr: u64 = if (ptr_size >= 4) 0x14000000 else 0xf000; |
| | 620 | const alignment = if (is_linux) self.page_size else @as(u16, ptr_size); |
| 613 | self.phdr_load_zerofill_index = try self.allocateSegment(.{ | 621 | self.phdr_load_zerofill_index = try self.allocateSegment(.{ |
| | 622 | .addr = addr, |
| 614 | .size = 0, | 623 | .size = 0, |
| 615 | .alignment = alignment, | 624 | .alignment = alignment, |
| 616 | .flags = elf.PF_R | elf.PF_W, | 625 | .flags = elf.PF_R | elf.PF_W, |
| ... | @@ -3801,6 +3810,14 @@ pub fn calcImageBase(self: Elf) u64 { | ... | @@ -3801,6 +3810,14 @@ pub fn calcImageBase(self: Elf) u64 { |
| 3801 | }; | 3810 | }; |
| 3802 | } | 3811 | } |
| 3803 | | 3812 | |
| | 3813 | pub fn defaultEntryAddress(self: Elf) u64 { |
| | 3814 | if (self.entry_addr) |addr| return addr; |
| | 3815 | return switch (self.base.options.target.cpu.arch) { |
| | 3816 | .spu_2 => 0, |
| | 3817 | else => default_entry_addr, |
| | 3818 | }; |
| | 3819 | } |
| | 3820 | |
| 3804 | pub fn isDynLib(self: Elf) bool { | 3821 | pub fn isDynLib(self: Elf) bool { |
| 3805 | return self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic; | 3822 | return self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic; |
| 3806 | } | 3823 | } |