mirror of
https://github.com/ziglang/zig.git
synced 2026-01-02 11:33:21 +00:00
macho: init metadata and partially implement updateDecl
This commit is contained in:
parent
bd9d8bd462
commit
0b2133d441
@ -82,6 +82,18 @@ lazy_bind: LazyBindSection = .{},
|
||||
export_trie: ExportTrieSection = .{},
|
||||
unwind_info: UnwindInfo = .{},
|
||||
|
||||
/// Tracked loadable segments during incremental linking.
|
||||
zig_text_seg_index: ?u8 = null,
|
||||
zig_data_const_seg_index: ?u8 = null,
|
||||
zig_data_seg_index: ?u8 = null,
|
||||
|
||||
/// Tracked section headers with incremental updates to Zig object.
|
||||
zig_text_section_index: ?u8 = null,
|
||||
zig_data_const_section_index: ?u8 = null,
|
||||
zig_data_section_index: ?u8 = null,
|
||||
zig_bss_section_index: ?u8 = null,
|
||||
zig_got_section_index: ?u8 = null,
|
||||
|
||||
has_tlv: bool = false,
|
||||
binds_to_weak: bool = false,
|
||||
weak_defines: bool = false,
|
||||
@ -234,8 +246,11 @@ pub fn createEmpty(
|
||||
} });
|
||||
self.zig_object = index;
|
||||
try self.getZigObject().?.init(self);
|
||||
try self.initMetadata(.{
|
||||
.symbol_count_hint = options.symbol_count_hint,
|
||||
.program_code_size_hint = options.program_code_size_hint,
|
||||
});
|
||||
|
||||
// TODO init metadata
|
||||
// TODO init dwarf
|
||||
|
||||
// if (comp.config.debug_format != .strip) {
|
||||
@ -3103,6 +3118,45 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 {
|
||||
return start;
|
||||
}
|
||||
|
||||
const InitMetadataOptions = struct {
|
||||
symbol_count_hint: u64,
|
||||
program_code_size_hint: u64,
|
||||
};
|
||||
|
||||
// TODO: move to ZigObject
|
||||
// TODO: bring back pre-alloc of segments/sections
|
||||
fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
|
||||
_ = options;
|
||||
|
||||
if (!self.base.isRelocatable()) {
|
||||
// TODO: If we are not emitting a relocatable object file, init segments.
|
||||
}
|
||||
|
||||
if (self.zig_text_section_index == null) {
|
||||
self.zig_text_section_index = try self.addSection("__TEXT", "__text", .{
|
||||
.flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
|
||||
});
|
||||
}
|
||||
|
||||
if (self.zig_got_section_index == null and !self.base.isRelocatable()) {
|
||||
self.zig_got_section_index = try self.addSection("__DATA_CONST", "__got_zig", .{});
|
||||
}
|
||||
|
||||
if (self.zig_data_const_section_index == null) {
|
||||
self.zig_data_const_section_index = try self.addSection("__DATA_CONST", "__const", .{});
|
||||
}
|
||||
|
||||
if (self.zig_data_section_index == null) {
|
||||
self.zig_data_section_index = try self.addSection("__DATA", "__data", .{});
|
||||
}
|
||||
|
||||
if (self.zig_bss_section_index == null) {
|
||||
self.zig_bss_section_index = try self.addSection("__DATA", "_bss", .{
|
||||
.flags = macho.S_ZEROFILL,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getTarget(self: MachO) std.Target {
|
||||
return self.base.comp.root_mod.resolved_target.result;
|
||||
}
|
||||
@ -3148,6 +3202,29 @@ inline fn requiresThunks(self: MachO) bool {
|
||||
return self.getTarget().cpu.arch == .aarch64;
|
||||
}
|
||||
|
||||
pub fn addSegment(self: *MachO, name: []const u8, opts: struct {
|
||||
vmaddr: u64 = 0,
|
||||
vmsize: u64 = 0,
|
||||
fileoff: u64 = 0,
|
||||
filesize: u64 = 0,
|
||||
prot: macho.vm_prot_t = macho.PROT.NONE,
|
||||
}) error{OutOfMemory}!u8 {
|
||||
const gpa = self.base.comp.gpa;
|
||||
const index = @as(u8, @intCast(self.segments.items.len));
|
||||
try self.segments.append(gpa, .{
|
||||
.segname = makeStaticString(name),
|
||||
.vmaddr = opts.vmaddr,
|
||||
.vmsize = opts.vmsize,
|
||||
.fileoff = opts.fileoff,
|
||||
.filesize = opts.filesize,
|
||||
.maxprot = opts.prot,
|
||||
.initprot = opts.prot,
|
||||
.nsects = 0,
|
||||
.cmdsize = @sizeOf(macho.segment_command_64),
|
||||
});
|
||||
return index;
|
||||
}
|
||||
|
||||
const AddSectionOpts = struct {
|
||||
flags: u32 = macho.S_REGULAR,
|
||||
reserved1: u32 = 0,
|
||||
|
||||
@ -295,7 +295,8 @@ pub fn updateDecl(
|
||||
return;
|
||||
},
|
||||
};
|
||||
_ = code;
|
||||
const sect_index = try self.getDeclOutputSection(macho_file, decl, code);
|
||||
_ = sect_index;
|
||||
// const addr = try self.updateDeclCode(decl_index, code);
|
||||
|
||||
// if (decl_state) |*ds| {
|
||||
@ -313,6 +314,59 @@ pub fn updateDecl(
|
||||
// try self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
|
||||
}
|
||||
|
||||
fn getDeclOutputSection(
|
||||
self: *ZigObject,
|
||||
macho_file: *MachO,
|
||||
decl: *const Module.Decl,
|
||||
code: []const u8,
|
||||
) error{OutOfMemory}!u8 {
|
||||
_ = self;
|
||||
const mod = macho_file.base.comp.module.?;
|
||||
const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
|
||||
const sect_id: u8 = switch (decl.ty.zigTypeTag(mod)) {
|
||||
.Fn => macho_file.zig_text_section_index.?,
|
||||
else => blk: {
|
||||
if (decl.getOwnedVariable(mod)) |variable| {
|
||||
if (variable.is_threadlocal and any_non_single_threaded) {
|
||||
const is_all_zeroes = for (code) |byte| {
|
||||
if (byte != 0) break false;
|
||||
} else true;
|
||||
if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
|
||||
"__DATA",
|
||||
"__thread_bss",
|
||||
.{ .flags = macho.S_THREAD_LOCAL_ZEROFILL },
|
||||
);
|
||||
break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection(
|
||||
"__DATA",
|
||||
"__thread_data",
|
||||
.{ .flags = macho.S_THREAD_LOCAL_REGULAR },
|
||||
);
|
||||
}
|
||||
|
||||
if (variable.is_const) break :blk macho_file.zig_data_const_section_index.?;
|
||||
if (Value.fromInterned(variable.init).isUndefDeep(mod)) {
|
||||
// TODO: get the optimize_mode from the Module that owns the decl instead
|
||||
// of using the root module here.
|
||||
break :blk switch (macho_file.base.comp.root_mod.optimize_mode) {
|
||||
.Debug, .ReleaseSafe => macho_file.zig_data_section_index.?,
|
||||
.ReleaseFast, .ReleaseSmall => macho_file.zig_bss_section_index.?,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO I blatantly copied the logic from the Wasm linker, but is there a less
|
||||
// intrusive check for all zeroes than this?
|
||||
const is_all_zeroes = for (code) |byte| {
|
||||
if (byte != 0) break false;
|
||||
} else true;
|
||||
if (is_all_zeroes) break :blk macho_file.zig_bss_section_index.?;
|
||||
break :blk macho_file.zig_data_section_index.?;
|
||||
}
|
||||
break :blk macho_file.zig_data_const_section_index.?;
|
||||
},
|
||||
};
|
||||
return sect_id;
|
||||
}
|
||||
|
||||
pub fn lowerUnnamedConst(
|
||||
self: *ZigObject,
|
||||
macho_file: *MachO,
|
||||
@ -386,7 +440,7 @@ pub fn getOrCreateMetadataForDecl(
|
||||
const sym_index = try self.addAtom(macho_file);
|
||||
const mod = macho_file.base.comp.module.?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const sym = macho_file.getSymbol(self.symbols.items[sym_index]);
|
||||
const sym = macho_file.getSymbol(sym_index);
|
||||
if (decl.getOwnedVariable(mod)) |variable| {
|
||||
if (variable.is_threadlocal and any_non_single_threaded) {
|
||||
sym.flags.tlv = true;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user