mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
macho: move helper functions to libstd
Helper functions such as `commands.sectionName`, etc. should really belong in `std.macho.section_64` extern struct.
This commit is contained in:
parent
77836e08a2
commit
81e7d8505c
@ -1,3 +1,5 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const mach_header = extern struct {
|
||||
magic: u32,
|
||||
cputype: cpu_type_t,
|
||||
@ -9,14 +11,14 @@ pub const mach_header = extern struct {
|
||||
};
|
||||
|
||||
pub const mach_header_64 = extern struct {
|
||||
magic: u32,
|
||||
cputype: cpu_type_t,
|
||||
cpusubtype: cpu_subtype_t,
|
||||
filetype: u32,
|
||||
ncmds: u32,
|
||||
sizeofcmds: u32,
|
||||
flags: u32,
|
||||
reserved: u32,
|
||||
magic: u32 = MH_MAGIC_64,
|
||||
cputype: cpu_type_t = 0,
|
||||
cpusubtype: cpu_subtype_t = 0,
|
||||
filetype: u32 = 0,
|
||||
ncmds: u32 = 0,
|
||||
sizeofcmds: u32 = 0,
|
||||
flags: u32 = 0,
|
||||
reserved: u32 = 0,
|
||||
};
|
||||
|
||||
pub const fat_header = extern struct {
|
||||
@ -630,6 +632,10 @@ pub const segment_command_64 = extern struct {
|
||||
/// number of sections in segment
|
||||
nsects: u32 = 0,
|
||||
flags: u32 = 0,
|
||||
|
||||
pub fn segName(seg: segment_command_64) []const u8 {
|
||||
return parseName(&seg.segname);
|
||||
}
|
||||
};
|
||||
|
||||
/// A segment is made up of zero or more sections. Non-MH_OBJECT files have
|
||||
@ -728,8 +734,46 @@ pub const section_64 = extern struct {
|
||||
|
||||
/// reserved
|
||||
reserved3: u32 = 0,
|
||||
|
||||
pub fn sectName(sect: section_64) []const u8 {
|
||||
return parseName(§.sectname);
|
||||
}
|
||||
|
||||
pub fn segName(sect: section_64) []const u8 {
|
||||
return parseName(§.segname);
|
||||
}
|
||||
|
||||
pub fn type_(sect: section_64) u8 {
|
||||
return @truncate(u8, sect.flags & 0xff);
|
||||
}
|
||||
|
||||
pub fn attrs(sect: section_64) u32 {
|
||||
return sect.flags & 0xffffff00;
|
||||
}
|
||||
|
||||
pub fn isCode(sect: section_64) bool {
|
||||
const attr = sect.attrs();
|
||||
return attr & S_ATTR_PURE_INSTRUCTIONS != 0 or attr & S_ATTR_SOME_INSTRUCTIONS != 0;
|
||||
}
|
||||
|
||||
pub fn isDebug(sect: section_64) bool {
|
||||
return sect.attrs() & S_ATTR_DEBUG != 0;
|
||||
}
|
||||
|
||||
pub fn isDontDeadStrip(sect: section_64) bool {
|
||||
return sect.attrs() & S_ATTR_NO_DEAD_STRIP != 0;
|
||||
}
|
||||
|
||||
pub fn isDontDeadStripIfReferencesLive(sect: section_64) bool {
|
||||
return sect.attrs() & S_ATTR_LIVE_SUPPORT != 0;
|
||||
}
|
||||
};
|
||||
|
||||
fn parseName(name: *const [16]u8) []const u8 {
|
||||
const len = std.mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
|
||||
return name[0..len];
|
||||
}
|
||||
|
||||
pub const nlist = extern struct {
|
||||
n_strx: u32,
|
||||
n_type: u8,
|
||||
|
||||
@ -1324,10 +1324,10 @@ pub const MatchingSection = struct {
|
||||
};
|
||||
|
||||
pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSection {
|
||||
const segname = commands.segmentName(sect);
|
||||
const sectname = commands.sectionName(sect);
|
||||
const segname = sect.segName();
|
||||
const sectname = sect.sectName();
|
||||
const res: ?MatchingSection = blk: {
|
||||
switch (commands.sectionType(sect)) {
|
||||
switch (sect.type_()) {
|
||||
macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
|
||||
if (self.text_const_section_index == null) {
|
||||
self.text_const_section_index = try self.initSection(
|
||||
@ -1579,7 +1579,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
|
||||
};
|
||||
},
|
||||
macho.S_REGULAR => {
|
||||
if (commands.sectionIsCode(sect)) {
|
||||
if (sect.isCode()) {
|
||||
if (self.text_section_index == null) {
|
||||
self.text_section_index = try self.initSection(
|
||||
self.text_segment_cmd_index.?,
|
||||
@ -1599,7 +1599,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
|
||||
.sect = self.text_section_index.?,
|
||||
};
|
||||
}
|
||||
if (commands.sectionIsDebug(sect)) {
|
||||
if (sect.isDebug()) {
|
||||
// TODO debug attributes
|
||||
if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
|
||||
log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
|
||||
@ -1889,10 +1889,7 @@ fn allocateLocals(self: *MachO) !void {
|
||||
const sect = seg.sections.items[match.sect];
|
||||
var base_vaddr = sect.addr;
|
||||
|
||||
log.debug("allocating local symbols in {s},{s}", .{
|
||||
commands.segmentName(sect),
|
||||
commands.sectionName(sect),
|
||||
});
|
||||
log.debug("allocating local symbols in {s},{s}", .{ sect.segName(), sect.sectName() });
|
||||
|
||||
while (true) {
|
||||
const alignment = try math.powi(u32, 2, atom.alignment);
|
||||
@ -1987,7 +1984,7 @@ fn writeAllAtoms(self: *MachO) !void {
|
||||
defer buffer.deinit();
|
||||
try buffer.ensureTotalCapacity(try math.cast(usize, sect.size));
|
||||
|
||||
log.debug("writing atoms in {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) });
|
||||
log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() });
|
||||
|
||||
while (atom.prev) |prev| {
|
||||
atom = prev;
|
||||
@ -2035,7 +2032,7 @@ fn writeAtoms(self: *MachO) !void {
|
||||
const sect = seg.sections.items[match.sect];
|
||||
var atom: *Atom = entry.value_ptr.*;
|
||||
|
||||
log.debug("writing atoms in {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) });
|
||||
log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() });
|
||||
|
||||
while (atom.prev) |prev| {
|
||||
atom = prev;
|
||||
@ -3005,7 +3002,7 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
|
||||
};
|
||||
}
|
||||
|
||||
log.debug("{s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) });
|
||||
log.debug("{s},{s}", .{ sect.segName(), sect.sectName() });
|
||||
|
||||
while (true) {
|
||||
const alignment = try math.powi(u32, 2, atom.alignment);
|
||||
@ -3049,8 +3046,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
|
||||
const seg = &self.load_commands.items[match.seg].Segment;
|
||||
const sect = &seg.sections.items[match.sect];
|
||||
log.debug("{s},{s} => size: 0x{x}, alignment: 0x{x}", .{
|
||||
commands.segmentName(sect.*),
|
||||
commands.sectionName(sect.*),
|
||||
sect.segName(),
|
||||
sect.sectName(),
|
||||
metadata.size,
|
||||
metadata.alignment,
|
||||
});
|
||||
@ -4507,8 +4504,8 @@ fn initSection(
|
||||
const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null;
|
||||
const off = self.findFreeSpace(segment_id, alignment_pow_2, padding);
|
||||
log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{
|
||||
commands.segmentName(sect),
|
||||
commands.sectionName(sect),
|
||||
sect.segName(),
|
||||
sect.sectName(),
|
||||
off,
|
||||
off + size,
|
||||
});
|
||||
@ -4596,8 +4593,8 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void {
|
||||
moved_sect.addr += offset_amt;
|
||||
|
||||
log.debug(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{
|
||||
commands.segmentName(moved_sect.*),
|
||||
commands.sectionName(moved_sect.*),
|
||||
moved_sect.segName(),
|
||||
moved_sect.sectName(),
|
||||
moved_sect.offset,
|
||||
moved_sect.offset + moved_sect.size,
|
||||
moved_sect.addr,
|
||||
@ -4670,8 +4667,8 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void {
|
||||
moved_sect.addr += offset_amt;
|
||||
|
||||
log.debug(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{
|
||||
commands.segmentName(moved_sect.*),
|
||||
commands.sectionName(moved_sect.*),
|
||||
moved_sect.segName(),
|
||||
moved_sect.sectName(),
|
||||
moved_sect.offset,
|
||||
moved_sect.offset + moved_sect.size,
|
||||
moved_sect.addr,
|
||||
@ -5784,9 +5781,8 @@ fn writeLoadCommands(self: *MachO) !void {
|
||||
|
||||
/// Writes Mach-O file header.
|
||||
fn writeHeader(self: *MachO) !void {
|
||||
var header = commands.emptyHeader(.{
|
||||
.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL,
|
||||
});
|
||||
var header: macho.mach_header_64 = .{};
|
||||
header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL;
|
||||
|
||||
switch (self.base.options.target.cpu.arch) {
|
||||
.aarch64 => {
|
||||
@ -5961,10 +5957,7 @@ fn snapshotState(self: *MachO) !void {
|
||||
for (self.section_ordinals.keys()) |key| {
|
||||
const seg = self.load_commands.items[key.seg].Segment;
|
||||
const sect = seg.sections.items[key.sect];
|
||||
const sect_name = try std.fmt.allocPrint(arena, "{s},{s}", .{
|
||||
commands.segmentName(sect),
|
||||
commands.sectionName(sect),
|
||||
});
|
||||
const sect_name = try std.fmt.allocPrint(arena, "{s},{s}", .{ sect.segName(), sect.sectName() });
|
||||
try nodes.append(.{
|
||||
.address = sect.addr,
|
||||
.tag = .section_start,
|
||||
@ -6037,7 +6030,7 @@ fn snapshotState(self: *MachO) !void {
|
||||
const match = self.section_ordinals.keys()[source_sym.n_sect - 1];
|
||||
const match_seg = self.load_commands.items[match.seg].Segment;
|
||||
const match_sect = match_seg.sections.items[match.sect];
|
||||
break :is_tlv commands.sectionType(match_sect) == macho.S_THREAD_LOCAL_VARIABLES;
|
||||
break :is_tlv match_sect.type_() == macho.S_THREAD_LOCAL_VARIABLES;
|
||||
};
|
||||
if (is_tlv) {
|
||||
const match_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
|
||||
@ -6206,8 +6199,8 @@ fn logSectionOrdinals(self: MachO) void {
|
||||
i + 1,
|
||||
match.seg,
|
||||
match.sect,
|
||||
commands.segmentName(sect),
|
||||
commands.sectionName(sect),
|
||||
sect.segName(),
|
||||
sect.sectName(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ const std = @import("std");
|
||||
const build_options = @import("build_options");
|
||||
const aarch64 = @import("../../arch/aarch64/bits.zig");
|
||||
const assert = std.debug.assert;
|
||||
const commands = @import("commands.zig");
|
||||
const log = std.log.scoped(.link);
|
||||
const macho = std.macho;
|
||||
const math = std.math;
|
||||
@ -492,7 +491,7 @@ fn addPtrBindingOrRebase(
|
||||
const match = context.macho_file.section_ordinals.keys()[source_sym.n_sect - 1];
|
||||
const seg = context.macho_file.load_commands.items[match.seg].Segment;
|
||||
const sect = seg.sections.items[match.sect];
|
||||
const sect_type = commands.sectionType(sect);
|
||||
const sect_type = sect.type_();
|
||||
|
||||
const should_rebase = rebase: {
|
||||
if (rel.r_length != 3) break :rebase false;
|
||||
@ -707,7 +706,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
|
||||
const match = macho_file.section_ordinals.keys()[source_sym.n_sect - 1];
|
||||
const seg = macho_file.load_commands.items[match.seg].Segment;
|
||||
const sect = seg.sections.items[match.sect];
|
||||
break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES;
|
||||
break :is_tlv sect.type_() == macho.S_THREAD_LOCAL_VARIABLES;
|
||||
};
|
||||
if (is_tlv) {
|
||||
// For TLV relocations, the value specified as a relocation is the displacement from the
|
||||
|
||||
@ -241,8 +241,8 @@ fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignme
|
||||
assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand
|
||||
|
||||
log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
|
||||
commands.segmentName(sect),
|
||||
commands.sectionName(sect),
|
||||
sect.segName(),
|
||||
sect.sectName(),
|
||||
off,
|
||||
off + size,
|
||||
});
|
||||
@ -670,9 +670,8 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: Allocator) !void {
|
||||
}
|
||||
|
||||
fn writeHeader(self: *DebugSymbols) !void {
|
||||
var header = commands.emptyHeader(.{
|
||||
.filetype = macho.MH_DSYM,
|
||||
});
|
||||
var header: macho.mach_header_64 = .{};
|
||||
header.filetype = macho.MH_DSYM;
|
||||
|
||||
switch (self.base.base.options.target.cpu.arch) {
|
||||
.aarch64 => {
|
||||
|
||||
@ -11,14 +11,11 @@ const macho = std.macho;
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
const sort = std.sort;
|
||||
const commands = @import("commands.zig");
|
||||
const segmentName = commands.segmentName;
|
||||
const sectionName = commands.sectionName;
|
||||
const trace = @import("../../tracy.zig").trace;
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const Atom = @import("Atom.zig");
|
||||
const LoadCommand = commands.LoadCommand;
|
||||
const LoadCommand = @import("commands.zig").LoadCommand;
|
||||
const MachO = @import("../MachO.zig");
|
||||
|
||||
file: fs.File,
|
||||
@ -278,8 +275,8 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v
|
||||
var seg = cmd.Segment;
|
||||
for (seg.sections.items) |*sect, j| {
|
||||
const index = @intCast(u16, j);
|
||||
const segname = segmentName(sect.*);
|
||||
const sectname = sectionName(sect.*);
|
||||
const segname = sect.segName();
|
||||
const sectname = sect.sectName();
|
||||
if (mem.eql(u8, segname, "__DWARF")) {
|
||||
if (mem.eql(u8, sectname, "__debug_info")) {
|
||||
self.dwarf_debug_info_index = index;
|
||||
@ -424,10 +421,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) !
|
||||
|
||||
for (seg.sections.items) |sect, id| {
|
||||
const sect_id = @intCast(u8, id);
|
||||
log.debug("putting section '{s},{s}' as an Atom", .{
|
||||
segmentName(sect),
|
||||
sectionName(sect),
|
||||
});
|
||||
log.debug("putting section '{s},{s}' as an Atom", .{ sect.segName(), sect.sectName() });
|
||||
|
||||
// Get matching segment/section in the final artifact.
|
||||
const match = (try macho_file.getMatchingSection(sect)) orelse {
|
||||
@ -479,7 +473,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) !
|
||||
const atom = try macho_file.createEmptyAtom(atom_local_sym_index, aligned_size, sect.@"align");
|
||||
|
||||
const is_zerofill = blk: {
|
||||
const section_type = commands.sectionType(sect);
|
||||
const section_type = sect.type_();
|
||||
break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL;
|
||||
};
|
||||
if (!is_zerofill) {
|
||||
|
||||
@ -12,28 +12,6 @@ const MachO = @import("../MachO.zig");
|
||||
const makeStaticString = MachO.makeStaticString;
|
||||
const padToIdeal = MachO.padToIdeal;
|
||||
|
||||
pub const HeaderArgs = struct {
|
||||
magic: u32 = macho.MH_MAGIC_64,
|
||||
cputype: macho.cpu_type_t = 0,
|
||||
cpusubtype: macho.cpu_subtype_t = 0,
|
||||
filetype: u32 = 0,
|
||||
flags: u32 = 0,
|
||||
reserved: u32 = 0,
|
||||
};
|
||||
|
||||
pub fn emptyHeader(args: HeaderArgs) macho.mach_header_64 {
|
||||
return .{
|
||||
.magic = args.magic,
|
||||
.cputype = args.cputype,
|
||||
.cpusubtype = args.cpusubtype,
|
||||
.filetype = args.filetype,
|
||||
.ncmds = 0,
|
||||
.sizeofcmds = 0,
|
||||
.flags = args.flags,
|
||||
.reserved = args.reserved,
|
||||
};
|
||||
}
|
||||
|
||||
pub const LoadCommand = union(enum) {
|
||||
Segment: SegmentCommand,
|
||||
DyldInfoOnly: macho.dyld_info_command,
|
||||
@ -357,44 +335,6 @@ pub fn createLoadDylibCommand(
|
||||
return dylib_cmd;
|
||||
}
|
||||
|
||||
fn parseName(name: *const [16]u8) []const u8 {
|
||||
const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
|
||||
return name[0..len];
|
||||
}
|
||||
|
||||
pub fn segmentName(sect: macho.section_64) []const u8 {
|
||||
return parseName(§.segname);
|
||||
}
|
||||
|
||||
pub fn sectionName(sect: macho.section_64) []const u8 {
|
||||
return parseName(§.sectname);
|
||||
}
|
||||
|
||||
pub fn sectionType(sect: macho.section_64) u8 {
|
||||
return @truncate(u8, sect.flags & 0xff);
|
||||
}
|
||||
|
||||
pub fn sectionAttrs(sect: macho.section_64) u32 {
|
||||
return sect.flags & 0xffffff00;
|
||||
}
|
||||
|
||||
pub fn sectionIsCode(sect: macho.section_64) bool {
|
||||
const attr = sectionAttrs(sect);
|
||||
return attr & macho.S_ATTR_PURE_INSTRUCTIONS != 0 or attr & macho.S_ATTR_SOME_INSTRUCTIONS != 0;
|
||||
}
|
||||
|
||||
pub fn sectionIsDebug(sect: macho.section_64) bool {
|
||||
return sectionAttrs(sect) & macho.S_ATTR_DEBUG != 0;
|
||||
}
|
||||
|
||||
pub fn sectionIsDontDeadStrip(sect: macho.section_64) bool {
|
||||
return sectionAttrs(sect) & macho.S_ATTR_NO_DEAD_STRIP != 0;
|
||||
}
|
||||
|
||||
pub fn sectionIsDontDeadStripIfReferencesLive(sect: macho.section_64) bool {
|
||||
return sectionAttrs(sect) & macho.S_ATTR_LIVE_SUPPORT != 0;
|
||||
}
|
||||
|
||||
fn testRead(allocator: Allocator, buffer: []const u8, expected: anytype) !void {
|
||||
var stream = io.fixedBufferStream(buffer);
|
||||
var given = try LoadCommand.read(allocator, stream.reader());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user