| ... | @@ -47,8 +47,13 @@ got: GotSection = .{}, | ... | @@ -47,8 +47,13 @@ got: GotSection = .{}, |
| 47 | | 47 | |
| 48 | text_section_index: ?u16 = null, | 48 | text_section_index: ?u16 = null, |
| 49 | rodata_section_index: ?u16 = null, | 49 | rodata_section_index: ?u16 = null, |
| 50 | got_section_index: ?u16 = null, | | |
| 51 | data_section_index: ?u16 = null, | 50 | data_section_index: ?u16 = null, |
| | 51 | dynamic_section_index: ?u16 = null, |
| | 52 | got_section_index: ?u16 = null, |
| | 53 | got_plt_section_index: ?u16 = null, |
| | 54 | plt_section_index: ?u16 = null, |
| | 55 | eh_frame_hdr_section_index: ?u16 = null, |
| | 56 | rela_dyn_section_index: ?u16 = null, |
| 52 | debug_info_section_index: ?u16 = null, | 57 | debug_info_section_index: ?u16 = null, |
| 53 | debug_abbrev_section_index: ?u16 = null, | 58 | debug_abbrev_section_index: ?u16 = null, |
| 54 | debug_str_section_index: ?u16 = null, | 59 | debug_str_section_index: ?u16 = null, |
| ... | @@ -74,6 +79,7 @@ gnu_eh_frame_hdr_index: ?Symbol.Index = null, | ... | @@ -74,6 +79,7 @@ gnu_eh_frame_hdr_index: ?Symbol.Index = null, |
| 74 | dso_handle_index: ?Symbol.Index = null, | 79 | dso_handle_index: ?Symbol.Index = null, |
| 75 | rela_iplt_start_index: ?Symbol.Index = null, | 80 | rela_iplt_start_index: ?Symbol.Index = null, |
| 76 | rela_iplt_end_index: ?Symbol.Index = null, | 81 | rela_iplt_end_index: ?Symbol.Index = null, |
| | 82 | start_stop_indexes: std.ArrayListUnmanaged(u32) = .{}, |
| 77 | | 83 | |
| 78 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | 84 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 79 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | 85 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, |
| ... | @@ -264,6 +270,7 @@ pub fn deinit(self: *Elf) void { | ... | @@ -264,6 +270,7 @@ pub fn deinit(self: *Elf) void { |
| 264 | self.got.deinit(gpa); | 270 | self.got.deinit(gpa); |
| 265 | self.resolver.deinit(gpa); | 271 | self.resolver.deinit(gpa); |
| 266 | self.unresolved.deinit(gpa); | 272 | self.unresolved.deinit(gpa); |
| | 273 | self.start_stop_indexes.deinit(gpa); |
| 267 | | 274 | |
| 268 | { | 275 | { |
| 269 | var it = self.decls.iterator(); | 276 | var it = self.decls.iterator(); |
| ... | @@ -385,6 +392,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -385,6 +392,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 385 | .p64 => false, | 392 | .p64 => false, |
| 386 | }; | 393 | }; |
| 387 | const ptr_size: u8 = self.ptrWidthBytes(); | 394 | const ptr_size: u8 = self.ptrWidthBytes(); |
| | 395 | const image_base = self.calcImageBase(); |
| 388 | | 396 | |
| 389 | if (self.phdr_table_index == null) { | 397 | if (self.phdr_table_index == null) { |
| 390 | self.phdr_table_index = @as(u16, @intCast(self.phdrs.items.len)); | 398 | self.phdr_table_index = @as(u16, @intCast(self.phdrs.items.len)); |
| ... | @@ -396,8 +404,8 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -396,8 +404,8 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 396 | .p_type = elf.PT_PHDR, | 404 | .p_type = elf.PT_PHDR, |
| 397 | .p_offset = 0, | 405 | .p_offset = 0, |
| 398 | .p_filesz = 0, | 406 | .p_filesz = 0, |
| 399 | .p_vaddr = 0, | 407 | .p_vaddr = image_base, |
| 400 | .p_paddr = 0, | 408 | .p_paddr = image_base, |
| 401 | .p_memsz = 0, | 409 | .p_memsz = 0, |
| 402 | .p_align = p_align, | 410 | .p_align = p_align, |
| 403 | .p_flags = elf.PF_R, | 411 | .p_flags = elf.PF_R, |
| ... | @@ -408,16 +416,14 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -408,16 +416,14 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 408 | if (self.phdr_table_load_index == null) { | 416 | if (self.phdr_table_load_index == null) { |
| 409 | self.phdr_table_load_index = @as(u16, @intCast(self.phdrs.items.len)); | 417 | self.phdr_table_load_index = @as(u16, @intCast(self.phdrs.items.len)); |
| 410 | // TODO Same as for GOT | 418 | // TODO Same as for GOT |
| 411 | const phdr_addr: u64 = if (self.base.options.target.ptrBitWidth() >= 32) 0x1000000 else 0x1000; | | |
| 412 | const p_align = self.page_size; | | |
| 413 | try self.phdrs.append(gpa, .{ | 419 | try self.phdrs.append(gpa, .{ |
| 414 | .p_type = elf.PT_LOAD, | 420 | .p_type = elf.PT_LOAD, |
| 415 | .p_offset = 0, | 421 | .p_offset = 0, |
| 416 | .p_filesz = 0, | 422 | .p_filesz = 0, |
| 417 | .p_vaddr = phdr_addr, | 423 | .p_vaddr = image_base, |
| 418 | .p_paddr = phdr_addr, | 424 | .p_paddr = image_base, |
| 419 | .p_memsz = 0, | 425 | .p_memsz = 0, |
| 420 | .p_align = p_align, | 426 | .p_align = self.page_size, |
| 421 | .p_flags = elf.PF_R, | 427 | .p_flags = elf.PF_R, |
| 422 | }); | 428 | }); |
| 423 | self.phdr_table_dirty = true; | 429 | self.phdr_table_dirty = true; |
| ... | @@ -429,7 +435,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -429,7 +435,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 429 | const p_align = self.page_size; | 435 | const p_align = self.page_size; |
| 430 | const off = self.findFreeSpace(file_size, p_align); | 436 | const off = self.findFreeSpace(file_size, p_align); |
| 431 | log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size }); | 437 | log.debug("found PT_LOAD RE free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 432 | const entry_addr: u64 = self.entry_addr orelse if (self.base.options.target.cpu.arch == .spu_2) @as(u64, 0) else default_entry_addr; | 438 | const entry_addr = self.defaultEntryAddress(); |
| 433 | try self.phdrs.append(gpa, .{ | 439 | try self.phdrs.append(gpa, .{ |
| 434 | .p_type = elf.PT_LOAD, | 440 | .p_type = elf.PT_LOAD, |
| 435 | .p_offset = off, | 441 | .p_offset = off, |
| ... | @@ -1055,6 +1061,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1055,6 +1061,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1055 | | 1061 | |
| 1056 | try self.addLinkerDefinedSymbols(); | 1062 | try self.addLinkerDefinedSymbols(); |
| 1057 | | 1063 | |
| | 1064 | self.allocateLinkerDefinedSymbols(); |
| | 1065 | |
| 1058 | // Beyond this point, everything has been allocated a virtual address and we can resolve | 1066 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| 1059 | // the relocations. | 1067 | // the relocations. |
| 1060 | { | 1068 | { |
| ... | @@ -2764,6 +2772,129 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { | ... | @@ -2764,6 +2772,129 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { |
| 2764 | linker_defined.resolveSymbols(self); | 2772 | linker_defined.resolveSymbols(self); |
| 2765 | } | 2773 | } |
| 2766 | | 2774 | |
| | 2775 | fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| | 2776 | // _DYNAMIC |
| | 2777 | if (self.dynamic_section_index) |shndx| { |
| | 2778 | const shdr = self.sections.items(.shdr)[shndx]; |
| | 2779 | const symbol_ptr = self.symbol(self.dynamic_index.?); |
| | 2780 | symbol_ptr.value = shdr.sh_addr; |
| | 2781 | symbol_ptr.output_section_index = shndx; |
| | 2782 | } |
| | 2783 | |
| | 2784 | // __ehdr_start |
| | 2785 | { |
| | 2786 | const symbol_ptr = self.symbol(self.ehdr_start_index.?); |
| | 2787 | symbol_ptr.value = self.calcImageBase(); |
| | 2788 | symbol_ptr.output_section_index = 1; |
| | 2789 | } |
| | 2790 | |
| | 2791 | // __init_array_start, __init_array_end |
| | 2792 | if (self.sectionByName(".init_array")) |shndx| { |
| | 2793 | const start_sym = self.symbol(self.init_array_start_index.?); |
| | 2794 | const end_sym = self.symbol(self.init_array_end_index.?); |
| | 2795 | const shdr = &self.sections.items(.shdr)[shndx]; |
| | 2796 | start_sym.output_section_index = shndx; |
| | 2797 | start_sym.value = shdr.sh_addr; |
| | 2798 | end_sym.output_section_index = shndx; |
| | 2799 | end_sym.value = shdr.sh_addr + shdr.sh_size; |
| | 2800 | } |
| | 2801 | |
| | 2802 | // __fini_array_start, __fini_array_end |
| | 2803 | if (self.sectionByName(".fini_array")) |shndx| { |
| | 2804 | const start_sym = self.symbol(self.fini_array_start_index.?); |
| | 2805 | const end_sym = self.symbol(self.fini_array_end_index.?); |
| | 2806 | const shdr = &self.sections.items(.shdr)[shndx]; |
| | 2807 | start_sym.output_section_index = shndx; |
| | 2808 | start_sym.value = shdr.sh_addr; |
| | 2809 | end_sym.output_section_index = shndx; |
| | 2810 | end_sym.value = shdr.sh_addr + shdr.sh_size; |
| | 2811 | } |
| | 2812 | |
| | 2813 | // __preinit_array_start, __preinit_array_end |
| | 2814 | if (self.sectionByName(".preinit_array")) |shndx| { |
| | 2815 | const start_sym = self.symbol(self.preinit_array_start_index.?); |
| | 2816 | const end_sym = self.symbol(self.preinit_array_end_index.?); |
| | 2817 | const shdr = &self.sections.items(.shdr)[shndx]; |
| | 2818 | start_sym.output_section_index = shndx; |
| | 2819 | start_sym.value = shdr.sh_addr; |
| | 2820 | end_sym.output_section_index = shndx; |
| | 2821 | end_sym.value = shdr.sh_addr + shdr.sh_size; |
| | 2822 | } |
| | 2823 | |
| | 2824 | // _GLOBAL_OFFSET_TABLE_ |
| | 2825 | if (self.got_plt_section_index) |shndx| { |
| | 2826 | const shdr = &self.sections.items(.shdr)[shndx]; |
| | 2827 | const symbol_ptr = self.symbol(self.got_index.?); |
| | 2828 | symbol_ptr.value = shdr.sh_addr; |
| | 2829 | symbol_ptr.output_section_index = shndx; |
| | 2830 | } |
| | 2831 | |
| | 2832 | // _PROCEDURE_LINKAGE_TABLE_ |
| | 2833 | if (self.plt_section_index) |shndx| { |
| | 2834 | const shdr = &self.sections.items(.shdr)[shndx]; |
| | 2835 | const symbol_ptr = self.symbol(self.plt_index.?); |
| | 2836 | symbol_ptr.value = shdr.sh_addr; |
| | 2837 | symbol_ptr.output_section_index = shndx; |
| | 2838 | } |
| | 2839 | |
| | 2840 | // __dso_handle |
| | 2841 | if (self.dso_handle_index) |index| { |
| | 2842 | const shdr = &self.sections.items(.shdr)[1]; |
| | 2843 | const symbol_ptr = self.symbol(index); |
| | 2844 | symbol_ptr.value = shdr.sh_addr; |
| | 2845 | symbol_ptr.output_section_index = 0; |
| | 2846 | } |
| | 2847 | |
| | 2848 | // __GNU_EH_FRAME_HDR |
| | 2849 | if (self.eh_frame_hdr_section_index) |shndx| { |
| | 2850 | const shdr = &self.sections.items(.shdr)[shndx]; |
| | 2851 | const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?); |
| | 2852 | symbol_ptr.value = shdr.sh_addr; |
| | 2853 | symbol_ptr.output_section_index = shndx; |
| | 2854 | } |
| | 2855 | |
| | 2856 | // __rela_iplt_start, __rela_iplt_end |
| | 2857 | if (self.rela_dyn_section_index) |shndx| blk: { |
| | 2858 | if (self.base.options.link_mode != .Static or self.base.options.pie) break :blk; |
| | 2859 | const shdr = &self.sections.items(.shdr)[shndx]; |
| | 2860 | const end_addr = shdr.sh_addr + shdr.sh_size; |
| | 2861 | const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); |
| | 2862 | const start_sym = self.symbol(self.rela_iplt_start_index.?); |
| | 2863 | const end_sym = self.symbol(self.rela_iplt_end_index.?); |
| | 2864 | start_sym.value = start_addr; |
| | 2865 | start_sym.output_section_index = shndx; |
| | 2866 | end_sym.value = end_addr; |
| | 2867 | end_sym.output_section_index = shndx; |
| | 2868 | } |
| | 2869 | |
| | 2870 | // _end |
| | 2871 | { |
| | 2872 | const end_symbol = self.symbol(self.end_index.?); |
| | 2873 | for (self.sections.items(.shdr), 0..) |shdr, shndx| { |
| | 2874 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { |
| | 2875 | end_symbol.value = shdr.sh_addr + shdr.sh_size; |
| | 2876 | end_symbol.output_section_index = @intCast(shndx); |
| | 2877 | } |
| | 2878 | } |
| | 2879 | } |
| | 2880 | |
| | 2881 | // __start_*, __stop_* |
| | 2882 | { |
| | 2883 | var index: usize = 0; |
| | 2884 | while (index < self.start_stop_indexes.items.len) : (index += 2) { |
| | 2885 | const start = self.symbol(self.start_stop_indexes.items[index]); |
| | 2886 | const name = start.name(self); |
| | 2887 | const stop = self.symbol(self.start_stop_indexes.items[index + 1]); |
| | 2888 | const shndx = self.sectionByName(name["__start_".len..]).?; |
| | 2889 | const shdr = self.sections.items(.shdr)[shndx]; |
| | 2890 | start.value = shdr.sh_addr; |
| | 2891 | start.output_section_index = shndx; |
| | 2892 | stop.value = shdr.sh_addr + shdr.sh_size; |
| | 2893 | stop.output_section_index = shndx; |
| | 2894 | } |
| | 2895 | } |
| | 2896 | } |
| | 2897 | |
| 2767 | fn updateSymtabSize(self: *Elf) !void { | 2898 | fn updateSymtabSize(self: *Elf) !void { |
| 2768 | var sizes = SymtabSize{}; | 2899 | var sizes = SymtabSize{}; |
| 2769 | | 2900 | |
| ... | @@ -2774,17 +2905,17 @@ fn updateSymtabSize(self: *Elf) !void { | ... | @@ -2774,17 +2905,17 @@ fn updateSymtabSize(self: *Elf) !void { |
| 2774 | sizes.nglobals += zig_module.output_symtab_size.nglobals; | 2905 | sizes.nglobals += zig_module.output_symtab_size.nglobals; |
| 2775 | } | 2906 | } |
| 2776 | | 2907 | |
| | 2908 | if (self.got_section_index) |_| { |
| | 2909 | self.got.updateSymtabSize(self); |
| | 2910 | sizes.nlocals += self.got.output_symtab_size.nlocals; |
| | 2911 | } |
| | 2912 | |
| 2777 | if (self.linker_defined_index) |index| { | 2913 | if (self.linker_defined_index) |index| { |
| 2778 | const linker_defined = self.file(index).?.linker_defined; | 2914 | const linker_defined = self.file(index).?.linker_defined; |
| 2779 | linker_defined.updateSymtabSize(self); | 2915 | linker_defined.updateSymtabSize(self); |
| 2780 | sizes.nlocals += linker_defined.output_symtab_size.nlocals; | 2916 | sizes.nlocals += linker_defined.output_symtab_size.nlocals; |
| 2781 | } | 2917 | } |
| 2782 | | 2918 | |
| 2783 | if (self.got_section_index) |_| { | | |
| 2784 | self.got.updateSymtabSize(self); | | |
| 2785 | sizes.nlocals += self.got.output_symtab_size.nlocals; | | |
| 2786 | } | | |
| 2787 | | | |
| 2788 | const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?]; | 2919 | const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?]; |
| 2789 | shdr.sh_info = sizes.nlocals + 1; | 2920 | shdr.sh_info = sizes.nlocals + 1; |
| 2790 | self.markDirty(self.symtab_section_index.?, null); | 2921 | self.markDirty(self.symtab_section_index.?, null); |
| ... | @@ -2829,17 +2960,17 @@ fn writeSymtab(self: *Elf) !void { | ... | @@ -2829,17 +2960,17 @@ fn writeSymtab(self: *Elf) !void { |
| 2829 | ctx.iglobal += zig_module.output_symtab_size.nglobals; | 2960 | ctx.iglobal += zig_module.output_symtab_size.nglobals; |
| 2830 | } | 2961 | } |
| 2831 | | 2962 | |
| | 2963 | if (self.got_section_index) |_| { |
| | 2964 | try self.got.writeSymtab(self, ctx); |
| | 2965 | ctx.ilocal += self.got.output_symtab_size.nlocals; |
| | 2966 | } |
| | 2967 | |
| 2832 | if (self.linker_defined_index) |index| { | 2968 | if (self.linker_defined_index) |index| { |
| 2833 | const linker_defined = self.file(index).?.linker_defined; | 2969 | const linker_defined = self.file(index).?.linker_defined; |
| 2834 | linker_defined.writeSymtab(self, ctx); | 2970 | linker_defined.writeSymtab(self, ctx); |
| 2835 | ctx.ilocal += linker_defined.output_symtab_size.nlocals; | 2971 | ctx.ilocal += linker_defined.output_symtab_size.nlocals; |
| 2836 | } | 2972 | } |
| 2837 | | 2973 | |
| 2838 | if (self.got_section_index) |_| { | | |
| 2839 | try self.got.writeSymtab(self, ctx); | | |
| 2840 | ctx.ilocal += self.got.output_symtab_size.nlocals; | | |
| 2841 | } | | |
| 2842 | | | |
| 2843 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); | 2974 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); |
| 2844 | switch (self.ptr_width) { | 2975 | switch (self.ptr_width) { |
| 2845 | .p32 => { | 2976 | .p32 => { |
| ... | @@ -3179,6 +3310,34 @@ const CsuObjects = struct { | ... | @@ -3179,6 +3310,34 @@ const CsuObjects = struct { |
| 3179 | } | 3310 | } |
| 3180 | }; | 3311 | }; |
| 3181 | | 3312 | |
| | 3313 | pub fn calcImageBase(self: Elf) u64 { |
| | 3314 | if (self.base.options.pic) return 0; // TODO flag an error if PIC and image_base_override |
| | 3315 | return self.base.options.image_base_override orelse switch (self.ptr_width) { |
| | 3316 | .p32 => 0x1000, |
| | 3317 | .p64 => 0x1000000, |
| | 3318 | }; |
| | 3319 | } |
| | 3320 | |
| | 3321 | pub fn defaultEntryAddress(self: Elf) u64 { |
| | 3322 | if (self.entry_addr) |addr| return addr; |
| | 3323 | return switch (self.base.options.target.cpu.arch) { |
| | 3324 | .spu_2 => 0, |
| | 3325 | else => default_entry_addr, |
| | 3326 | }; |
| | 3327 | } |
| | 3328 | |
| | 3329 | pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 { |
| | 3330 | for (self.sections.items(.shdr), 0..) |shdr, i| { |
| | 3331 | const this_name = self.shstrtab.getAssumeExists(shdr.sh_name); |
| | 3332 | if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i)); |
| | 3333 | } else return null; |
| | 3334 | } |
| | 3335 | |
| | 3336 | pub fn calcNumIRelativeRelocs(self: *Elf) u64 { |
| | 3337 | _ = self; |
| | 3338 | unreachable; // TODO |
| | 3339 | } |
| | 3340 | |
| 3182 | pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom { | 3341 | pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom { |
| 3183 | if (atom_index == 0) return null; | 3342 | if (atom_index == 0) return null; |
| 3184 | assert(atom_index < self.atoms.items.len); | 3343 | assert(atom_index < self.atoms.items.len); |