| ... | @@ -4037,107 +4037,19 @@ fn allocateSpecialPhdrs(self: *Elf) void { | ... | @@ -4037,107 +4037,19 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4037 | } | 4037 | } |
| 4038 | | 4038 | |
| 4039 | fn writeAtoms(self: *Elf) !void { | 4039 | fn writeAtoms(self: *Elf) !void { |
| 4040 | const gpa = self.base.comp.gpa; | 4040 | for (self.objects.items) |index| { |
| 4041 | | 4041 | try self.file(index).?.object.writeAtoms(self); |
| 4042 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); | | |
| 4043 | defer { | | |
| 4044 | for (undefs.values()) |*refs| { | | |
| 4045 | refs.deinit(); | | |
| 4046 | } | | |
| 4047 | undefs.deinit(); | | |
| 4048 | } | | |
| 4049 | | | |
| 4050 | var has_reloc_errors = false; | | |
| 4051 | const slice = self.sections.slice(); | | |
| 4052 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { | | |
| 4053 | if (shdr.sh_type == elf.SHT_NULL) continue; | | |
| 4054 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | | |
| 4055 | if (atom_list.items.len == 0) continue; | | |
| 4056 | | | |
| 4057 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); | | |
| 4058 | | | |
| 4059 | // TODO really, really handle debug section separately | | |
| 4060 | const base_offset = if (self.zigObjectPtr()) |zo| base_offset: { | | |
| 4061 | for ([_]?Symbol.Index{ | | |
| 4062 | zo.text_index, | | |
| 4063 | zo.rodata_index, | | |
| 4064 | zo.data_relro_index, | | |
| 4065 | zo.data_index, | | |
| 4066 | zo.tdata_index, | | |
| 4067 | zo.eh_frame_index, | | |
| 4068 | zo.debug_info_index, | | |
| 4069 | zo.debug_abbrev_index, | | |
| 4070 | zo.debug_aranges_index, | | |
| 4071 | zo.debug_str_index, | | |
| 4072 | zo.debug_line_index, | | |
| 4073 | zo.debug_line_str_index, | | |
| 4074 | zo.debug_loclists_index, | | |
| 4075 | zo.debug_rnglists_index, | | |
| 4076 | }) |maybe_sym_index| { | | |
| 4077 | const sym_index = maybe_sym_index orelse continue; | | |
| 4078 | const sym = zo.symbol(sym_index); | | |
| 4079 | const atom_ptr = sym.atom(self).?; | | |
| 4080 | if (atom_ptr.output_section_index == shndx) break :base_offset atom_ptr.size; | | |
| 4081 | } | | |
| 4082 | break :base_offset 0; | | |
| 4083 | } else 0; | | |
| 4084 | const sh_offset = shdr.sh_offset + base_offset; | | |
| 4085 | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; | | |
| 4086 | | | |
| 4087 | const buffer = try gpa.alloc(u8, sh_size); | | |
| 4088 | defer gpa.free(buffer); | | |
| 4089 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and | | |
| 4090 | shdr.sh_flags & elf.SHF_EXECINSTR != 0 and self.getTarget().cpu.arch == .x86_64) | | |
| 4091 | 0xcc // int3 | | |
| 4092 | else | | |
| 4093 | 0; | | |
| 4094 | @memset(buffer, padding_byte); | | |
| 4095 | | | |
| 4096 | for (atom_list.items) |ref| { | | |
| 4097 | const atom_ptr = self.atom(ref).?; | | |
| 4098 | assert(atom_ptr.alive); | | |
| 4099 | | | |
| 4100 | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse | | |
| 4101 | return error.Overflow; | | |
| 4102 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | | |
| 4103 | | | |
| 4104 | log.debug("writing atom({}) at 0x{x}", .{ ref, sh_offset + offset }); | | |
| 4105 | | | |
| 4106 | // TODO decompress directly into provided buffer | | |
| 4107 | const out_code = buffer[offset..][0..size]; | | |
| 4108 | const in_code = switch (atom_ptr.file(self).?) { | | |
| 4109 | .object => |x| try x.codeDecompressAlloc(self, ref.index), | | |
| 4110 | .zig_object => |x| try x.codeAlloc(self, ref.index), | | |
| 4111 | else => unreachable, | | |
| 4112 | }; | | |
| 4113 | defer gpa.free(in_code); | | |
| 4114 | @memcpy(out_code, in_code); | | |
| 4115 | | | |
| 4116 | const res = if (shdr.sh_flags & elf.SHF_ALLOC == 0) | | |
| 4117 | atom_ptr.resolveRelocsNonAlloc(self, out_code, &undefs) | | |
| 4118 | else | | |
| 4119 | atom_ptr.resolveRelocsAlloc(self, out_code); | | |
| 4120 | _ = res catch |err| switch (err) { | | |
| 4121 | error.UnsupportedCpuArch => { | | |
| 4122 | try self.reportUnsupportedCpuArch(); | | |
| 4123 | return error.FlushFailure; | | |
| 4124 | }, | | |
| 4125 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, | | |
| 4126 | else => |e| return e, | | |
| 4127 | }; | | |
| 4128 | } | | |
| 4129 | | | |
| 4130 | try self.base.file.?.pwriteAll(buffer, sh_offset); | | |
| 4131 | } | 4042 | } |
| 4132 | | 4043 | |
| 4133 | if (self.requiresThunks()) { | 4044 | if (self.requiresThunks()) { |
| | 4045 | const gpa = self.base.comp.gpa; |
| 4134 | var buffer = std.ArrayList(u8).init(gpa); | 4046 | var buffer = std.ArrayList(u8).init(gpa); |
| 4135 | defer buffer.deinit(); | 4047 | defer buffer.deinit(); |
| 4136 | | 4048 | |
| 4137 | for (self.thunks.items) |th| { | 4049 | for (self.thunks.items) |th| { |
| 4138 | const thunk_size = th.size(self); | 4050 | const thunk_size = th.size(self); |
| 4139 | try buffer.ensureUnusedCapacity(thunk_size); | 4051 | try buffer.ensureUnusedCapacity(thunk_size); |
| 4140 | const shdr = slice.items(.shdr)[th.output_section_index]; | 4052 | const shdr = self.sections.items(.shdr)[th.output_section_index]; |
| 4141 | const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; | 4053 | const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; |
| 4142 | try th.write(self, buffer.writer()); | 4054 | try th.write(self, buffer.writer()); |
| 4143 | assert(buffer.items.len == thunk_size); | 4055 | assert(buffer.items.len == thunk_size); |
| ... | @@ -4145,10 +4057,6 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4145,10 +4057,6 @@ fn writeAtoms(self: *Elf) !void { |
| 4145 | buffer.clearRetainingCapacity(); | 4057 | buffer.clearRetainingCapacity(); |
| 4146 | } | 4058 | } |
| 4147 | } | 4059 | } |
| 4148 | | | |
| 4149 | try self.reportUndefinedSymbols(&undefs); | | |
| 4150 | | | |
| 4151 | if (has_reloc_errors) return error.FlushFailure; | | |
| 4152 | } | 4060 | } |
| 4153 | | 4061 | |
| 4154 | pub fn updateSymtabSize(self: *Elf) !void { | 4062 | pub fn updateSymtabSize(self: *Elf) !void { |
| ... | @@ -5089,7 +4997,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { | ... | @@ -5089,7 +4997,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { |
| 5089 | return off; | 4997 | return off; |
| 5090 | } | 4998 | } |
| 5091 | | 4999 | |
| 5092 | fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { | 5000 | pub fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 5093 | const gpa = self.base.comp.gpa; | 5001 | const gpa = self.base.comp.gpa; |
| 5094 | const max_notes = 4; | 5002 | const max_notes = 4; |
| 5095 | | 5003 | |