macho: move initSection into MachO from Zld

This commit is contained in:
Jakub Konka 2023-08-26 08:13:41 +02:00
parent 180979ee41
commit b2773cd712
4 changed files with 85 additions and 67 deletions

View File

@ -2739,6 +2739,34 @@ fn calcPagezeroSize(self: *MachO) u64 {
return aligned_pagezero_vmsize;
}
const InitSectionOpts = struct {
flags: u32 = macho.S_REGULAR,
reserved1: u32 = 0,
reserved2: u32 = 0,
};
pub fn initSection(
gpa: Allocator,
ctx: anytype,
segname: []const u8,
sectname: []const u8,
opts: InitSectionOpts,
) !u8 {
log.debug("creating section '{s},{s}'", .{ segname, sectname });
const index = @as(u8, @intCast(ctx.sections.slice().len));
try ctx.sections.append(gpa, .{
.segment_index = undefined, // Segments will be created automatically later down the pipeline
.header = .{
.sectname = makeStaticString(sectname),
.segname = makeStaticString(segname),
.flags = opts.flags,
.reserved1 = opts.reserved1,
.reserved2 = opts.reserved2,
},
});
return index;
}
fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts: struct {
size: u64 = 0,
alignment: u32 = 0,
@ -2751,7 +2779,6 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts
// In incremental context, we create one section per segment pairing. This way,
// we can move the segment in raw file as we please.
const segment_id = @as(u8, @intCast(self.segments.items.len));
const section_id = @as(u8, @intCast(self.sections.slice().len));
const vmaddr = blk: {
const prev_segment = self.segments.items[segment_id - 1];
break :blk mem.alignForward(u64, prev_segment.vmaddr + prev_segment.vmsize, page_size);
@ -2782,23 +2809,18 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts
.cmdsize = @sizeOf(macho.segment_command_64) + @sizeOf(macho.section_64),
};
var section = macho.section_64{
.sectname = makeStaticString(sectname),
.segname = makeStaticString(segname),
.addr = mem.alignForward(u64, vmaddr, opts.alignment),
.offset = mem.alignForward(u32, @as(u32, @intCast(off)), opts.alignment),
.size = opts.size,
.@"align" = math.log2(opts.alignment),
const sect_id = try initSection(gpa, self, sectname, segname, .{
.flags = opts.flags,
.reserved2 = opts.reserved2,
};
});
const section = &self.sections.items(.header)[sect_id];
section.addr = mem.alignForward(u64, vmaddr, opts.alignment);
section.offset = mem.alignForward(u32, @as(u32, @intCast(off)), opts.alignment);
section.size = opts.size;
section.@"align" = math.log2(opts.alignment);
assert(!section.isZerofill()); // TODO zerofill sections
try self.sections.append(gpa, .{
.segment_index = segment_id,
.header = section,
});
return section_id;
return sect_id;
}
fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void {

View File

@ -106,6 +106,7 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
}
pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
const gpa = zld.gpa;
const segname = sect.segName();
const sectname = sect.sectName();
const res: ?u8 = blk: {
@ -126,7 +127,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
if (sect.isCode()) {
if (zld.text_section_index == null) {
zld.text_section_index = try zld.initSection(
zld.text_section_index = try MachO.initSection(
gpa,
zld,
"__TEXT",
"__text",
.{
@ -148,7 +151,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
macho.S_8BYTE_LITERALS,
macho.S_16BYTE_LITERALS,
=> {
break :blk zld.getSectionByName("__TEXT", "__const") orelse try zld.initSection(
break :blk zld.getSectionByName("__TEXT", "__const") orelse try MachO.initSection(
gpa,
zld,
"__TEXT",
"__const",
.{},
@ -156,13 +161,17 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
},
macho.S_CSTRING_LITERALS => {
if (mem.startsWith(u8, sectname, "__objc")) {
break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
gpa,
zld,
segname,
sectname,
.{},
);
}
break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try zld.initSection(
break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try MachO.initSection(
gpa,
zld,
"__TEXT",
"__cstring",
.{ .flags = macho.S_CSTRING_LITERALS },
@ -171,7 +180,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
macho.S_MOD_INIT_FUNC_POINTERS,
macho.S_MOD_TERM_FUNC_POINTERS,
=> {
break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(
break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try MachO.initSection(
gpa,
zld,
"__DATA_CONST",
sectname,
.{ .flags = sect.flags },
@ -184,14 +195,19 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
macho.S_THREAD_LOCAL_REGULAR,
macho.S_THREAD_LOCAL_ZEROFILL,
=> {
break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
gpa,
zld,
segname,
sectname,
.{ .flags = sect.flags },
);
},
macho.S_COALESCED => {
break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
gpa,
zld,
segname,
sectname,
.{},
@ -205,7 +221,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
mem.eql(u8, sectname, "__gosymtab") or
mem.eql(u8, sectname, "__gopclntab"))
{
break :blk zld.getSectionByName("__TEXT", sectname) orelse try zld.initSection(
break :blk zld.getSectionByName("__TEXT", sectname) orelse try MachO.initSection(
gpa,
zld,
"__TEXT",
sectname,
.{},
@ -218,20 +236,26 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
mem.eql(u8, sectname, "__objc_classlist") or
mem.eql(u8, sectname, "__objc_imageinfo"))
{
break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(
break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try MachO.initSection(
gpa,
zld,
"__DATA_CONST",
sectname,
.{},
);
} else if (mem.eql(u8, sectname, "__data")) {
break :blk zld.getSectionByName("__DATA", "__data") orelse try zld.initSection(
break :blk zld.getSectionByName("__DATA", "__data") orelse try MachO.initSection(
gpa,
zld,
"__DATA",
"__data",
.{},
);
}
}
break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
gpa,
zld,
segname,
sectname,
.{},

View File

@ -685,11 +685,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
log.debug("parsing __TEXT,__eh_frame section", .{});
const gpa = zld.gpa;
if (zld.getSectionByName("__TEXT", "__eh_frame") == null) {
_ = try zld.initSection("__TEXT", "__eh_frame", .{});
_ = try MachO.initSection(gpa, zld, "__TEXT", "__eh_frame", .{});
}
const gpa = zld.gpa;
const cpu_arch = zld.options.target.cpu.arch;
try self.parseRelocs(gpa, sect_id);
const relocs = self.getRelocs(sect_id);
@ -779,6 +780,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
}
fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
const gpa = zld.gpa;
const cpu_arch = zld.options.target.cpu.arch;
const sect_id = self.unwind_info_sect_id orelse {
// If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`,
// we will try fully synthesising unwind info records to somewhat match Apple ld's
@ -786,7 +789,7 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
// we still create the output `__TEXT,__unwind_info` section.
if (self.hasEhFrameRecords()) {
if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {
_ = try zld.initSection("__TEXT", "__unwind_info", .{});
_ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{});
}
}
return;
@ -794,11 +797,8 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
log.debug("parsing unwind info in {s}", .{self.name});
const gpa = zld.gpa;
const cpu_arch = zld.options.target.cpu.arch;
if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {
_ = try zld.initSection("__TEXT", "__unwind_info", .{});
_ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{});
}
const unwind_records = self.getUnwindRecords();

View File

@ -141,7 +141,7 @@ pub const Zld = struct {
sym.n_type = macho.N_SECT;
const sect_id = self.getSectionByName("__DATA", "__data") orelse
try self.initSection("__DATA", "__data", .{});
try MachO.initSection(self.gpa, self, "__DATA", "__data", .{});
sym.n_sect = sect_id + 1;
self.dyld_private_atom_index = atom_index;
@ -165,7 +165,7 @@ pub const Zld = struct {
const size = sym.n_value;
const alignment = (sym.n_desc >> 8) & 0x0f;
const sect_id = self.getSectionByName("__DATA", "__bss") orelse
try self.initSection("__DATA", "__bss", .{ .flags = macho.S_ZEROFILL });
try MachO.initSection(gpa, self, "__DATA", "__bss", .{ .flags = macho.S_ZEROFILL });
sym.* = .{
.n_strx = sym.n_strx,
@ -619,7 +619,7 @@ pub const Zld = struct {
if (self.got_table.lookup.contains(target)) return;
_ = try self.got_table.allocateEntry(self.gpa, target);
if (self.got_section_index == null) {
self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{
self.got_section_index = try MachO.initSection(self.gpa, self, "__DATA_CONST", "__got", .{
.flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
});
}
@ -629,7 +629,7 @@ pub const Zld = struct {
if (self.tlv_ptr_table.lookup.contains(target)) return;
_ = try self.tlv_ptr_table.allocateEntry(self.gpa, target);
if (self.tlv_ptr_section_index == null) {
self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{
self.tlv_ptr_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__thread_ptrs", .{
.flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
});
}
@ -639,18 +639,18 @@ pub const Zld = struct {
if (self.stubs_table.lookup.contains(target)) return;
_ = try self.stubs_table.allocateEntry(self.gpa, target);
if (self.stubs_section_index == null) {
self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{
self.stubs_section_index = try MachO.initSection(self.gpa, self, "__TEXT", "__stubs", .{
.flags = macho.S_SYMBOL_STUBS |
macho.S_ATTR_PURE_INSTRUCTIONS |
macho.S_ATTR_SOME_INSTRUCTIONS,
.reserved2 = stubs.stubSize(self.options.target.cpu.arch),
});
self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{
self.stub_helper_section_index = try MachO.initSection(self.gpa, self, "__TEXT", "__stub_helper", .{
.flags = macho.S_REGULAR |
macho.S_ATTR_PURE_INSTRUCTIONS |
macho.S_ATTR_SOME_INSTRUCTIONS,
});
self.la_symbol_ptr_section_index = try self.initSection("__DATA", "__la_symbol_ptr", .{
self.la_symbol_ptr_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__la_symbol_ptr", .{
.flags = macho.S_LAZY_SYMBOL_POINTERS,
});
}
@ -1152,34 +1152,6 @@ pub const Zld = struct {
segment.vmsize = mem.alignForward(u64, segment.vmsize, page_size);
}
const InitSectionOpts = struct {
flags: u32 = macho.S_REGULAR,
reserved1: u32 = 0,
reserved2: u32 = 0,
};
pub fn initSection(
self: *Zld,
segname: []const u8,
sectname: []const u8,
opts: InitSectionOpts,
) !u8 {
const gpa = self.gpa;
log.debug("creating section '{s},{s}'", .{ segname, sectname });
const index = @as(u8, @intCast(self.sections.slice().len));
try self.sections.append(gpa, .{
.segment_index = undefined, // Segments will be created automatically later down the pipeline
.header = .{
.sectname = makeStaticString(sectname),
.segname = makeStaticString(segname),
.flags = opts.flags,
.reserved1 = opts.reserved1,
.reserved2 = opts.reserved2,
},
});
return index;
}
fn writeSegmentHeaders(self: *Zld, writer: anytype) !void {
for (self.segments.items, 0..) |seg, i| {
const indexes = self.getSectionIndexes(@as(u8, @intCast(i)));