| ... | @@ -56,6 +56,11 @@ phdr_load_re_index: ?u16 = null, | ... | @@ -56,6 +56,11 @@ phdr_load_re_index: ?u16 = null, |
| 56 | phdr_got_index: ?u16 = null, | 56 | phdr_got_index: ?u16 = null, |
| 57 | /// The index into the program headers of a PT_LOAD program header with Read flag | 57 | /// The index into the program headers of a PT_LOAD program header with Read flag |
| 58 | phdr_load_ro_index: ?u16 = null, | 58 | phdr_load_ro_index: ?u16 = null, |
| | 59 | /// The index into the program headers of a PT_LOAD program header with Write flag |
| | 60 | phdr_load_rw_index: ?u16 = null, |
| | 61 | |
| | 62 | phdr_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{}, |
| | 63 | |
| 59 | entry_addr: ?u64 = null, | 64 | entry_addr: ?u64 = null, |
| 60 | | 65 | |
| 61 | debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | 66 | debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, |
| ... | @@ -63,7 +68,10 @@ shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | ... | @@ -63,7 +68,10 @@ shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, |
| 63 | shstrtab_index: ?u16 = null, | 68 | shstrtab_index: ?u16 = null, |
| 64 | | 69 | |
| 65 | symtab_section_index: ?u16 = null, | 70 | symtab_section_index: ?u16 = null, |
| | 71 | text_section_index: ?u16 = null, |
| | 72 | rodata_section_index: ?u16 = null, |
| 66 | got_section_index: ?u16 = null, | 73 | got_section_index: ?u16 = null, |
| | 74 | data_section_index: ?u16 = null, |
| 67 | debug_info_section_index: ?u16 = null, | 75 | debug_info_section_index: ?u16 = null, |
| 68 | debug_abbrev_section_index: ?u16 = null, | 76 | debug_abbrev_section_index: ?u16 = null, |
| 69 | debug_str_section_index: ?u16 = null, | 77 | debug_str_section_index: ?u16 = null, |
| ... | @@ -116,8 +124,9 @@ error_flags: File.ErrorFlags = File.ErrorFlags{}, | ... | @@ -116,8 +124,9 @@ error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 116 | /// overcapacity can be negative. A simple way to have negative overcapacity is to | 124 | /// overcapacity can be negative. A simple way to have negative overcapacity is to |
| 117 | /// allocate a fresh text block, which will have ideal capacity, and then grow it | 125 | /// allocate a fresh text block, which will have ideal capacity, and then grow it |
| 118 | /// by 1 byte. It will then have -1 overcapacity. | 126 | /// by 1 byte. It will then have -1 overcapacity. |
| 119 | text_block_list: TextBlockList = .{}, | 127 | atoms: std.AutoHashMapUnmanaged(u16, *TextBlock) = .{}, |
| 120 | rodata_block_list: TextBlockList = .{}, | 128 | atom_free_lists: std.AutoHashMapUnmanaged(u16, std.ArrayListUnmanaged(*TextBlock)) = .{}, |
| | 129 | decls: std.AutoHashMapUnmanaged(*Module.Decl, ?u16) = .{}, |
| 121 | | 130 | |
| 122 | /// A list of `SrcFn` whose Line Number Programs have surplus capacity. | 131 | /// A list of `SrcFn` whose Line Number Programs have surplus capacity. |
| 123 | /// This is the same concept as `text_block_free_list`; see those doc comments. | 132 | /// This is the same concept as `text_block_free_list`; see those doc comments. |
| ... | @@ -205,14 +214,6 @@ pub const TextBlock = struct { | ... | @@ -205,14 +214,6 @@ pub const TextBlock = struct { |
| 205 | } | 214 | } |
| 206 | }; | 215 | }; |
| 207 | | 216 | |
| 208 | /// A list of text blocks in a specific section | | |
| 209 | const TextBlockList = struct { | | |
| 210 | free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, | | |
| 211 | last_block: ?*TextBlock = null, | | |
| 212 | phdr_index: ?u16 = null, | | |
| 213 | section_index: ?u16 = null, | | |
| 214 | }; | | |
| 215 | | | |
| 216 | pub const Export = struct { | 217 | pub const Export = struct { |
| 217 | sym_index: ?u32 = null, | 218 | sym_index: ?u32 = null, |
| 218 | }; | 219 | }; |
| ... | @@ -326,11 +327,20 @@ pub fn deinit(self: *Elf) void { | ... | @@ -326,11 +327,20 @@ pub fn deinit(self: *Elf) void { |
| 326 | self.global_symbol_free_list.deinit(self.base.allocator); | 327 | self.global_symbol_free_list.deinit(self.base.allocator); |
| 327 | self.local_symbol_free_list.deinit(self.base.allocator); | 328 | self.local_symbol_free_list.deinit(self.base.allocator); |
| 328 | self.offset_table_free_list.deinit(self.base.allocator); | 329 | self.offset_table_free_list.deinit(self.base.allocator); |
| 329 | self.text_block_list.free_list.deinit(self.base.allocator); | | |
| 330 | self.rodata_block_list.free_list.deinit(self.base.allocator); | | |
| 331 | self.dbg_line_fn_free_list.deinit(self.base.allocator); | 330 | self.dbg_line_fn_free_list.deinit(self.base.allocator); |
| 332 | self.dbg_info_decl_free_list.deinit(self.base.allocator); | 331 | self.dbg_info_decl_free_list.deinit(self.base.allocator); |
| 333 | self.offset_table.deinit(self.base.allocator); | 332 | self.offset_table.deinit(self.base.allocator); |
| | 333 | self.phdr_shdr_table.deinit(self.base.allocator); |
| | 334 | self.decls.deinit(self.base.allocator); |
| | 335 | |
| | 336 | self.atoms.deinit(self.base.allocator); |
| | 337 | { |
| | 338 | var it = self.atom_free_lists.valueIterator(); |
| | 339 | while (it.next()) |free_list| { |
| | 340 | free_list.deinit(self.base.allocator); |
| | 341 | } |
| | 342 | self.atom_free_lists.deinit(self.base.allocator); |
| | 343 | } |
| 334 | } | 344 | } |
| 335 | | 345 | |
| 336 | pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 { | 346 | pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 { |
| ... | @@ -463,11 +473,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -463,11 +473,10 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 463 | const ptr_size: u8 = self.ptrWidthBytes(); | 473 | const ptr_size: u8 = self.ptrWidthBytes(); |
| 464 | if (self.phdr_load_re_index == null) { | 474 | if (self.phdr_load_re_index == null) { |
| 465 | self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len); | 475 | self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len); |
| 466 | self.text_block_list.phdr_index = self.phdr_load_re_index; | | |
| 467 | const file_size = self.base.options.program_code_size_hint; | 476 | const file_size = self.base.options.program_code_size_hint; |
| 468 | const p_align = 0x1000; | 477 | const p_align = 0x1000; |
| 469 | const off = self.findFreeSpace(file_size, p_align); | 478 | const off = self.findFreeSpace(file_size, p_align); |
| 470 | log.debug("found PT_LOAD free space 0x{x} to 0x{x}", .{ off, off + file_size }); | 479 | log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 471 | const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr; | 480 | const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr; |
| 472 | try self.program_headers.append(self.base.allocator, .{ | 481 | try self.program_headers.append(self.base.allocator, .{ |
| 473 | .p_type = elf.PT_LOAD, | 482 | .p_type = elf.PT_LOAD, |
| ... | @@ -479,6 +488,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -479,6 +488,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 479 | .p_align = p_align, | 488 | .p_align = p_align, |
| 480 | .p_flags = elf.PF_X | elf.PF_R, | 489 | .p_flags = elf.PF_X | elf.PF_R, |
| 481 | }); | 490 | }); |
| | 491 | try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_re_index.?, .{}); |
| 482 | self.entry_addr = null; | 492 | self.entry_addr = null; |
| 483 | self.phdr_table_dirty = true; | 493 | self.phdr_table_dirty = true; |
| 484 | } | 494 | } |
| ... | @@ -489,7 +499,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -489,7 +499,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 489 | // page align. | 499 | // page align. |
| 490 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); | 500 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); |
| 491 | const off = self.findFreeSpace(file_size, p_align); | 501 | const off = self.findFreeSpace(file_size, p_align); |
| 492 | log.debug("found PT_LOAD free space 0x{x} to 0x{x}", .{ off, off + file_size }); | 502 | log.debug("found PT_LOAD GOT free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 493 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. | 503 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. |
| 494 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something | 504 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something |
| 495 | // else in virtual memory. | 505 | // else in virtual memory. |
| ... | @@ -508,15 +518,14 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -508,15 +518,14 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 508 | } | 518 | } |
| 509 | if (self.phdr_load_ro_index == null) { | 519 | if (self.phdr_load_ro_index == null) { |
| 510 | self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len); | 520 | self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len); |
| 511 | self.rodata_block_list.phdr_index = self.phdr_load_ro_index; | | |
| 512 | // TODO Find a hint about how much data need to be in rodata ? | 521 | // TODO Find a hint about how much data need to be in rodata ? |
| 513 | const file_size = 1024; | 522 | const file_size = 1024; |
| 514 | // Same reason as for GOT | 523 | // Same reason as for GOT |
| 515 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); | 524 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); |
| 516 | const off = self.findFreeSpace(file_size, p_align); | 525 | const off = self.findFreeSpace(file_size, p_align); |
| 517 | log.debug("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 526 | log.debug("found PT_LOAD RO free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 518 | // TODO Same as for GOT | 527 | // TODO Same as for GOT |
| 519 | const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x6000000 else 0xD000; | 528 | const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x5000000 else 0xa000; |
| 520 | try self.program_headers.append(self.base.allocator, .{ | 529 | try self.program_headers.append(self.base.allocator, .{ |
| 521 | .p_type = elf.PT_LOAD, | 530 | .p_type = elf.PT_LOAD, |
| 522 | .p_offset = off, | 531 | .p_offset = off, |
| ... | @@ -527,6 +536,30 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -527,6 +536,30 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 527 | .p_align = p_align, | 536 | .p_align = p_align, |
| 528 | .p_flags = elf.PF_R, | 537 | .p_flags = elf.PF_R, |
| 529 | }); | 538 | }); |
| | 539 | try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_ro_index.?, .{}); |
| | 540 | self.phdr_table_dirty = true; |
| | 541 | } |
| | 542 | if (self.phdr_load_rw_index == null) { |
| | 543 | self.phdr_load_rw_index = @intCast(u16, self.program_headers.items.len); |
| | 544 | // TODO Find a hint about how much data need to be in data ? |
| | 545 | const file_size = 1024; |
| | 546 | // Same reason as for GOT |
| | 547 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); |
| | 548 | const off = self.findFreeSpace(file_size, p_align); |
| | 549 | log.debug("found PT_LOAD RW free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| | 550 | // TODO Same as for GOT |
| | 551 | const rwdata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x6000000 else 0xc000; |
| | 552 | try self.program_headers.append(self.base.allocator, .{ |
| | 553 | .p_type = elf.PT_LOAD, |
| | 554 | .p_offset = off, |
| | 555 | .p_filesz = file_size, |
| | 556 | .p_vaddr = rwdata_addr, |
| | 557 | .p_paddr = rwdata_addr, |
| | 558 | .p_memsz = file_size, |
| | 559 | .p_align = p_align, |
| | 560 | .p_flags = elf.PF_R | elf.PF_W, |
| | 561 | }); |
| | 562 | try self.atom_free_lists.putNoClobber(self.base.allocator, self.phdr_load_rw_index.?, .{}); |
| 530 | self.phdr_table_dirty = true; | 563 | self.phdr_table_dirty = true; |
| 531 | } | 564 | } |
| 532 | if (self.shstrtab_index == null) { | 565 | if (self.shstrtab_index == null) { |
| ... | @@ -550,8 +583,8 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -550,8 +583,8 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 550 | self.shstrtab_dirty = true; | 583 | self.shstrtab_dirty = true; |
| 551 | self.shdr_table_dirty = true; | 584 | self.shdr_table_dirty = true; |
| 552 | } | 585 | } |
| 553 | if (self.text_block_list.section_index == null) { | 586 | if (self.text_section_index == null) { |
| 554 | self.text_block_list.section_index = @intCast(u16, self.sections.items.len); | 587 | self.text_section_index = @intCast(u16, self.sections.items.len); |
| 555 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | 588 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 556 | | 589 | |
| 557 | try self.sections.append(self.base.allocator, .{ | 590 | try self.sections.append(self.base.allocator, .{ |
| ... | @@ -566,6 +599,11 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -566,6 +599,11 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 566 | .sh_addralign = phdr.p_align, | 599 | .sh_addralign = phdr.p_align, |
| 567 | .sh_entsize = 0, | 600 | .sh_entsize = 0, |
| 568 | }); | 601 | }); |
| | 602 | try self.phdr_shdr_table.putNoClobber( |
| | 603 | self.base.allocator, |
| | 604 | self.phdr_load_re_index.?, |
| | 605 | self.text_section_index.?, |
| | 606 | ); |
| 569 | self.shdr_table_dirty = true; | 607 | self.shdr_table_dirty = true; |
| 570 | } | 608 | } |
| 571 | if (self.got_section_index == null) { | 609 | if (self.got_section_index == null) { |
| ... | @@ -584,10 +622,15 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -584,10 +622,15 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 584 | .sh_addralign = phdr.p_align, | 622 | .sh_addralign = phdr.p_align, |
| 585 | .sh_entsize = 0, | 623 | .sh_entsize = 0, |
| 586 | }); | 624 | }); |
| | 625 | try self.phdr_shdr_table.putNoClobber( |
| | 626 | self.base.allocator, |
| | 627 | self.phdr_got_index.?, |
| | 628 | self.got_section_index.?, |
| | 629 | ); |
| 587 | self.shdr_table_dirty = true; | 630 | self.shdr_table_dirty = true; |
| 588 | } | 631 | } |
| 589 | if (self.rodata_block_list.section_index == null) { | 632 | if (self.rodata_section_index == null) { |
| 590 | self.rodata_block_list.section_index = @intCast(u16, self.sections.items.len); | 633 | self.rodata_section_index = @intCast(u16, self.sections.items.len); |
| 591 | const phdr = &self.program_headers.items[self.phdr_load_ro_index.?]; | 634 | const phdr = &self.program_headers.items[self.phdr_load_ro_index.?]; |
| 592 | | 635 | |
| 593 | try self.sections.append(self.base.allocator, .{ | 636 | try self.sections.append(self.base.allocator, .{ |
| ... | @@ -602,6 +645,34 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -602,6 +645,34 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 602 | .sh_addralign = phdr.p_align, | 645 | .sh_addralign = phdr.p_align, |
| 603 | .sh_entsize = 0, | 646 | .sh_entsize = 0, |
| 604 | }); | 647 | }); |
| | 648 | try self.phdr_shdr_table.putNoClobber( |
| | 649 | self.base.allocator, |
| | 650 | self.phdr_load_ro_index.?, |
| | 651 | self.rodata_section_index.?, |
| | 652 | ); |
| | 653 | self.shdr_table_dirty = true; |
| | 654 | } |
| | 655 | if (self.data_section_index == null) { |
| | 656 | self.data_section_index = @intCast(u16, self.sections.items.len); |
| | 657 | const phdr = &self.program_headers.items[self.phdr_load_rw_index.?]; |
| | 658 | |
| | 659 | try self.sections.append(self.base.allocator, .{ |
| | 660 | .sh_name = try self.makeString(".data"), |
| | 661 | .sh_type = elf.SHT_PROGBITS, |
| | 662 | .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC, |
| | 663 | .sh_addr = phdr.p_vaddr, |
| | 664 | .sh_offset = phdr.p_offset, |
| | 665 | .sh_size = phdr.p_filesz, |
| | 666 | .sh_link = 0, |
| | 667 | .sh_info = 0, |
| | 668 | .sh_addralign = phdr.p_align, |
| | 669 | .sh_entsize = 0, |
| | 670 | }); |
| | 671 | try self.phdr_shdr_table.putNoClobber( |
| | 672 | self.base.allocator, |
| | 673 | self.phdr_load_rw_index.?, |
| | 674 | self.data_section_index.?, |
| | 675 | ); |
| 605 | self.shdr_table_dirty = true; | 676 | self.shdr_table_dirty = true; |
| 606 | } | 677 | } |
| 607 | if (self.symtab_section_index == null) { | 678 | if (self.symtab_section_index == null) { |
| ... | @@ -2072,17 +2143,18 @@ fn writeElfHeader(self: *Elf) !void { | ... | @@ -2072,17 +2143,18 @@ fn writeElfHeader(self: *Elf) !void { |
| 2072 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); | 2143 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 2073 | } | 2144 | } |
| 2074 | | 2145 | |
| 2075 | fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) void { | 2146 | fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { |
| | 2147 | const free_list = self.atom_free_lists.getPtr(phdr_index).?; |
| 2076 | var already_have_free_list_node = false; | 2148 | var already_have_free_list_node = false; |
| 2077 | { | 2149 | { |
| 2078 | var i: usize = 0; | 2150 | var i: usize = 0; |
| 2079 | // TODO turn text_block_free_list into a hash map | 2151 | // TODO turn free_list into a hash map |
| 2080 | while (i < block_list.free_list.items.len) { | 2152 | while (i < free_list.items.len) { |
| 2081 | if (block_list.free_list.items[i] == text_block) { | 2153 | if (free_list.items[i] == text_block) { |
| 2082 | _ = block_list.free_list.swapRemove(i); | 2154 | _ = free_list.swapRemove(i); |
| 2083 | continue; | 2155 | continue; |
| 2084 | } | 2156 | } |
| 2085 | if (block_list.free_list.items[i] == text_block.prev) { | 2157 | if (free_list.items[i] == text_block.prev) { |
| 2086 | already_have_free_list_node = true; | 2158 | already_have_free_list_node = true; |
| 2087 | } | 2159 | } |
| 2088 | i += 1; | 2160 | i += 1; |
| ... | @@ -2090,10 +2162,17 @@ fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) | ... | @@ -2090,10 +2162,17 @@ fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) |
| 2090 | } | 2162 | } |
| 2091 | // TODO process free list for dbg info just like we do above for vaddrs | 2163 | // TODO process free list for dbg info just like we do above for vaddrs |
| 2092 | | 2164 | |
| 2093 | if (block_list.last_block == text_block) { | 2165 | if (self.atoms.getPtr(phdr_index)) |last_block| { |
| 2094 | // TODO shrink the .text section size here | 2166 | if (last_block.* == text_block) { |
| 2095 | block_list.last_block = text_block.prev; | 2167 | if (text_block.prev) |prev| { |
| | 2168 | // TODO shrink the section size here |
| | 2169 | last_block.* = prev; |
| | 2170 | } else { |
| | 2171 | _ = self.atoms.fetchRemove(phdr_index); |
| | 2172 | } |
| | 2173 | } |
| 2096 | } | 2174 | } |
| | 2175 | |
| 2097 | if (self.dbg_info_decl_first == text_block) { | 2176 | if (self.dbg_info_decl_first == text_block) { |
| 2098 | self.dbg_info_decl_first = text_block.dbg_info_next; | 2177 | self.dbg_info_decl_first = text_block.dbg_info_next; |
| 2099 | } | 2178 | } |
| ... | @@ -2108,7 +2187,7 @@ fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) | ... | @@ -2108,7 +2187,7 @@ fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) |
| 2108 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { | 2187 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { |
| 2109 | // The free list is heuristics, it doesn't have to be perfect, so we can | 2188 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 2110 | // ignore the OOM here. | 2189 | // ignore the OOM here. |
| 2111 | block_list.free_list.append(self.base.allocator, prev) catch {}; | 2190 | free_list.append(self.base.allocator, prev) catch {}; |
| 2112 | } | 2191 | } |
| 2113 | } else { | 2192 | } else { |
| 2114 | text_block.prev = null; | 2193 | text_block.prev = null; |
| ... | @@ -2135,24 +2214,25 @@ fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) | ... | @@ -2135,24 +2214,25 @@ fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) |
| 2135 | } | 2214 | } |
| 2136 | } | 2215 | } |
| 2137 | | 2216 | |
| 2138 | fn shrinkTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock, new_block_size: u64) void { | 2217 | fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, phdr_index: u16) void { |
| 2139 | _ = self; | 2218 | _ = self; |
| 2140 | _ = block_list; | | |
| 2141 | _ = text_block; | 2219 | _ = text_block; |
| 2142 | _ = new_block_size; | 2220 | _ = new_block_size; |
| | 2221 | _ = phdr_index; |
| 2143 | } | 2222 | } |
| 2144 | | 2223 | |
| 2145 | fn growTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | 2224 | fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64, phdr_index: u16) !u64 { |
| 2146 | const sym = self.local_symbols.items[text_block.local_sym_index]; | 2225 | const sym = self.local_symbols.items[text_block.local_sym_index]; |
| 2147 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; | 2226 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; |
| 2148 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*); | 2227 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*); |
| 2149 | if (!need_realloc) return sym.st_value; | 2228 | if (!need_realloc) return sym.st_value; |
| 2150 | return self.allocateTextBlock(block_list, text_block, new_block_size, alignment); | 2229 | return self.allocateTextBlock(text_block, new_block_size, alignment, phdr_index); |
| 2151 | } | 2230 | } |
| 2152 | | 2231 | |
| 2153 | fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | 2232 | fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64, phdr_index: u16) !u64 { |
| 2154 | const phdr = &self.program_headers.items[block_list.phdr_index.?]; | 2233 | const shdr_index = self.phdr_shdr_table.get(phdr_index).?; |
| 2155 | const shdr = &self.sections.items[block_list.section_index.?]; | 2234 | const phdr = &self.program_headers.items[phdr_index]; |
| | 2235 | const shdr = &self.sections.items[shdr_index]; |
| 2156 | const new_block_ideal_capacity = padToIdeal(new_block_size); | 2236 | const new_block_ideal_capacity = padToIdeal(new_block_size); |
| 2157 | | 2237 | |
| 2158 | // We use these to indicate our intention to update metadata, placing the new block, | 2238 | // We use these to indicate our intention to update metadata, placing the new block, |
| ... | @@ -2162,13 +2242,14 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl | ... | @@ -2162,13 +2242,14 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl |
| 2162 | // is actually carried out at the end of the function, when errors are no longer possible. | 2242 | // is actually carried out at the end of the function, when errors are no longer possible. |
| 2163 | var block_placement: ?*TextBlock = null; | 2243 | var block_placement: ?*TextBlock = null; |
| 2164 | var free_list_removal: ?usize = null; | 2244 | var free_list_removal: ?usize = null; |
| | 2245 | var free_list = self.atom_free_lists.get(phdr_index).?; |
| 2165 | | 2246 | |
| 2166 | // First we look for an appropriately sized free list node. | 2247 | // First we look for an appropriately sized free list node. |
| 2167 | // The list is unordered. We'll just take the first thing that works. | 2248 | // The list is unordered. We'll just take the first thing that works. |
| 2168 | const vaddr = blk: { | 2249 | const vaddr = blk: { |
| 2169 | var i: usize = 0; | 2250 | var i: usize = 0; |
| 2170 | while (i < block_list.free_list.items.len) { | 2251 | while (i < free_list.items.len) { |
| 2171 | const big_block = block_list.free_list.items[i]; | 2252 | const big_block = free_list.items[i]; |
| 2172 | // We now have a pointer to a live text block that has too much capacity. | 2253 | // We now have a pointer to a live text block that has too much capacity. |
| 2173 | // Is it enough that we could fit this new text block? | 2254 | // Is it enough that we could fit this new text block? |
| 2174 | const sym = self.local_symbols.items[big_block.local_sym_index]; | 2255 | const sym = self.local_symbols.items[big_block.local_sym_index]; |
| ... | @@ -2183,7 +2264,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl | ... | @@ -2183,7 +2264,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl |
| 2183 | // should be deleted because the block that it points to has grown to take up | 2264 | // should be deleted because the block that it points to has grown to take up |
| 2184 | // more of the extra capacity. | 2265 | // more of the extra capacity. |
| 2185 | if (!big_block.freeListEligible(self.*)) { | 2266 | if (!big_block.freeListEligible(self.*)) { |
| 2186 | _ = block_list.free_list.swapRemove(i); | 2267 | _ = free_list.swapRemove(i); |
| 2187 | } else { | 2268 | } else { |
| 2188 | i += 1; | 2269 | i += 1; |
| 2189 | } | 2270 | } |
| ... | @@ -2201,7 +2282,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl | ... | @@ -2201,7 +2282,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl |
| 2201 | free_list_removal = i; | 2282 | free_list_removal = i; |
| 2202 | } | 2283 | } |
| 2203 | break :blk new_start_vaddr; | 2284 | break :blk new_start_vaddr; |
| 2204 | } else if (block_list.last_block) |last| { | 2285 | } else if (self.atoms.get(phdr_index)) |last| { |
| 2205 | const sym = self.local_symbols.items[last.local_sym_index]; | 2286 | const sym = self.local_symbols.items[last.local_sym_index]; |
| 2206 | const ideal_capacity = padToIdeal(sym.st_size); | 2287 | const ideal_capacity = padToIdeal(sym.st_size); |
| 2207 | const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; | 2288 | const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; |
| ... | @@ -2221,7 +2302,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl | ... | @@ -2221,7 +2302,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl |
| 2221 | if (needed_size > text_capacity) { | 2302 | if (needed_size > text_capacity) { |
| 2222 | // Must move the entire text section. | 2303 | // Must move the entire text section. |
| 2223 | const new_offset = self.findFreeSpace(needed_size, 0x1000); | 2304 | const new_offset = self.findFreeSpace(needed_size, 0x1000); |
| 2224 | const text_size = if (block_list.last_block) |last| blk: { | 2305 | const text_size = if (self.atoms.get(phdr_index)) |last| blk: { |
| 2225 | const sym = self.local_symbols.items[last.local_sym_index]; | 2306 | const sym = self.local_symbols.items[last.local_sym_index]; |
| 2226 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; | 2307 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; |
| 2227 | } else 0; | 2308 | } else 0; |
| ... | @@ -2230,7 +2311,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl | ... | @@ -2230,7 +2311,7 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl |
| 2230 | shdr.sh_offset = new_offset; | 2311 | shdr.sh_offset = new_offset; |
| 2231 | phdr.p_offset = new_offset; | 2312 | phdr.p_offset = new_offset; |
| 2232 | } | 2313 | } |
| 2233 | block_list.last_block = text_block; | 2314 | _ = try self.atoms.put(self.base.allocator, phdr_index, text_block); |
| 2234 | | 2315 | |
| 2235 | shdr.sh_size = needed_size; | 2316 | shdr.sh_size = needed_size; |
| 2236 | phdr.p_memsz = needed_size; | 2317 | phdr.p_memsz = needed_size; |
| ... | @@ -2268,19 +2349,11 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl | ... | @@ -2268,19 +2349,11 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl |
| 2268 | text_block.next = null; | 2349 | text_block.next = null; |
| 2269 | } | 2350 | } |
| 2270 | if (free_list_removal) |i| { | 2351 | if (free_list_removal) |i| { |
| 2271 | _ = block_list.free_list.swapRemove(i); | 2352 | _ = free_list.swapRemove(i); |
| 2272 | } | 2353 | } |
| 2273 | return vaddr; | 2354 | return vaddr; |
| 2274 | } | 2355 | } |
| 2275 | | 2356 | |
| 2276 | /// Get the block list corresponding to a specific decl | | |
| 2277 | /// For example, if the decl is a function, it returns the list of the section .text | | |
| 2278 | fn getDeclBlockList(self: *Elf, decl: *const Module.Decl) *TextBlockList { | | |
| 2279 | // const is_fn = decl.val.tag() == .function; | | |
| 2280 | const is_fn = decl.ty.zigTypeTag() == .Fn; | | |
| 2281 | return if (is_fn) &self.text_block_list else &self.rodata_block_list; | | |
| 2282 | } | | |
| 2283 | | | |
| 2284 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | 2357 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2285 | if (self.llvm_object) |_| return; | 2358 | if (self.llvm_object) |_| return; |
| 2286 | | 2359 | |
| ... | @@ -2288,6 +2361,7 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | ... | @@ -2288,6 +2361,7 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2288 | | 2361 | |
| 2289 | try self.local_symbols.ensureUnusedCapacity(self.base.allocator, 1); | 2362 | try self.local_symbols.ensureUnusedCapacity(self.base.allocator, 1); |
| 2290 | try self.offset_table.ensureUnusedCapacity(self.base.allocator, 1); | 2363 | try self.offset_table.ensureUnusedCapacity(self.base.allocator, 1); |
| | 2364 | try self.decls.putNoClobber(self.base.allocator, decl, null); |
| 2291 | | 2365 | |
| 2292 | if (self.local_symbol_free_list.popOrNull()) |i| { | 2366 | if (self.local_symbol_free_list.popOrNull()) |i| { |
| 2293 | log.debug("reusing symbol index {d} for {s}", .{ i, decl.name }); | 2367 | log.debug("reusing symbol index {d} for {s}", .{ i, decl.name }); |
| ... | @@ -2306,14 +2380,12 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | ... | @@ -2306,14 +2380,12 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2306 | self.offset_table_count_dirty = true; | 2380 | self.offset_table_count_dirty = true; |
| 2307 | } | 2381 | } |
| 2308 | | 2382 | |
| 2309 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | | |
| 2310 | | | |
| 2311 | self.local_symbols.items[decl.link.elf.local_sym_index] = .{ | 2383 | self.local_symbols.items[decl.link.elf.local_sym_index] = .{ |
| 2312 | .st_name = 0, | 2384 | .st_name = 0, |
| 2313 | .st_info = 0, | 2385 | .st_info = 0, |
| 2314 | .st_other = 0, | 2386 | .st_other = 0, |
| 2315 | .st_shndx = 0, | 2387 | .st_shndx = 0, |
| 2316 | .st_value = phdr.p_vaddr, | 2388 | .st_value = 0, |
| 2317 | .st_size = 0, | 2389 | .st_size = 0, |
| 2318 | }; | 2390 | }; |
| 2319 | self.offset_table.items[decl.link.elf.offset_table_index] = 0; | 2391 | self.offset_table.items[decl.link.elf.offset_table_index] = 0; |
| ... | @@ -2324,10 +2396,12 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { | ... | @@ -2324,10 +2396,12 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 2324 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); | 2396 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); |
| 2325 | } | 2397 | } |
| 2326 | | 2398 | |
| 2327 | const block_list = self.getDeclBlockList(decl); | 2399 | const kv = self.decls.fetchRemove(decl); |
| | 2400 | if (kv.?.value) |index| { |
| | 2401 | self.freeTextBlock(&decl.link.elf, index); |
| | 2402 | } |
| 2328 | | 2403 | |
| 2329 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | 2404 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 2330 | self.freeTextBlock(block_list, &decl.link.elf); | | |
| 2331 | if (decl.link.elf.local_sym_index != 0) { | 2405 | if (decl.link.elf.local_sym_index != 0) { |
| 2332 | self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; | 2406 | self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; |
| 2333 | self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; | 2407 | self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; |
| ... | @@ -2366,11 +2440,39 @@ fn deinitRelocs(gpa: Allocator, table: *File.DbgInfoTypeRelocsTable) void { | ... | @@ -2366,11 +2440,39 @@ fn deinitRelocs(gpa: Allocator, table: *File.DbgInfoTypeRelocsTable) void { |
| 2366 | table.deinit(gpa); | 2440 | table.deinit(gpa); |
| 2367 | } | 2441 | } |
| 2368 | | 2442 | |
| | 2443 | fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 { |
| | 2444 | const ty = decl.ty; |
| | 2445 | const zig_ty = ty.zigTypeTag(); |
| | 2446 | const val = decl.val; |
| | 2447 | const phdr_index: u16 = blk: { |
| | 2448 | if (val.isUndefDeep()) { |
| | 2449 | // TODO in release-fast and release-small, we should put undef in .bss |
| | 2450 | break :blk self.phdr_load_rw_index.?; |
| | 2451 | } |
| | 2452 | |
| | 2453 | switch (zig_ty) { |
| | 2454 | .Fn => break :blk self.phdr_load_re_index.?, |
| | 2455 | else => { |
| | 2456 | if (val.castTag(.variable)) |_| { |
| | 2457 | break :blk self.phdr_load_rw_index.?; |
| | 2458 | } |
| | 2459 | break :blk self.phdr_load_ro_index.?; |
| | 2460 | }, |
| | 2461 | } |
| | 2462 | }; |
| | 2463 | return phdr_index; |
| | 2464 | } |
| | 2465 | |
| 2369 | fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8) !*elf.Elf64_Sym { | 2466 | fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8) !*elf.Elf64_Sym { |
| 2370 | log.debug("updateDeclCode {s}{*}", .{ mem.sliceTo(decl.name, 0), decl }); | 2467 | log.debug("updateDeclCode {s}{*}", .{ mem.sliceTo(decl.name, 0), decl }); |
| 2371 | const required_alignment = decl.ty.abiAlignment(self.base.options.target); | 2468 | const required_alignment = decl.ty.abiAlignment(self.base.options.target); |
| 2372 | | 2469 | |
| 2373 | const block_list = self.getDeclBlockList(decl); | 2470 | const decl_ptr = self.decls.getPtr(decl).?; |
| | 2471 | if (decl_ptr.* == null) { |
| | 2472 | decl_ptr.* = try self.getDeclPhdrIndex(decl); |
| | 2473 | } |
| | 2474 | const phdr_index = decl_ptr.*.?; |
| | 2475 | const shdr_index = self.phdr_shdr_table.get(phdr_index).?; |
| 2374 | | 2476 | |
| 2375 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() | 2477 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() |
| 2376 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; | 2478 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; |
| ... | @@ -2379,7 +2481,7 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8 | ... | @@ -2379,7 +2481,7 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8 |
| 2379 | const need_realloc = code.len > capacity or | 2481 | const need_realloc = code.len > capacity or |
| 2380 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); | 2482 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); |
| 2381 | if (need_realloc) { | 2483 | if (need_realloc) { |
| 2382 | const vaddr = try self.growTextBlock(block_list, &decl.link.elf, code.len, required_alignment); | 2484 | const vaddr = try self.growTextBlock(&decl.link.elf, code.len, required_alignment, phdr_index); |
| 2383 | log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl.name, local_sym.st_value, vaddr }); | 2485 | log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl.name, local_sym.st_value, vaddr }); |
| 2384 | if (vaddr != local_sym.st_value) { | 2486 | if (vaddr != local_sym.st_value) { |
| 2385 | local_sym.st_value = vaddr; | 2487 | local_sym.st_value = vaddr; |
| ... | @@ -2389,28 +2491,28 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8 | ... | @@ -2389,28 +2491,28 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8 |
| 2389 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); | 2491 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); |
| 2390 | } | 2492 | } |
| 2391 | } else if (code.len < local_sym.st_size) { | 2493 | } else if (code.len < local_sym.st_size) { |
| 2392 | self.shrinkTextBlock(block_list, &decl.link.elf, code.len); | 2494 | self.shrinkTextBlock(&decl.link.elf, code.len, phdr_index); |
| 2393 | } | 2495 | } |
| 2394 | local_sym.st_size = code.len; | 2496 | local_sym.st_size = code.len; |
| 2395 | local_sym.st_name = try self.updateString(local_sym.st_name, mem.sliceTo(decl.name, 0)); | 2497 | local_sym.st_name = try self.updateString(local_sym.st_name, mem.sliceTo(decl.name, 0)); |
| 2396 | local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits; | 2498 | local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits; |
| 2397 | local_sym.st_other = 0; | 2499 | local_sym.st_other = 0; |
| 2398 | local_sym.st_shndx = block_list.section_index.?; | 2500 | local_sym.st_shndx = shdr_index; |
| 2399 | // TODO this write could be avoided if no fields of the symbol were changed. | 2501 | // TODO this write could be avoided if no fields of the symbol were changed. |
| 2400 | try self.writeSymbol(decl.link.elf.local_sym_index); | 2502 | try self.writeSymbol(decl.link.elf.local_sym_index); |
| 2401 | } else { | 2503 | } else { |
| 2402 | const decl_name = mem.sliceTo(decl.name, 0); | 2504 | const decl_name = mem.sliceTo(decl.name, 0); |
| 2403 | const name_str_index = try self.makeString(decl_name); | 2505 | const name_str_index = try self.makeString(decl_name); |
| 2404 | const vaddr = try self.allocateTextBlock(block_list, &decl.link.elf, code.len, required_alignment); | 2506 | const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment, phdr_index); |
| 2405 | errdefer self.freeTextBlock(block_list, &decl.link.elf); | 2507 | errdefer self.freeTextBlock(&decl.link.elf, phdr_index); |
| 2406 | log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, vaddr }); | 2508 | log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, vaddr }); |
| 2407 | errdefer self.freeTextBlock(block_list, &decl.link.elf); | 2509 | errdefer self.freeTextBlock(&decl.link.elf, phdr_index); |
| 2408 | | 2510 | |
| 2409 | local_sym.* = .{ | 2511 | local_sym.* = .{ |
| 2410 | .st_name = name_str_index, | 2512 | .st_name = name_str_index, |
| 2411 | .st_info = (elf.STB_LOCAL << 4) | stt_bits, | 2513 | .st_info = (elf.STB_LOCAL << 4) | stt_bits, |
| 2412 | .st_other = 0, | 2514 | .st_other = 0, |
| 2413 | .st_shndx = block_list.section_index.?, | 2515 | .st_shndx = shdr_index, |
| 2414 | .st_value = vaddr, | 2516 | .st_value = vaddr, |
| 2415 | .st_size = code.len, | 2517 | .st_size = code.len, |
| 2416 | }; | 2518 | }; |
| ... | @@ -2420,8 +2522,8 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8 | ... | @@ -2420,8 +2522,8 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8 |
| 2420 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); | 2522 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); |
| 2421 | } | 2523 | } |
| 2422 | | 2524 | |
| 2423 | const section_offset = local_sym.st_value - self.program_headers.items[block_list.phdr_index.?].p_vaddr; | 2525 | const section_offset = local_sym.st_value - self.program_headers.items[phdr_index].p_vaddr; |
| 2424 | const file_offset = self.sections.items[block_list.section_index.?].sh_offset + section_offset; | 2526 | const file_offset = self.sections.items[shdr_index].sh_offset + section_offset; |
| 2425 | try self.base.file.?.pwriteAll(code, file_offset); | 2527 | try self.base.file.?.pwriteAll(code, file_offset); |
| 2426 | | 2528 | |
| 2427 | return local_sym; | 2529 | return local_sym; |
| ... | @@ -3008,7 +3110,12 @@ pub fn updateDeclExports( | ... | @@ -3008,7 +3110,12 @@ pub fn updateDeclExports( |
| 3008 | if (decl.link.elf.local_sym_index == 0) return; | 3110 | if (decl.link.elf.local_sym_index == 0) return; |
| 3009 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; | 3111 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; |
| 3010 | | 3112 | |
| 3011 | const block_list = self.getDeclBlockList(decl); | 3113 | const decl_ptr = self.decls.getPtr(decl).?; |
| | 3114 | if (decl_ptr.* == null) { |
| | 3115 | decl_ptr.* = try self.getDeclPhdrIndex(decl); |
| | 3116 | } |
| | 3117 | const phdr_index = decl_ptr.*.?; |
| | 3118 | const shdr_index = self.phdr_shdr_table.get(phdr_index).?; |
| 3012 | | 3119 | |
| 3013 | for (exports) |exp| { | 3120 | for (exports) |exp| { |
| 3014 | if (exp.options.section) |section_name| { | 3121 | if (exp.options.section) |section_name| { |
| ... | @@ -3047,7 +3154,7 @@ pub fn updateDeclExports( | ... | @@ -3047,7 +3154,7 @@ pub fn updateDeclExports( |
| 3047 | .st_name = try self.updateString(sym.st_name, exp.options.name), | 3154 | .st_name = try self.updateString(sym.st_name, exp.options.name), |
| 3048 | .st_info = (stb_bits << 4) | stt_bits, | 3155 | .st_info = (stb_bits << 4) | stt_bits, |
| 3049 | .st_other = 0, | 3156 | .st_other = 0, |
| 3050 | .st_shndx = block_list.section_index.?, | 3157 | .st_shndx = shdr_index, |
| 3051 | .st_value = decl_sym.st_value, | 3158 | .st_value = decl_sym.st_value, |
| 3052 | .st_size = decl_sym.st_size, | 3159 | .st_size = decl_sym.st_size, |
| 3053 | }; | 3160 | }; |
| ... | @@ -3061,7 +3168,7 @@ pub fn updateDeclExports( | ... | @@ -3061,7 +3168,7 @@ pub fn updateDeclExports( |
| 3061 | .st_name = name, | 3168 | .st_name = name, |
| 3062 | .st_info = (stb_bits << 4) | stt_bits, | 3169 | .st_info = (stb_bits << 4) | stt_bits, |
| 3063 | .st_other = 0, | 3170 | .st_other = 0, |
| 3064 | .st_shndx = block_list.section_index.?, | 3171 | .st_shndx = shdr_index, |
| 3065 | .st_value = decl_sym.st_value, | 3172 | .st_value = decl_sym.st_value, |
| 3066 | .st_size = decl_sym.st_size, | 3173 | .st_size = decl_sym.st_size, |
| 3067 | }; | 3174 | }; |