| ... | ... | @@ -94,35 +94,40 @@ pub const ElfFile = struct { |
| 94 | 94 | |
| 95 | 95 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 96 | 96 | /// Same order as in the file. |
| 97 | | sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, |
| 97 | sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){}, |
| 98 | 98 | shdr_table_offset: ?u64 = null, |
| 99 | 99 | |
| 100 | 100 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 101 | 101 | /// Same order as in the file. |
| 102 | | program_headers: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, |
| 102 | program_headers: std.ArrayListUnmanaged(elf.Elf64_Phdr) = std.ArrayListUnmanaged(elf.Elf64_Phdr){}, |
| 103 | 103 | phdr_table_offset: ?u64 = null, |
| 104 | 104 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags |
| 105 | 105 | phdr_load_re_index: ?u16 = null, |
| 106 | /// The index into the program headers of the global offset table. |
| 107 | /// It needs PT_LOAD and Read flags. |
| 108 | phdr_got_index: ?u16 = null, |
| 106 | 109 | entry_addr: ?u64 = null, |
| 107 | 110 | |
| 108 | | shstrtab: std.ArrayListUnmanaged(u8) = .{}, |
| 111 | shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, |
| 109 | 112 | shstrtab_index: ?u16 = null, |
| 110 | 113 | |
| 111 | 114 | text_section_index: ?u16 = null, |
| 112 | 115 | symtab_section_index: ?u16 = null, |
| 116 | got_section_index: ?u16 = null, |
| 113 | 117 | |
| 114 | 118 | /// The same order as in the file |
| 115 | | symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, |
| 119 | symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = std.ArrayListUnmanaged(elf.Elf64_Sym){}, |
| 116 | 120 | |
| 117 | | /// Same order as in the file. |
| 118 | | offset_table: std.ArrayListUnmanaged(aoeu) = .{}, |
| 121 | /// Same order as in the file. The value is the absolute vaddr value. |
| 122 | /// If the vaddr of the executable program header changes, the entire |
| 123 | /// offset table needs to be rewritten. |
| 124 | offset_table: std.ArrayListUnmanaged(u64) = std.ArrayListUnmanaged(u64){}, |
| 119 | 125 | |
| 120 | | /// This means the entire read-only executable program code needs to be rewritten. |
| 121 | | phdr_load_re_dirty: bool = false, |
| 122 | 126 | phdr_table_dirty: bool = false, |
| 123 | 127 | shdr_table_dirty: bool = false, |
| 124 | 128 | shstrtab_dirty: bool = false, |
| 125 | | symtab_dirty: bool = false, |
| 129 | offset_table_count_dirty: bool = false, |
| 130 | symbol_count_dirty: bool = false, |
| 126 | 131 | |
| 127 | 132 | error_flags: ErrorFlags = ErrorFlags{}, |
| 128 | 133 | |
| ... | ... | @@ -130,18 +135,25 @@ pub const ElfFile = struct { |
| 130 | 135 | no_entry_point_found: bool = false, |
| 131 | 136 | }; |
| 132 | 137 | |
| 133 | | /// TODO it's too bad this optional takes up double the memory it should |
| 134 | 138 | pub const Decl = struct { |
| 135 | 139 | /// Each decl always gets a local symbol with the fully qualified name. |
| 136 | 140 | /// The vaddr and size are found here directly. |
| 137 | 141 | /// The file offset is found by computing the vaddr offset from the section vaddr |
| 138 | 142 | /// the symbol references, and adding that to the file offset of the section. |
| 139 | | local_sym_index: ?usize = null, |
| 143 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or |
| 144 | /// offset table entry. |
| 145 | local_sym_index: u32, |
| 146 | /// This field is undefined for symbols with size = 0. |
| 147 | offset_table_index: u32, |
| 148 | |
| 149 | pub const empty = Decl{ |
| 150 | .local_sym_index = 0, |
| 151 | .offset_table_index = undefined, |
| 152 | }; |
| 140 | 153 | }; |
| 141 | 154 | |
| 142 | | /// TODO it's too bad this optional takes up double the memory it should |
| 143 | 155 | pub const Export = struct { |
| 144 | | sym_index: ?usize = null, |
| 156 | sym_index: usize, |
| 145 | 157 | }; |
| 146 | 158 | |
| 147 | 159 | pub fn deinit(self: *ElfFile) void { |
| ... | ... | @@ -250,33 +262,57 @@ pub const ElfFile = struct { |
| 250 | 262 | .p32 => true, |
| 251 | 263 | .p64 => false, |
| 252 | 264 | }; |
| 265 | const ptr_size: u8 = switch (self.ptr_width) { |
| 266 | .p32 => 4, |
| 267 | .p64 => 8, |
| 268 | }; |
| 253 | 269 | if (self.phdr_load_re_index == null) { |
| 254 | 270 | self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len); |
| 255 | 271 | const file_size = self.options.program_code_size_hint; |
| 256 | 272 | const p_align = 0x1000; |
| 257 | 273 | const off = self.findFreeSpace(file_size, p_align); |
| 258 | 274 | //std.debug.warn("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 259 | | try self.program_headers.append(.{ |
| 275 | try self.program_headers.append(self.allocator, .{ |
| 260 | 276 | .p_type = elf.PT_LOAD, |
| 261 | 277 | .p_offset = off, |
| 262 | 278 | .p_filesz = file_size, |
| 263 | 279 | .p_vaddr = default_entry_addr, |
| 264 | 280 | .p_paddr = default_entry_addr, |
| 265 | | .p_memsz = 0, |
| 281 | .p_memsz = file_size, |
| 266 | 282 | .p_align = p_align, |
| 267 | 283 | .p_flags = elf.PF_X | elf.PF_R, |
| 268 | 284 | }); |
| 269 | 285 | self.entry_addr = null; |
| 270 | | self.phdr_load_re_dirty = true; |
| 286 | self.phdr_table_dirty = true; |
| 287 | } |
| 288 | if (self.phdr_got_index == null) { |
| 289 | self.phdr_got_index = @intCast(u16, self.program_headers.items.len); |
| 290 | const file_size = @as(u64, ptr_size) * self.options.symbol_count_hint; |
| 291 | const off = self.findFreeSpace(file_size, ptr_size); |
| 292 | //std.debug.warn("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 293 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. |
| 294 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something |
| 295 | // else in virtual memory. |
| 296 | const default_got_addr = 0x80000000; |
| 297 | try self.program_headers.append(self.allocator, .{ |
| 298 | .p_type = elf.PT_LOAD, |
| 299 | .p_offset = off, |
| 300 | .p_filesz = file_size, |
| 301 | .p_vaddr = default_got_addr, |
| 302 | .p_paddr = default_got_addr, |
| 303 | .p_memsz = file_size, |
| 304 | .p_align = ptr_size, |
| 305 | .p_flags = elf.PF_R, |
| 306 | }); |
| 271 | 307 | self.phdr_table_dirty = true; |
| 272 | 308 | } |
| 273 | 309 | if (self.shstrtab_index == null) { |
| 274 | 310 | self.shstrtab_index = @intCast(u16, self.sections.items.len); |
| 275 | 311 | assert(self.shstrtab.items.len == 0); |
| 276 | | try self.shstrtab.append(0); // need a 0 at position 0 |
| 312 | try self.shstrtab.append(self.allocator, 0); // need a 0 at position 0 |
| 277 | 313 | const off = self.findFreeSpace(self.shstrtab.items.len, 1); |
| 278 | 314 | //std.debug.warn("found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len }); |
| 279 | | try self.sections.append(.{ |
| 315 | try self.sections.append(self.allocator, .{ |
| 280 | 316 | .sh_name = try self.makeString(".shstrtab"), |
| 281 | 317 | .sh_type = elf.SHT_STRTAB, |
| 282 | 318 | .sh_flags = 0, |
| ... | ... | @@ -295,7 +331,7 @@ pub const ElfFile = struct { |
| 295 | 331 | self.text_section_index = @intCast(u16, self.sections.items.len); |
| 296 | 332 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 297 | 333 | |
| 298 | | try self.sections.append(.{ |
| 334 | try self.sections.append(self.allocator, .{ |
| 299 | 335 | .sh_name = try self.makeString(".text"), |
| 300 | 336 | .sh_type = elf.SHT_PROGBITS, |
| 301 | 337 | .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| ... | ... | @@ -309,6 +345,24 @@ pub const ElfFile = struct { |
| 309 | 345 | }); |
| 310 | 346 | self.shdr_table_dirty = true; |
| 311 | 347 | } |
| 348 | if (self.got_section_index == null) { |
| 349 | self.got_section_index = @intCast(u16, self.sections.items.len); |
| 350 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; |
| 351 | |
| 352 | try self.sections.append(self.allocator, .{ |
| 353 | .sh_name = try self.makeString(".got"), |
| 354 | .sh_type = elf.SHT_PROGBITS, |
| 355 | .sh_flags = elf.SHF_ALLOC, |
| 356 | .sh_addr = phdr.p_vaddr, |
| 357 | .sh_offset = phdr.p_offset, |
| 358 | .sh_size = phdr.p_filesz, |
| 359 | .sh_link = 0, |
| 360 | .sh_info = 0, |
| 361 | .sh_addralign = phdr.p_align, |
| 362 | .sh_entsize = ptr_size, |
| 363 | }); |
| 364 | self.shdr_table_dirty = true; |
| 365 | } |
| 312 | 366 | if (self.symtab_section_index == null) { |
| 313 | 367 | self.symtab_section_index = @intCast(u16, self.sections.items.len); |
| 314 | 368 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); |
| ... | ... | @@ -317,7 +371,7 @@ pub const ElfFile = struct { |
| 317 | 371 | const off = self.findFreeSpace(file_size, min_align); |
| 318 | 372 | //std.debug.warn("found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 319 | 373 | |
| 320 | | try self.sections.append(.{ |
| 374 | try self.sections.append(self.allocator, .{ |
| 321 | 375 | .sh_name = try self.makeString(".symtab"), |
| 322 | 376 | .sh_type = elf.SHT_SYMTAB, |
| 323 | 377 | .sh_flags = 0, |
| ... | ... | @@ -330,14 +384,14 @@ pub const ElfFile = struct { |
| 330 | 384 | .sh_addralign = min_align, |
| 331 | 385 | .sh_entsize = each_size, |
| 332 | 386 | }); |
| 333 | | self.symtab_dirty = true; |
| 334 | 387 | self.shdr_table_dirty = true; |
| 388 | try self.writeAllSymbols(); |
| 335 | 389 | } |
| 336 | | const shsize: u64 = switch (ptr_width) { |
| 390 | const shsize: u64 = switch (self.ptr_width) { |
| 337 | 391 | .p32 => @sizeOf(elf.Elf32_Shdr), |
| 338 | 392 | .p64 => @sizeOf(elf.Elf64_Shdr), |
| 339 | 393 | }; |
| 340 | | const shalign: u16 = switch (ptr_width) { |
| 394 | const shalign: u16 = switch (self.ptr_width) { |
| 341 | 395 | .p32 => @alignOf(elf.Elf32_Shdr), |
| 342 | 396 | .p64 => @alignOf(elf.Elf64_Shdr), |
| 343 | 397 | }; |
| ... | ... | @@ -345,11 +399,11 @@ pub const ElfFile = struct { |
| 345 | 399 | self.shdr_table_offset = self.findFreeSpace(self.sections.items.len * shsize, shalign); |
| 346 | 400 | self.shdr_table_dirty = true; |
| 347 | 401 | } |
| 348 | | const phsize: u64 = switch (ptr_width) { |
| 402 | const phsize: u64 = switch (self.ptr_width) { |
| 349 | 403 | .p32 => @sizeOf(elf.Elf32_Phdr), |
| 350 | 404 | .p64 => @sizeOf(elf.Elf64_Phdr), |
| 351 | 405 | }; |
| 352 | | const phalign: u16 = switch (ptr_width) { |
| 406 | const phalign: u16 = switch (self.ptr_width) { |
| 353 | 407 | .p32 => @alignOf(elf.Elf32_Phdr), |
| 354 | 408 | .p64 => @alignOf(elf.Elf64_Phdr), |
| 355 | 409 | }; |
| ... | ... | @@ -399,7 +453,7 @@ pub const ElfFile = struct { |
| 399 | 453 | try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); |
| 400 | 454 | }, |
| 401 | 455 | } |
| 402 | | self.phdr_table_offset = false; |
| 456 | self.phdr_table_dirty = false; |
| 403 | 457 | } |
| 404 | 458 | |
| 405 | 459 | { |
| ... | ... | @@ -432,11 +486,10 @@ pub const ElfFile = struct { |
| 432 | 486 | self.shdr_table_offset = self.findFreeSpace(needed_size, phalign); |
| 433 | 487 | } |
| 434 | 488 | |
| 435 | | const allocator = self.sections.allocator; |
| 436 | 489 | switch (self.ptr_width) { |
| 437 | 490 | .p32 => { |
| 438 | | const buf = try allocator.alloc(elf.Elf32_Shdr, self.sections.items.len); |
| 439 | | defer allocator.free(buf); |
| 491 | const buf = try self.allocator.alloc(elf.Elf32_Shdr, self.sections.items.len); |
| 492 | defer self.allocator.free(buf); |
| 440 | 493 | |
| 441 | 494 | for (buf) |*shdr, i| { |
| 442 | 495 | shdr.* = sectHeaderTo32(self.sections.items[i]); |
| ... | ... | @@ -447,8 +500,8 @@ pub const ElfFile = struct { |
| 447 | 500 | try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 448 | 501 | }, |
| 449 | 502 | .p64 => { |
| 450 | | const buf = try allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); |
| 451 | | defer allocator.free(buf); |
| 503 | const buf = try self.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); |
| 504 | defer self.allocator.free(buf); |
| 452 | 505 | |
| 453 | 506 | for (buf) |*shdr, i| { |
| 454 | 507 | shdr.* = self.sections.items[i]; |
| ... | ... | @@ -460,6 +513,7 @@ pub const ElfFile = struct { |
| 460 | 513 | try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 461 | 514 | }, |
| 462 | 515 | } |
| 516 | self.shdr_table_dirty = false; |
| 463 | 517 | } |
| 464 | 518 | if (self.entry_addr == null and self.options.output_mode == .Exe) { |
| 465 | 519 | self.error_flags.no_entry_point_found = true; |
| ... | ... | @@ -470,11 +524,11 @@ pub const ElfFile = struct { |
| 470 | 524 | // TODO find end pos and truncate |
| 471 | 525 | |
| 472 | 526 | // The point of flush() is to commit changes, so nothing should be dirty after this. |
| 473 | | assert(!self.phdr_load_re_dirty); |
| 474 | 527 | assert(!self.phdr_table_dirty); |
| 475 | 528 | assert(!self.shdr_table_dirty); |
| 476 | 529 | assert(!self.shstrtab_dirty); |
| 477 | | assert(!self.symtab_dirty); |
| 530 | assert(!self.symbol_count_dirty); |
| 531 | assert(!self.offset_table_count_dirty); |
| 478 | 532 | } |
| 479 | 533 | |
| 480 | 534 | fn writeElfHeader(self: *ElfFile) !void { |
| ... | ... | @@ -608,6 +662,7 @@ pub const ElfFile = struct { |
| 608 | 662 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 609 | 663 | const shdr = &self.sections.items[self.text_section_index.?]; |
| 610 | 664 | |
| 665 | // TODO Also detect virtual address collisions. |
| 611 | 666 | const text_capacity = self.allocatedSize(shdr.sh_offset); |
| 612 | 667 | // TODO instead of looping here, maintain a free list and a pointer to the end. |
| 613 | 668 | const end_vaddr = blk: { |
| ... | ... | @@ -664,7 +719,7 @@ pub const ElfFile = struct { |
| 664 | 719 | defer code.deinit(); |
| 665 | 720 | |
| 666 | 721 | const typed_value = decl.typed_value.most_recent.typed_value; |
| 667 | | const err_msg = try codegen.generateSymbol(typed_value, module, &code, module.allocator); |
| 722 | const err_msg = try codegen.generateSymbol(typed_value, module, &code); |
| 668 | 723 | if (err_msg != null) |em| { |
| 669 | 724 | decl.analysis = .codegen_failure; |
| 670 | 725 | _ = try module.failed_decls.put(decl, em); |
| ... | ... | @@ -678,26 +733,31 @@ pub const ElfFile = struct { |
| 678 | 733 | else => elf.STT_OBJECT, |
| 679 | 734 | }; |
| 680 | 735 | |
| 681 | | if (decl.link.local_sym_index) |local_sym_index| { |
| 682 | | const local_sym = &self.symbols.items[local_sym_index]; |
| 736 | if (decl.link.local_sym_index != 0) { |
| 737 | const local_sym = &self.symbols.items[decl.link.local_sym_index]; |
| 683 | 738 | const existing_block = self.findAllocatedTextBlock(local_sym); |
| 684 | 739 | const file_offset = if (code_size > existing_block.size_capacity) fo: { |
| 685 | | const new_block = self.allocateTextBlock(code_size); |
| 740 | const new_block = try self.allocateTextBlock(code_size); |
| 686 | 741 | local_sym.st_value = new_block.vaddr; |
| 687 | 742 | local_sym.st_size = code_size; |
| 743 | |
| 744 | try self.writeOffsetTableEntry(decl.link.offset_table_index); |
| 745 | |
| 688 | 746 | break :fo new_block.file_offset; |
| 689 | 747 | } else existing_block.file_offset; |
| 690 | 748 | local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(u8, decl.name)); |
| 691 | 749 | local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits; |
| 692 | 750 | // TODO this write could be avoided if no fields of the symbol were changed. |
| 693 | | try self.writeSymbol(local_sym_index); |
| 751 | try self.writeSymbol(decl.link.local_sym_index); |
| 694 | 752 | break :blk file_offset; |
| 695 | 753 | } else { |
| 696 | 754 | try self.symbols.ensureCapacity(self.symbols.items.len + 1); |
| 755 | try self.offset_table.ensureCapacity(self.offset_table.items.len + 1); |
| 697 | 756 | const decl_name = mem.spanZ(u8, decl.name); |
| 698 | 757 | const name_str_index = try self.makeString(decl_name); |
| 699 | | const new_block = self.allocateTextBlock(code_size); |
| 758 | const new_block = try self.allocateTextBlock(code_size); |
| 700 | 759 | const local_sym_index = self.symbols.items.len; |
| 760 | const offset_table_index = self.offset_table.items.len; |
| 701 | 761 | |
| 702 | 762 | self.symbols.appendAssumeCapacity(self.allocator, .{ |
| 703 | 763 | .st_name = name_str_index, |
| ... | ... | @@ -708,10 +768,17 @@ pub const ElfFile = struct { |
| 708 | 768 | .st_size = code_size, |
| 709 | 769 | }); |
| 710 | 770 | errdefer self.symbols.shrink(self.symbols.items.len - 1); |
| 771 | self.offset_table.appendAssumeCapacity(self.allocator, new_block.vaddr); |
| 772 | errdefer self.offset_table.shrink(self.offset_table.items.len - 1); |
| 711 | 773 | try self.writeSymbol(local_sym_index); |
| 774 | try self.writeOffsetTableEntry(offset_table_index); |
| 712 | 775 | |
| 713 | 776 | self.symbol_count_dirty = true; |
| 714 | | decl.link.local_sym_index = local_sym_index; |
| 777 | self.offset_table_count_dirty = true; |
| 778 | decl.link = .{ |
| 779 | .local_sym_index = local_sym_index, |
| 780 | .offset_table_index = offset_table_index, |
| 781 | }; |
| 715 | 782 | |
| 716 | 783 | break :blk new_block.file_offset; |
| 717 | 784 | } |
| ... | ... | @@ -839,6 +906,45 @@ pub const ElfFile = struct { |
| 839 | 906 | } |
| 840 | 907 | } |
| 841 | 908 | |
| 909 | fn writeOffsetTableEntry(self: *ElfFile, index: usize) !void { |
| 910 | const shdr = &self.sections.items[self.got_section_index.?]; |
| 911 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; |
| 912 | if (self.offset_table_count_dirty) { |
| 913 | // TODO Also detect virtual address collisions. |
| 914 | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| 915 | const needed_size = self.symbols.items.len * shdr.sh_entsize; |
| 916 | if (needed_size > allocated_size) { |
| 917 | // Must move the entire got section. |
| 918 | const new_offset = self.findFreeSpace(needed_size, shdr.sh_entsize); |
| 919 | const amt = try self.file.copyRangeAll(shdr.sh_offset, self.file, new_offset, shdr.sh_size); |
| 920 | if (amt != text_size) return error.InputOutput; |
| 921 | shdr.sh_offset = new_offset; |
| 922 | } |
| 923 | shdr.sh_size = needed_size; |
| 924 | phdr.p_memsz = needed_size; |
| 925 | phdr.p_filesz = needed_size; |
| 926 | |
| 927 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty |
| 928 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty |
| 929 | |
| 930 | self.offset_table_count_dirty = false; |
| 931 | } |
| 932 | const endian = self.options.target.cpu.arch.endian(); |
| 933 | const off = shdr.sh_offset + shdr.sh_entsize * index; |
| 934 | switch (self.ptr_width) { |
| 935 | .p32 => { |
| 936 | var buf: [4]u8 = undefined; |
| 937 | mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian); |
| 938 | try self.file.pwriteAll(&buf, off); |
| 939 | }, |
| 940 | .p64 => { |
| 941 | var buf: [8]u8 = undefined; |
| 942 | mem.writeInt(u64, &buf, self.offset_table.items[index], endian); |
| 943 | try self.file.pwriteAll(&buf, off); |
| 944 | }, |
| 945 | } |
| 946 | } |
| 947 | |
| 842 | 948 | fn writeSymbol(self: *ElfFile, index: usize) !void { |
| 843 | 949 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; |
| 844 | 950 | // Make sure we are not pointlessly writing symbol data that will have to get relocated |
| ... | ... | @@ -849,6 +955,9 @@ pub const ElfFile = struct { |
| 849 | 955 | if (needed_size > allocated_size) { |
| 850 | 956 | return self.writeAllSymbols(); |
| 851 | 957 | } |
| 958 | syms_sect.sh_info = @intCast(u32, self.symbols.items.len); |
| 959 | self.shdr_table_dirty = true; // TODO look into only writing one section |
| 960 | self.symbol_count_dirty = false; |
| 852 | 961 | } |
| 853 | 962 | const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); |
| 854 | 963 | switch (self.ptr_width) { |
| ... | ... | @@ -896,12 +1005,13 @@ pub const ElfFile = struct { |
| 896 | 1005 | //std.debug.warn("symtab start=0x{x} end=0x{x}\n", .{ syms_sect.sh_offset, syms_sect.sh_offset + needed_size }); |
| 897 | 1006 | syms_sect.sh_size = needed_size; |
| 898 | 1007 | syms_sect.sh_info = @intCast(u32, self.symbols.items.len); |
| 899 | | const allocator = self.symbols.allocator; |
| 1008 | self.symbol_count_dirty = false; |
| 1009 | self.shdr_table_dirty = true; // TODO look into only writing one section |
| 900 | 1010 | const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); |
| 901 | 1011 | switch (self.ptr_width) { |
| 902 | 1012 | .p32 => { |
| 903 | | const buf = try allocator.alloc(elf.Elf32_Sym, self.symbols.items.len); |
| 904 | | defer allocator.free(buf); |
| 1013 | const buf = try self.allocator.alloc(elf.Elf32_Sym, self.symbols.items.len); |
| 1014 | defer self.allocator.free(buf); |
| 905 | 1015 | |
| 906 | 1016 | for (buf) |*sym, i| { |
| 907 | 1017 | sym.* = .{ |
| ... | ... | @@ -919,8 +1029,8 @@ pub const ElfFile = struct { |
| 919 | 1029 | try self.file.pwriteAll(mem.sliceAsBytes(buf), syms_sect.sh_offset); |
| 920 | 1030 | }, |
| 921 | 1031 | .p64 => { |
| 922 | | const buf = try allocator.alloc(elf.Elf64_Sym, self.symbols.items.len); |
| 923 | | defer allocator.free(buf); |
| 1032 | const buf = try self.allocator.alloc(elf.Elf64_Sym, self.symbols.items.len); |
| 1033 | defer self.allocator.free(buf); |
| 924 | 1034 | |
| 925 | 1035 | for (buf) |*sym, i| { |
| 926 | 1036 | sym.* = .{ |
| ... | ... | @@ -961,12 +1071,11 @@ pub fn createElfFile(allocator: *Allocator, file: fs.File, options: Options) !El |
| 961 | 1071 | .allocator = allocator, |
| 962 | 1072 | .file = file, |
| 963 | 1073 | .options = options, |
| 964 | | .ptr_width = switch (self.options.target.cpu.arch.ptrBitWidth()) { |
| 1074 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { |
| 965 | 1075 | 32 => .p32, |
| 966 | 1076 | 64 => .p64, |
| 967 | 1077 | else => return error.UnsupportedELFArchitecture, |
| 968 | 1078 | }, |
| 969 | | .symtab_dirty = true, |
| 970 | 1079 | .shdr_table_dirty = true, |
| 971 | 1080 | }; |
| 972 | 1081 | errdefer self.deinit(); |
| ... | ... | @@ -1018,7 +1127,7 @@ fn openBinFileInner(allocator: *Allocator, file: fs.File, options: Options) !Elf |
| 1018 | 1127 | .allocator = allocator, |
| 1019 | 1128 | .file = file, |
| 1020 | 1129 | .options = options, |
| 1021 | | .ptr_width = switch (self.options.target.cpu.arch.ptrBitWidth()) { |
| 1130 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { |
| 1022 | 1131 | 32 => .p32, |
| 1023 | 1132 | 64 => .p64, |
| 1024 | 1133 | else => return error.UnsupportedELFArchitecture, |