mirror of
https://github.com/ziglang/zig.git
synced 2026-01-01 19:13:16 +00:00
elf: re-enable self-hosted backends
This commit is contained in:
parent
7be983ac92
commit
85d451f96c
@ -762,6 +762,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
.name = ".zig.got",
|
||||
.phdr_index = self.phdr_zig_got_index.?,
|
||||
.alignment = ptr_size,
|
||||
.flags = elf.SHF_ALLOC | elf.SHF_WRITE,
|
||||
});
|
||||
}
|
||||
|
||||
@ -785,7 +786,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
|
||||
if (self.zig_bss_section_index == null) {
|
||||
self.zig_bss_section_index = try self.allocateAllocSection(.{
|
||||
.name = ".bss.zig",
|
||||
.name = ".zig.bss",
|
||||
.phdr_index = self.phdr_zig_load_zerofill_index.?,
|
||||
.alignment = ptr_size,
|
||||
.flags = elf.SHF_ALLOC | elf.SHF_WRITE,
|
||||
@ -1558,7 +1559,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
for (zig_module.atoms.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shdr = &self.shdrs.items[atom_ptr.outputShndx().?];
|
||||
const out_shndx = atom_ptr.outputShndx() orelse continue;
|
||||
const shdr = &self.shdrs.items[out_shndx];
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
const code = try zig_module.codeAlloc(self, atom_index);
|
||||
defer gpa.free(code);
|
||||
@ -3744,6 +3746,9 @@ fn initSections(self: *Elf) !void {
|
||||
const needs_rela_dyn = blk: {
|
||||
if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or
|
||||
self.copy_rel.symbols.items.len > 0) break :blk true;
|
||||
if (self.zig_module_index) |index| {
|
||||
if (self.file(index).?.zig_module.num_dynrelocs > 0) break :blk true;
|
||||
}
|
||||
for (self.objects.items) |index| {
|
||||
if (self.file(index).?.object.num_dynrelocs > 0) break :blk true;
|
||||
}
|
||||
@ -4243,6 +4248,33 @@ fn sortSections(self: *Elf) !void {
|
||||
shdr.sh_link = self.dynsymtab_section_index.?;
|
||||
shdr.sh_info = self.plt_section_index.?;
|
||||
}
|
||||
|
||||
if (self.zig_module_index) |index| {
|
||||
const zig_module = self.file(index).?.zig_module;
|
||||
for (zig_module.atoms.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const out_shndx = atom_ptr.outputShndx() orelse continue;
|
||||
atom_ptr.output_section_index = backlinks[out_shndx];
|
||||
}
|
||||
|
||||
for (zig_module.locals()) |local_index| {
|
||||
const local = self.symbol(local_index);
|
||||
const atom_ptr = local.atom(self) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const out_shndx = local.outputShndx() orelse continue;
|
||||
local.output_section_index = backlinks[out_shndx];
|
||||
}
|
||||
|
||||
for (zig_module.globals()) |global_index| {
|
||||
const global = self.symbol(global_index);
|
||||
const atom_ptr = global.atom(self) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
if (global.file(self).?.index() != index) continue;
|
||||
const out_shndx = global.outputShndx() orelse continue;
|
||||
global.output_section_index = backlinks[out_shndx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn updateSectionSizes(self: *Elf) !void {
|
||||
@ -4286,6 +4318,9 @@ fn updateSectionSizes(self: *Elf) !void {
|
||||
|
||||
if (self.rela_dyn_section_index) |shndx| {
|
||||
var num = self.got.numRela(self) + self.copy_rel.numRela();
|
||||
if (self.zig_module_index) |index| {
|
||||
num += self.file(index).?.zig_module.num_dynrelocs;
|
||||
}
|
||||
for (self.objects.items) |index| {
|
||||
num += self.file(index).?.object.num_dynrelocs;
|
||||
}
|
||||
@ -4373,9 +4408,10 @@ fn shdrToPhdrFlags(sh_flags: u64) u32 {
|
||||
fn calcNumberOfSegments(self: *Elf) usize {
|
||||
var count: usize = 0;
|
||||
var flags: u64 = 0;
|
||||
for (self.shdrs.items) |shdr| {
|
||||
for (self.shdrs.items, 0..) |shdr, shndx| {
|
||||
if (shdr.sh_type == elf.SHT_NULL) continue;
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
|
||||
if (self.isZigSection(@intCast(shndx))) continue;
|
||||
if (flags != shdrToPhdrFlags(shdr.sh_flags)) count += 1;
|
||||
flags = shdrToPhdrFlags(shdr.sh_flags);
|
||||
}
|
||||
@ -4474,7 +4510,10 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
|
||||
}
|
||||
}
|
||||
}
|
||||
covers[nphdrs - 1].len = shndx - covers[nphdrs - 1].start;
|
||||
|
||||
if (nphdrs > 0) {
|
||||
covers[nphdrs - 1].len = shndx - covers[nphdrs - 1].start;
|
||||
}
|
||||
|
||||
// Now we can proceed with allocating the sections in virtual memory.
|
||||
// As the base address we take the end address of the PHDR table.
|
||||
@ -4647,6 +4686,7 @@ fn writeAtoms(self: *Elf) !void {
|
||||
undefs.deinit();
|
||||
}
|
||||
|
||||
// TODO iterate over `output_sections` directly
|
||||
for (self.shdrs.items, 0..) |shdr, shndx| {
|
||||
if (shdr.sh_type == elf.SHT_NULL) continue;
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
@ -5830,7 +5870,10 @@ fn fmtDumpState(
|
||||
if (self.zig_module_index) |index| {
|
||||
const zig_module = self.file(index).?.zig_module;
|
||||
try writer.print("zig_module({d}) : {s}\n", .{ index, zig_module.path });
|
||||
try writer.print("{}\n", .{zig_module.fmtSymtab(self)});
|
||||
try writer.print("{}{}\n", .{
|
||||
zig_module.fmtAtoms(self),
|
||||
zig_module.fmtSymtab(self),
|
||||
});
|
||||
}
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
@ -5872,7 +5915,7 @@ fn fmtDumpState(
|
||||
self.fmtShdr(shdr),
|
||||
});
|
||||
}
|
||||
try writer.writeAll("Output phdrs\n");
|
||||
try writer.writeAll("\nOutput phdrs\n");
|
||||
for (self.phdrs.items, 0..) |phdr, phndx| {
|
||||
try writer.print("phdr{d} : {}\n", .{ phndx, self.fmtPhdr(phdr) });
|
||||
}
|
||||
@ -5983,6 +6026,19 @@ pub const null_sym = elf.Elf64_Sym{
|
||||
.st_size = 0,
|
||||
};
|
||||
|
||||
pub const null_shdr = elf.Elf64_Shdr{
|
||||
.sh_name = 0,
|
||||
.sh_type = 0,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = 0,
|
||||
.sh_size = 0,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 0,
|
||||
.sh_entsize = 0,
|
||||
};
|
||||
|
||||
const SystemLib = struct {
|
||||
needed: bool = false,
|
||||
path: []const u8,
|
||||
|
||||
@ -50,8 +50,11 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
|
||||
}
|
||||
|
||||
pub fn inputShdr(self: Atom, elf_file: *Elf) Object.ElfShdr {
|
||||
const object = self.file(elf_file).?.object;
|
||||
return object.shdrs.items[self.input_section_index];
|
||||
return switch (self.file(elf_file).?) {
|
||||
.object => |x| x.shdrs.items[self.input_section_index],
|
||||
.zig_module => |x| x.inputShdr(self.atom_index, elf_file),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn outputShndx(self: Atom) ?u16 {
|
||||
@ -199,7 +202,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
_ = free_list.swapRemove(i);
|
||||
}
|
||||
|
||||
self.flags.allocated = true;
|
||||
self.flags.alive = true;
|
||||
}
|
||||
|
||||
pub fn shrink(self: *Atom, elf_file: *Elf) void {
|
||||
@ -471,7 +474,11 @@ fn scanReloc(
|
||||
elf_file: *Elf,
|
||||
) error{OutOfMemory}!void {
|
||||
const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0;
|
||||
const object = self.file(elf_file).?.object;
|
||||
const num_dynrelocs = switch (self.file(elf_file).?) {
|
||||
.linker_defined => unreachable,
|
||||
.shared_object => unreachable,
|
||||
inline else => |x| &x.num_dynrelocs,
|
||||
};
|
||||
|
||||
switch (action) {
|
||||
.none => {},
|
||||
@ -500,7 +507,7 @@ fn scanReloc(
|
||||
try self.reportTextRelocError(symbol, rel, elf_file);
|
||||
}
|
||||
}
|
||||
object.num_dynrelocs += 1;
|
||||
num_dynrelocs.* += 1;
|
||||
} else {
|
||||
symbol.flags.needs_copy_rel = true;
|
||||
}
|
||||
@ -517,7 +524,7 @@ fn scanReloc(
|
||||
|
||||
.dyn_cplt => {
|
||||
if (is_writeable) {
|
||||
object.num_dynrelocs += 1;
|
||||
num_dynrelocs.* += 1;
|
||||
} else {
|
||||
symbol.flags.needs_plt = true;
|
||||
symbol.flags.is_canonical = true;
|
||||
@ -532,7 +539,7 @@ fn scanReloc(
|
||||
try self.reportTextRelocError(symbol, rel, elf_file);
|
||||
}
|
||||
}
|
||||
object.num_dynrelocs += 1;
|
||||
num_dynrelocs.* += 1;
|
||||
|
||||
if (action == .ifunc) elf_file.num_ifunc_dynrelocs += 1;
|
||||
},
|
||||
@ -898,9 +905,13 @@ fn resolveDynAbsReloc(
|
||||
const A = rel.r_addend;
|
||||
const S = @as(i64, @intCast(target.address(.{}, elf_file)));
|
||||
const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0;
|
||||
const object = self.file(elf_file).?.object;
|
||||
|
||||
try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, object.num_dynrelocs);
|
||||
const num_dynrelocs = switch (self.file(elf_file).?) {
|
||||
.linker_defined => unreachable,
|
||||
.shared_object => unreachable,
|
||||
inline else => |x| x.num_dynrelocs,
|
||||
};
|
||||
try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, num_dynrelocs);
|
||||
|
||||
switch (action) {
|
||||
.@"error",
|
||||
@ -1165,7 +1176,7 @@ fn format2(
|
||||
_ = unused_fmt_string;
|
||||
const atom = ctx.atom;
|
||||
const elf_file = ctx.elf_file;
|
||||
try writer.print("atom({d}) : {s} : @{x} : sect({d}) : align({x}) : size({x})", .{
|
||||
try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x})", .{
|
||||
atom.atom_index, atom.name(elf_file), atom.value,
|
||||
atom.output_section_index, atom.alignment, atom.size,
|
||||
});
|
||||
@ -1191,9 +1202,6 @@ pub const Flags = packed struct {
|
||||
|
||||
/// Specifies if the atom has been visited during garbage collection.
|
||||
visited: bool = false,
|
||||
|
||||
/// Specifies whether this atom has been allocated in the output section.
|
||||
allocated: bool = false,
|
||||
};
|
||||
|
||||
const x86_64 = struct {
|
||||
|
||||
@ -314,7 +314,7 @@ fn format2(
|
||||
try writer.writeAll(" : absolute");
|
||||
}
|
||||
} else if (symbol.outputShndx()) |shndx| {
|
||||
try writer.print(" : sect({d})", .{shndx});
|
||||
try writer.print(" : shdr({d})", .{shndx});
|
||||
}
|
||||
if (symbol.atom(ctx.elf_file)) |atom_ptr| {
|
||||
try writer.print(" : atom({d})", .{atom_ptr.atom_index});
|
||||
|
||||
@ -16,6 +16,8 @@ globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
|
||||
|
||||
num_dynrelocs: u32 = 0,
|
||||
|
||||
output_symtab_size: Elf.SymtabSize = .{},
|
||||
|
||||
pub fn deinit(self: *ZigModule, allocator: Allocator) void {
|
||||
@ -79,6 +81,22 @@ pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
/// TODO actually create fake input shdrs and return that instead.
|
||||
pub fn inputShdr(self: ZigModule, atom_index: Atom.Index, elf_file: *Elf) Object.ElfShdr {
|
||||
_ = self;
|
||||
const shdr = shdr: {
|
||||
const atom = elf_file.atom(atom_index) orelse break :shdr Elf.null_shdr;
|
||||
const shndx = atom.outputShndx() orelse break :shdr Elf.null_shdr;
|
||||
var shdr = elf_file.shdrs.items[shndx];
|
||||
shdr.sh_addr = 0;
|
||||
shdr.sh_offset = 0;
|
||||
shdr.sh_size = atom.size;
|
||||
shdr.sh_addralign = atom.alignment.toByteUnits(1);
|
||||
break :shdr shdr;
|
||||
};
|
||||
return Object.ElfShdr.fromElf64Shdr(shdr) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
|
||||
for (self.globals(), 0..) |index, i| {
|
||||
const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000;
|
||||
@ -145,6 +163,8 @@ pub fn scanRelocs(self: *ZigModule, elf_file: *Elf, undefs: anytype) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
if (atom.scanRelocsRequiresCode(elf_file)) {
|
||||
// TODO ideally we don't have to fetch the code here.
|
||||
// Perhaps it would make sense to save the code until flushModule where we
|
||||
@ -273,7 +293,10 @@ pub fn codeAlloc(self: ZigModule, elf_file: *Elf, atom_index: Atom.Index) ![]u8
|
||||
const code = try gpa.alloc(u8, size);
|
||||
errdefer gpa.free(code);
|
||||
const amt = try elf_file.base.file.?.preadAll(code, file_offset);
|
||||
if (amt != code.len) return error.InputOutput;
|
||||
if (amt != code.len) {
|
||||
log.err("fetching code for {s} failed", .{atom.name(elf_file)});
|
||||
return error.InputOutput;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@ -334,11 +357,13 @@ fn formatAtoms(
|
||||
const assert = std.debug.assert;
|
||||
const std = @import("std");
|
||||
const elf = std.elf;
|
||||
const log = std.log.scoped(.link);
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Atom = @import("Atom.zig");
|
||||
const Elf = @import("../Elf.zig");
|
||||
const File = @import("file.zig").File;
|
||||
const Module = @import("../../Module.zig");
|
||||
const Object = @import("Object.zig");
|
||||
const Symbol = @import("Symbol.zig");
|
||||
const ZigModule = @This();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user