| author | |
| committer | |
| log | 81e7d8505c086a93accb74e9f1a84abb8ff7cf24 |
| tree | 9f4a8814448537da53d2eeab838672401a024eb5 |
| parent | 77836e08a2384450b5e7933094511b61e3c22140 |
Helper functions such as `commands.sectionName`, etc. should really
belong in `std.macho.section_64` extern struct.6 files changed, 86 insertions(+), 117 deletions(-)
lib/std/macho.zig+52-8| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 1 | 3 | pub const mach_header = extern struct { |
| 2 | 4 | magic: u32, |
| 3 | 5 | cputype: cpu_type_t, |
| ... | ... | @@ -9,14 +11,14 @@ pub const mach_header = extern struct { |
| 9 | 11 | }; |
| 10 | 12 | |
| 11 | 13 | pub const mach_header_64 = extern struct { |
| 12 | magic: u32, | |
| 13 | cputype: cpu_type_t, | |
| 14 | cpusubtype: cpu_subtype_t, | |
| 15 | filetype: u32, | |
| 16 | ncmds: u32, | |
| 17 | sizeofcmds: u32, | |
| 18 | flags: u32, | |
| 19 | reserved: u32, | |
| 14 | magic: u32 = MH_MAGIC_64, | |
| 15 | cputype: cpu_type_t = 0, | |
| 16 | cpusubtype: cpu_subtype_t = 0, | |
| 17 | filetype: u32 = 0, | |
| 18 | ncmds: u32 = 0, | |
| 19 | sizeofcmds: u32 = 0, | |
| 20 | flags: u32 = 0, | |
| 21 | reserved: u32 = 0, | |
| 20 | 22 | }; |
| 21 | 23 | |
| 22 | 24 | pub const fat_header = extern struct { |
| ... | ... | @@ -630,6 +632,10 @@ pub const segment_command_64 = extern struct { |
| 630 | 632 | /// number of sections in segment |
| 631 | 633 | nsects: u32 = 0, |
| 632 | 634 | flags: u32 = 0, |
| 635 | ||
| 636 | pub fn segName(seg: segment_command_64) []const u8 { | |
| 637 | return parseName(&seg.segname); | |
| 638 | } | |
| 633 | 639 | }; |
| 634 | 640 | |
| 635 | 641 | /// 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 { |
| 728 | 734 | |
| 729 | 735 | /// reserved |
| 730 | 736 | reserved3: u32 = 0, |
| 737 | ||
| 738 | pub fn sectName(sect: section_64) []const u8 { | |
| 739 | return parseName(&sect.sectname); | |
| 740 | } | |
| 741 | ||
| 742 | pub fn segName(sect: section_64) []const u8 { | |
| 743 | return parseName(&sect.segname); | |
| 744 | } | |
| 745 | ||
| 746 | pub fn type_(sect: section_64) u8 { | |
| 747 | return @truncate(u8, sect.flags & 0xff); | |
| 748 | } | |
| 749 | ||
| 750 | pub fn attrs(sect: section_64) u32 { | |
| 751 | return sect.flags & 0xffffff00; | |
| 752 | } | |
| 753 | ||
| 754 | pub fn isCode(sect: section_64) bool { | |
| 755 | const attr = sect.attrs(); | |
| 756 | return attr & S_ATTR_PURE_INSTRUCTIONS != 0 or attr & S_ATTR_SOME_INSTRUCTIONS != 0; | |
| 757 | } | |
| 758 | ||
| 759 | pub fn isDebug(sect: section_64) bool { | |
| 760 | return sect.attrs() & S_ATTR_DEBUG != 0; | |
| 761 | } | |
| 762 | ||
| 763 | pub fn isDontDeadStrip(sect: section_64) bool { | |
| 764 | return sect.attrs() & S_ATTR_NO_DEAD_STRIP != 0; | |
| 765 | } | |
| 766 | ||
| 767 | pub fn isDontDeadStripIfReferencesLive(sect: section_64) bool { | |
| 768 | return sect.attrs() & S_ATTR_LIVE_SUPPORT != 0; | |
| 769 | } | |
| 731 | 770 | }; |
| 732 | 771 | |
| 772 | fn parseName(name: *const [16]u8) []const u8 { | |
| 773 | const len = std.mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len; | |
| 774 | return name[0..len]; | |
| 775 | } | |
| 776 | ||
| 733 | 777 | pub const nlist = extern struct { |
| 734 | 778 | n_strx: u32, |
| 735 | 779 | n_type: u8, |
src/link/MachO.zig+23-30| ... | ... | @@ -1324,10 +1324,10 @@ pub const MatchingSection = struct { |
| 1324 | 1324 | }; |
| 1325 | 1325 | |
| 1326 | 1326 | pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSection { |
| 1327 | const segname = commands.segmentName(sect); | |
| 1328 | const sectname = commands.sectionName(sect); | |
| 1327 | const segname = sect.segName(); | |
| 1328 | const sectname = sect.sectName(); | |
| 1329 | 1329 | const res: ?MatchingSection = blk: { |
| 1330 | switch (commands.sectionType(sect)) { | |
| 1330 | switch (sect.type_()) { | |
| 1331 | 1331 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 1332 | 1332 | if (self.text_const_section_index == null) { |
| 1333 | 1333 | self.text_const_section_index = try self.initSection( |
| ... | ... | @@ -1579,7 +1579,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1579 | 1579 | }; |
| 1580 | 1580 | }, |
| 1581 | 1581 | macho.S_REGULAR => { |
| 1582 | if (commands.sectionIsCode(sect)) { | |
| 1582 | if (sect.isCode()) { | |
| 1583 | 1583 | if (self.text_section_index == null) { |
| 1584 | 1584 | self.text_section_index = try self.initSection( |
| 1585 | 1585 | self.text_segment_cmd_index.?, |
| ... | ... | @@ -1599,7 +1599,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1599 | 1599 | .sect = self.text_section_index.?, |
| 1600 | 1600 | }; |
| 1601 | 1601 | } |
| 1602 | if (commands.sectionIsDebug(sect)) { | |
| 1602 | if (sect.isDebug()) { | |
| 1603 | 1603 | // TODO debug attributes |
| 1604 | 1604 | if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) { |
| 1605 | 1605 | log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{ |
| ... | ... | @@ -1889,10 +1889,7 @@ fn allocateLocals(self: *MachO) !void { |
| 1889 | 1889 | const sect = seg.sections.items[match.sect]; |
| 1890 | 1890 | var base_vaddr = sect.addr; |
| 1891 | 1891 | |
| 1892 | log.debug("allocating local symbols in {s},{s}", .{ | |
| 1893 | commands.segmentName(sect), | |
| 1894 | commands.sectionName(sect), | |
| 1895 | }); | |
| 1892 | log.debug("allocating local symbols in {s},{s}", .{ sect.segName(), sect.sectName() }); | |
| 1896 | 1893 | |
| 1897 | 1894 | while (true) { |
| 1898 | 1895 | const alignment = try math.powi(u32, 2, atom.alignment); |
| ... | ... | @@ -1987,7 +1984,7 @@ fn writeAllAtoms(self: *MachO) !void { |
| 1987 | 1984 | defer buffer.deinit(); |
| 1988 | 1985 | try buffer.ensureTotalCapacity(try math.cast(usize, sect.size)); |
| 1989 | 1986 | |
| 1990 | log.debug("writing atoms in {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); | |
| 1987 | log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() }); | |
| 1991 | 1988 | |
| 1992 | 1989 | while (atom.prev) |prev| { |
| 1993 | 1990 | atom = prev; |
| ... | ... | @@ -2035,7 +2032,7 @@ fn writeAtoms(self: *MachO) !void { |
| 2035 | 2032 | const sect = seg.sections.items[match.sect]; |
| 2036 | 2033 | var atom: *Atom = entry.value_ptr.*; |
| 2037 | 2034 | |
| 2038 | log.debug("writing atoms in {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); | |
| 2035 | log.debug("writing atoms in {s},{s}", .{ sect.segName(), sect.sectName() }); | |
| 2039 | 2036 | |
| 2040 | 2037 | while (atom.prev) |prev| { |
| 2041 | 2038 | atom = prev; |
| ... | ... | @@ -3005,7 +3002,7 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 3005 | 3002 | }; |
| 3006 | 3003 | } |
| 3007 | 3004 | |
| 3008 | log.debug("{s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); | |
| 3005 | log.debug("{s},{s}", .{ sect.segName(), sect.sectName() }); | |
| 3009 | 3006 | |
| 3010 | 3007 | while (true) { |
| 3011 | 3008 | const alignment = try math.powi(u32, 2, atom.alignment); |
| ... | ... | @@ -3049,8 +3046,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 3049 | 3046 | const seg = &self.load_commands.items[match.seg].Segment; |
| 3050 | 3047 | const sect = &seg.sections.items[match.sect]; |
| 3051 | 3048 | log.debug("{s},{s} => size: 0x{x}, alignment: 0x{x}", .{ |
| 3052 | commands.segmentName(sect.*), | |
| 3053 | commands.sectionName(sect.*), | |
| 3049 | sect.segName(), | |
| 3050 | sect.sectName(), | |
| 3054 | 3051 | metadata.size, |
| 3055 | 3052 | metadata.alignment, |
| 3056 | 3053 | }); |
| ... | ... | @@ -4507,8 +4504,8 @@ fn initSection( |
| 4507 | 4504 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 4508 | 4505 | const off = self.findFreeSpace(segment_id, alignment_pow_2, padding); |
| 4509 | 4506 | log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{ |
| 4510 | commands.segmentName(sect), | |
| 4511 | commands.sectionName(sect), | |
| 4507 | sect.segName(), | |
| 4508 | sect.sectName(), | |
| 4512 | 4509 | off, |
| 4513 | 4510 | off + size, |
| 4514 | 4511 | }); |
| ... | ... | @@ -4596,8 +4593,8 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void { |
| 4596 | 4593 | moved_sect.addr += offset_amt; |
| 4597 | 4594 | |
| 4598 | 4595 | log.debug(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{ |
| 4599 | commands.segmentName(moved_sect.*), | |
| 4600 | commands.sectionName(moved_sect.*), | |
| 4596 | moved_sect.segName(), | |
| 4597 | moved_sect.sectName(), | |
| 4601 | 4598 | moved_sect.offset, |
| 4602 | 4599 | moved_sect.offset + moved_sect.size, |
| 4603 | 4600 | moved_sect.addr, |
| ... | ... | @@ -4670,8 +4667,8 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void { |
| 4670 | 4667 | moved_sect.addr += offset_amt; |
| 4671 | 4668 | |
| 4672 | 4669 | log.debug(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{ |
| 4673 | commands.segmentName(moved_sect.*), | |
| 4674 | commands.sectionName(moved_sect.*), | |
| 4670 | moved_sect.segName(), | |
| 4671 | moved_sect.sectName(), | |
| 4675 | 4672 | moved_sect.offset, |
| 4676 | 4673 | moved_sect.offset + moved_sect.size, |
| 4677 | 4674 | moved_sect.addr, |
| ... | ... | @@ -5784,9 +5781,8 @@ fn writeLoadCommands(self: *MachO) !void { |
| 5784 | 5781 | |
| 5785 | 5782 | /// Writes Mach-O file header. |
| 5786 | 5783 | fn writeHeader(self: *MachO) !void { |
| 5787 | var header = commands.emptyHeader(.{ | |
| 5788 | .flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL, | |
| 5789 | }); | |
| 5784 | var header: macho.mach_header_64 = .{}; | |
| 5785 | header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL; | |
| 5790 | 5786 | |
| 5791 | 5787 | switch (self.base.options.target.cpu.arch) { |
| 5792 | 5788 | .aarch64 => { |
| ... | ... | @@ -5961,10 +5957,7 @@ fn snapshotState(self: *MachO) !void { |
| 5961 | 5957 | for (self.section_ordinals.keys()) |key| { |
| 5962 | 5958 | const seg = self.load_commands.items[key.seg].Segment; |
| 5963 | 5959 | const sect = seg.sections.items[key.sect]; |
| 5964 | const sect_name = try std.fmt.allocPrint(arena, "{s},{s}", .{ | |
| 5965 | commands.segmentName(sect), | |
| 5966 | commands.sectionName(sect), | |
| 5967 | }); | |
| 5960 | const sect_name = try std.fmt.allocPrint(arena, "{s},{s}", .{ sect.segName(), sect.sectName() }); | |
| 5968 | 5961 | try nodes.append(.{ |
| 5969 | 5962 | .address = sect.addr, |
| 5970 | 5963 | .tag = .section_start, |
| ... | ... | @@ -6037,7 +6030,7 @@ fn snapshotState(self: *MachO) !void { |
| 6037 | 6030 | const match = self.section_ordinals.keys()[source_sym.n_sect - 1]; |
| 6038 | 6031 | const match_seg = self.load_commands.items[match.seg].Segment; |
| 6039 | 6032 | const match_sect = match_seg.sections.items[match.sect]; |
| 6040 | break :is_tlv commands.sectionType(match_sect) == macho.S_THREAD_LOCAL_VARIABLES; | |
| 6033 | break :is_tlv match_sect.type_() == macho.S_THREAD_LOCAL_VARIABLES; | |
| 6041 | 6034 | }; |
| 6042 | 6035 | if (is_tlv) { |
| 6043 | 6036 | const match_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| ... | ... | @@ -6206,8 +6199,8 @@ fn logSectionOrdinals(self: MachO) void { |
| 6206 | 6199 | i + 1, |
| 6207 | 6200 | match.seg, |
| 6208 | 6201 | match.sect, |
| 6209 | commands.segmentName(sect), | |
| 6210 | commands.sectionName(sect), | |
| 6202 | sect.segName(), | |
| 6203 | sect.sectName(), | |
| 6211 | 6204 | }); |
| 6212 | 6205 | } |
| 6213 | 6206 | } |
src/link/MachO/Atom.zig+2-3| ... | ... | @@ -4,7 +4,6 @@ const std = @import("std"); |
| 4 | 4 | const build_options = @import("build_options"); |
| 5 | 5 | const aarch64 = @import("../../arch/aarch64/bits.zig"); |
| 6 | 6 | const assert = std.debug.assert; |
| 7 | const commands = @import("commands.zig"); | |
| 8 | 7 | const log = std.log.scoped(.link); |
| 9 | 8 | const macho = std.macho; |
| 10 | 9 | const math = std.math; |
| ... | ... | @@ -492,7 +491,7 @@ fn addPtrBindingOrRebase( |
| 492 | 491 | const match = context.macho_file.section_ordinals.keys()[source_sym.n_sect - 1]; |
| 493 | 492 | const seg = context.macho_file.load_commands.items[match.seg].Segment; |
| 494 | 493 | const sect = seg.sections.items[match.sect]; |
| 495 | const sect_type = commands.sectionType(sect); | |
| 494 | const sect_type = sect.type_(); | |
| 496 | 495 | |
| 497 | 496 | const should_rebase = rebase: { |
| 498 | 497 | if (rel.r_length != 3) break :rebase false; |
| ... | ... | @@ -707,7 +706,7 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { |
| 707 | 706 | const match = macho_file.section_ordinals.keys()[source_sym.n_sect - 1]; |
| 708 | 707 | const seg = macho_file.load_commands.items[match.seg].Segment; |
| 709 | 708 | const sect = seg.sections.items[match.sect]; |
| 710 | break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES; | |
| 709 | break :is_tlv sect.type_() == macho.S_THREAD_LOCAL_VARIABLES; | |
| 711 | 710 | }; |
| 712 | 711 | if (is_tlv) { |
| 713 | 712 | // For TLV relocations, the value specified as a relocation is the displacement from the |
src/link/MachO/DebugSymbols.zig+4-5| ... | ... | @@ -241,8 +241,8 @@ fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignme |
| 241 | 241 | assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand |
| 242 | 242 | |
| 243 | 243 | log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{ |
| 244 | commands.segmentName(sect), | |
| 245 | commands.sectionName(sect), | |
| 244 | sect.segName(), | |
| 245 | sect.sectName(), | |
| 246 | 246 | off, |
| 247 | 247 | off + size, |
| 248 | 248 | }); |
| ... | ... | @@ -670,9 +670,8 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: Allocator) !void { |
| 670 | 670 | } |
| 671 | 671 | |
| 672 | 672 | fn writeHeader(self: *DebugSymbols) !void { |
| 673 | var header = commands.emptyHeader(.{ | |
| 674 | .filetype = macho.MH_DSYM, | |
| 675 | }); | |
| 673 | var header: macho.mach_header_64 = .{}; | |
| 674 | header.filetype = macho.MH_DSYM; | |
| 676 | 675 | |
| 677 | 676 | switch (self.base.base.options.target.cpu.arch) { |
| 678 | 677 | .aarch64 => { |
src/link/MachO/Object.zig+5-11| ... | ... | @@ -11,14 +11,11 @@ const macho = std.macho; |
| 11 | 11 | const math = std.math; |
| 12 | 12 | const mem = std.mem; |
| 13 | 13 | const sort = std.sort; |
| 14 | const commands = @import("commands.zig"); | |
| 15 | const segmentName = commands.segmentName; | |
| 16 | const sectionName = commands.sectionName; | |
| 17 | 14 | const trace = @import("../../tracy.zig").trace; |
| 18 | 15 | |
| 19 | 16 | const Allocator = mem.Allocator; |
| 20 | 17 | const Atom = @import("Atom.zig"); |
| 21 | const LoadCommand = commands.LoadCommand; | |
| 18 | const LoadCommand = @import("commands.zig").LoadCommand; | |
| 22 | 19 | const MachO = @import("../MachO.zig"); |
| 23 | 20 | |
| 24 | 21 | file: fs.File, |
| ... | ... | @@ -278,8 +275,8 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v |
| 278 | 275 | var seg = cmd.Segment; |
| 279 | 276 | for (seg.sections.items) |*sect, j| { |
| 280 | 277 | const index = @intCast(u16, j); |
| 281 | const segname = segmentName(sect.*); | |
| 282 | const sectname = sectionName(sect.*); | |
| 278 | const segname = sect.segName(); | |
| 279 | const sectname = sect.sectName(); | |
| 283 | 280 | if (mem.eql(u8, segname, "__DWARF")) { |
| 284 | 281 | if (mem.eql(u8, sectname, "__debug_info")) { |
| 285 | 282 | self.dwarf_debug_info_index = index; |
| ... | ... | @@ -424,10 +421,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 424 | 421 | |
| 425 | 422 | for (seg.sections.items) |sect, id| { |
| 426 | 423 | const sect_id = @intCast(u8, id); |
| 427 | log.debug("putting section '{s},{s}' as an Atom", .{ | |
| 428 | segmentName(sect), | |
| 429 | sectionName(sect), | |
| 430 | }); | |
| 424 | log.debug("putting section '{s},{s}' as an Atom", .{ sect.segName(), sect.sectName() }); | |
| 431 | 425 | |
| 432 | 426 | // Get matching segment/section in the final artifact. |
| 433 | 427 | const match = (try macho_file.getMatchingSection(sect)) orelse { |
| ... | ... | @@ -479,7 +473,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 479 | 473 | const atom = try macho_file.createEmptyAtom(atom_local_sym_index, aligned_size, sect.@"align"); |
| 480 | 474 | |
| 481 | 475 | const is_zerofill = blk: { |
| 482 | const section_type = commands.sectionType(sect); | |
| 476 | const section_type = sect.type_(); | |
| 483 | 477 | break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL; |
| 484 | 478 | }; |
| 485 | 479 | if (!is_zerofill) { |
src/link/MachO/commands.zig-60| ... | ... | @@ -12,28 +12,6 @@ const MachO = @import("../MachO.zig"); |
| 12 | 12 | const makeStaticString = MachO.makeStaticString; |
| 13 | 13 | const padToIdeal = MachO.padToIdeal; |
| 14 | 14 | |
| 15 | pub const HeaderArgs = struct { | |
| 16 | magic: u32 = macho.MH_MAGIC_64, | |
| 17 | cputype: macho.cpu_type_t = 0, | |
| 18 | cpusubtype: macho.cpu_subtype_t = 0, | |
| 19 | filetype: u32 = 0, | |
| 20 | flags: u32 = 0, | |
| 21 | reserved: u32 = 0, | |
| 22 | }; | |
| 23 | ||
| 24 | pub fn emptyHeader(args: HeaderArgs) macho.mach_header_64 { | |
| 25 | return .{ | |
| 26 | .magic = args.magic, | |
| 27 | .cputype = args.cputype, | |
| 28 | .cpusubtype = args.cpusubtype, | |
| 29 | .filetype = args.filetype, | |
| 30 | .ncmds = 0, | |
| 31 | .sizeofcmds = 0, | |
| 32 | .flags = args.flags, | |
| 33 | .reserved = args.reserved, | |
| 34 | }; | |
| 35 | } | |
| 36 | ||
| 37 | 15 | pub const LoadCommand = union(enum) { |
| 38 | 16 | Segment: SegmentCommand, |
| 39 | 17 | DyldInfoOnly: macho.dyld_info_command, |
| ... | ... | @@ -357,44 +335,6 @@ pub fn createLoadDylibCommand( |
| 357 | 335 | return dylib_cmd; |
| 358 | 336 | } |
| 359 | 337 | |
| 360 | fn parseName(name: *const [16]u8) []const u8 { | |
| 361 | const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len; | |
| 362 | return name[0..len]; | |
| 363 | } | |
| 364 | ||
| 365 | pub fn segmentName(sect: macho.section_64) []const u8 { | |
| 366 | return parseName(&sect.segname); | |
| 367 | } | |
| 368 | ||
| 369 | pub fn sectionName(sect: macho.section_64) []const u8 { | |
| 370 | return parseName(&sect.sectname); | |
| 371 | } | |
| 372 | ||
| 373 | pub fn sectionType(sect: macho.section_64) u8 { | |
| 374 | return @truncate(u8, sect.flags & 0xff); | |
| 375 | } | |
| 376 | ||
| 377 | pub fn sectionAttrs(sect: macho.section_64) u32 { | |
| 378 | return sect.flags & 0xffffff00; | |
| 379 | } | |
| 380 | ||
| 381 | pub fn sectionIsCode(sect: macho.section_64) bool { | |
| 382 | const attr = sectionAttrs(sect); | |
| 383 | return attr & macho.S_ATTR_PURE_INSTRUCTIONS != 0 or attr & macho.S_ATTR_SOME_INSTRUCTIONS != 0; | |
| 384 | } | |
| 385 | ||
| 386 | pub fn sectionIsDebug(sect: macho.section_64) bool { | |
| 387 | return sectionAttrs(sect) & macho.S_ATTR_DEBUG != 0; | |
| 388 | } | |
| 389 | ||
| 390 | pub fn sectionIsDontDeadStrip(sect: macho.section_64) bool { | |
| 391 | return sectionAttrs(sect) & macho.S_ATTR_NO_DEAD_STRIP != 0; | |
| 392 | } | |
| 393 | ||
| 394 | pub fn sectionIsDontDeadStripIfReferencesLive(sect: macho.section_64) bool { | |
| 395 | return sectionAttrs(sect) & macho.S_ATTR_LIVE_SUPPORT != 0; | |
| 396 | } | |
| 397 | ||
| 398 | 338 | fn testRead(allocator: Allocator, buffer: []const u8, expected: anytype) !void { |
| 399 | 339 | var stream = io.fixedBufferStream(buffer); |
| 400 | 340 | var given = try LoadCommand.read(allocator, stream.reader()); |