authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-04 12:56:14+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log5b3c4691e628cb288e6595974781ffbadb717c28
tree14a665cc9085cc5f9c324cdf8cd85e3e96af29e2
parent453c16d8acead9bc5ef19155474ba8af37d151cf

zld: put relocs in a TextBlock


3 files changed, 185 insertions(+), 126 deletions(-)

src/link/MachO/Object.zig+103-85
...@@ -9,13 +9,13 @@ const log = std.log.scoped(.object);...@@ -9,13 +9,13 @@ const log = std.log.scoped(.object);
9const macho = std.macho;9const macho = std.macho;
10const mem = std.mem;10const mem = std.mem;
11const reloc = @import("reloc.zig");11const reloc = @import("reloc.zig");
12const parseName = @import("Zld.zig").parseName;
1312
14const Allocator = mem.Allocator;13const Allocator = mem.Allocator;
15const Arch = std.Target.Cpu.Arch;14const Arch = std.Target.Cpu.Arch;
16const Relocation = reloc.Relocation;15const Relocation = reloc.Relocation;
17const Symbol = @import("Symbol.zig");16const Symbol = @import("Symbol.zig");
18const TextBlock = @import("Zld.zig").TextBlock;17const TextBlock = Zld.TextBlock;
18const Zld = @import("Zld.zig");
1919
20usingnamespace @import("commands.zig");20usingnamespace @import("commands.zig");
2121
...@@ -74,43 +74,6 @@ pub const Section = struct {...@@ -74,43 +74,6 @@ pub const Section = struct {
74 allocator.free(relocs);74 allocator.free(relocs);
75 }75 }
76 }76 }
77
78 pub fn segname(self: Section) []const u8 {
79 return parseName(&self.inner.segname);
80 }
81
82 pub fn sectname(self: Section) []const u8 {
83 return parseName(&self.inner.sectname);
84 }
85
86 pub fn flags(self: Section) u32 {
87 return self.inner.flags;
88 }
89
90 pub fn sectionType(self: Section) u8 {
91 return @truncate(u8, self.flags() & 0xff);
92 }
93
94 pub fn sectionAttrs(self: Section) u32 {
95 return self.flags() & 0xffffff00;
96 }
97
98 pub fn isCode(self: Section) bool {
99 const attr = self.sectionAttrs();
100 return attr & macho.S_ATTR_PURE_INSTRUCTIONS != 0 or attr & macho.S_ATTR_SOME_INSTRUCTIONS != 0;
101 }
102
103 pub fn isDebug(self: Section) bool {
104 return self.sectionAttrs() & macho.S_ATTR_DEBUG != 0;
105 }
106
107 pub fn dontDeadStrip(self: Section) bool {
108 return self.sectionAttrs() & macho.S_ATTR_NO_DEAD_STRIP != 0;
109 }
110
111 pub fn dontDeadStripIfReferencesLive(self: Section) bool {
112 return self.sectionAttrs() & macho.S_ATTR_LIVE_SUPPORT != 0;
113 }
114};77};
11578
116const DebugInfo = struct {79const DebugInfo = struct {
...@@ -272,7 +235,6 @@ pub fn parse(self: *Object) !void {...@@ -272,7 +235,6 @@ pub fn parse(self: *Object) !void {
272 try self.parseSymtab();235 try self.parseSymtab();
273 try self.parseDataInCode();236 try self.parseDataInCode();
274 try self.parseInitializers();237 try self.parseInitializers();
275 try self.parseDummy();
276}238}
277239
278pub fn readLoadCommands(self: *Object, reader: anytype) !void {240pub fn readLoadCommands(self: *Object, reader: anytype) !void {
...@@ -288,8 +250,8 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {...@@ -288,8 +250,8 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
288 var seg = cmd.Segment;250 var seg = cmd.Segment;
289 for (seg.sections.items) |*sect, j| {251 for (seg.sections.items) |*sect, j| {
290 const index = @intCast(u16, j);252 const index = @intCast(u16, j);
291 const segname = parseName(&sect.segname);253 const segname = segmentName(sect.*);
292 const sectname = parseName(&sect.sectname);254 const sectname = sectionName(sect.*);
293 if (mem.eql(u8, segname, "__DWARF")) {255 if (mem.eql(u8, segname, "__DWARF")) {
294 if (mem.eql(u8, sectname, "__debug_info")) {256 if (mem.eql(u8, sectname, "__debug_info")) {
295 self.dwarf_debug_info_index = index;257 self.dwarf_debug_info_index = index;
...@@ -351,7 +313,7 @@ pub fn parseSections(self: *Object) !void {...@@ -351,7 +313,7 @@ pub fn parseSections(self: *Object) !void {
351 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);313 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);
352314
353 for (seg.sections.items) |sect| {315 for (seg.sections.items) |sect| {
354 log.debug("parsing section '{s},{s}'", .{ parseName(&sect.segname), parseName(&sect.sectname) });316 log.debug("parsing section '{s},{s}'", .{ segmentName(sect), sectionName(sect) });
355 // Read sections' code317 // Read sections' code
356 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));318 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
357 _ = try self.file.?.preadAll(code, sect.offset);319 _ = try self.file.?.preadAll(code, sect.offset);
...@@ -381,47 +343,91 @@ pub fn parseSections(self: *Object) !void {...@@ -381,47 +343,91 @@ pub fn parseSections(self: *Object) !void {
381 }343 }
382}344}
383345
384fn cmpNlist(_: void, lhs: macho.nlist_64, rhs: macho.nlist_64) bool {346pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
385 return lhs.n_value < rhs.n_value;347 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
386}
387348
388fn filterSymsInSection(symbols: []macho.nlist_64, sect_id: u8) []macho.nlist_64 {349 log.warn("analysing {s}", .{self.name.?});
389 var start: usize = 0;
390 var end: usize = symbols.len;
391350
392 while (true) {351 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
393 var change = false;352
394 if (symbols[start].n_sect != sect_id) {353 const SymWithIndex = struct {
395 start += 1;354 nlist: macho.nlist_64,
396 change = true;355 index: u32,
356
357 pub fn cmp(_: void, lhs: @This(), rhs: @This()) bool {
358 return lhs.nlist.n_value < rhs.nlist.n_value;
397 }359 }
398 if (symbols[end - 1].n_sect != sect_id) {360
399 end -= 1;361 fn filterSymsInSection(symbols: []@This(), sect_id: u8) []@This() {
400 change = true;362 var start: usize = 0;
363 var end: usize = symbols.len;
364
365 while (true) {
366 var change = false;
367 if (symbols[start].nlist.n_sect != sect_id) {
368 start += 1;
369 change = true;
370 }
371 if (symbols[end - 1].nlist.n_sect != sect_id) {
372 end -= 1;
373 change = true;
374 }
375
376 if (start == end) break;
377 if (!change) break;
378 }
379
380 return symbols[start..end];
401 }381 }
402382
403 if (start == end) break;383 fn filterRelocs(relocs: []macho.relocation_info, start: u64, end: u64) []macho.relocation_info {
404 if (!change) break;384 if (relocs.len == 0) return relocs;
405 }
406385
407 return symbols[start..end];386 var start_id: usize = 0;
408}387 var end_id: usize = relocs.len;
409388
410pub fn parseDummy(self: *Object) !void {389 while (true) {
411 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;390 var change = false;
391 if (relocs[start_id].r_address > end) {
392 start_id += 1;
393 change = true;
394 }
395 if (relocs[end_id - 1].r_address < start) {
396 end_id -= 1;
397 change = true;
398 }
412399
413 log.warn("analysing {s}", .{self.name.?});400 if (start_id == end_id) break;
401 if (!change) break;
402 }
414403
415 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;404 return relocs[start_id..end_id];
405 }
406 };
407
408 const nlists = self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym];
416409
417 var sorted_syms = std.ArrayList(macho.nlist_64).init(self.allocator);410 var sorted_syms = std.ArrayList(SymWithIndex).init(self.allocator);
418 defer sorted_syms.deinit();411 defer sorted_syms.deinit();
419 try sorted_syms.appendSlice(self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym]);412 try sorted_syms.ensureTotalCapacity(nlists.len);
420413
421 std.sort.sort(macho.nlist_64, sorted_syms.items, {}, cmpNlist);414 for (nlists) |nlist, index| {
415 sorted_syms.appendAssumeCapacity(.{
416 .nlist = nlist,
417 .index = @intCast(u32, index + dysymtab.ilocalsym),
418 });
419 }
420
421 std.sort.sort(SymWithIndex, sorted_syms.items, {}, SymWithIndex.cmp);
422422
423 for (seg.sections.items) |sect, sect_id| {423 for (seg.sections.items) |sect, sect_id| {
424 log.warn("section {s},{s}", .{ parseName(&sect.segname), parseName(&sect.sectname) });424 log.warn("section {s},{s}", .{ segmentName(sect), sectionName(sect) });
425
426 const match = (try zld.getMatchingSection(sect)) orelse {
427 log.warn("unhandled section", .{});
428 continue;
429 };
430
425 // Read code431 // Read code
426 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));432 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
427 defer self.allocator.free(code);433 defer self.allocator.free(code);
...@@ -431,16 +437,25 @@ pub fn parseDummy(self: *Object) !void {...@@ -431,16 +437,25 @@ pub fn parseDummy(self: *Object) !void {
431 const raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);437 const raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
432 defer self.allocator.free(raw_relocs);438 defer self.allocator.free(raw_relocs);
433 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);439 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
440 const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
434441
435 const relocs = try reloc.parse(442 const alignment = sect.@"align";
436 self.allocator,
437 self.arch.?,
438 code,
439 mem.bytesAsSlice(macho.relocation_info, raw_relocs),
440 );
441443
442 if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) {444 if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) {
443 const syms = filterSymsInSection(sorted_syms.items, @intCast(u8, sect_id + 1));445 const syms = SymWithIndex.filterSymsInSection(sorted_syms.items, @intCast(u8, sect_id + 1));
446
447 if (syms.len == 0) {
448 // One large text block referenced by section offsets only
449 log.warn("TextBlock", .{});
450 log.warn(" | referenced by section offsets", .{});
451 log.warn(" | start_addr = {}", .{sect.addr});
452 log.warn(" | end_addr = {}", .{sect.size});
453 log.warn(" | size = {}", .{sect.size});
454 log.warn(" | alignment = 0x{x}", .{alignment});
455 log.warn(" | segment_id = {}", .{match.seg});
456 log.warn(" | section_id = {}", .{match.sect});
457 log.warn(" | relocs: {any}", .{relocs});
458 }
444459
445 var indices = std.ArrayList(u32).init(self.allocator);460 var indices = std.ArrayList(u32).init(self.allocator);
446 defer indices.deinit();461 defer indices.deinit();
...@@ -450,32 +465,35 @@ pub fn parseDummy(self: *Object) !void {...@@ -450,32 +465,35 @@ pub fn parseDummy(self: *Object) !void {
450 const curr = syms[i];465 const curr = syms[i];
451 try indices.append(i);466 try indices.append(i);
452467
453 const next: ?macho.nlist_64 = if (i + 1 < syms.len)468 const next: ?SymWithIndex = if (i + 1 < syms.len)
454 syms[i + 1]469 syms[i + 1]
455 else470 else
456 null;471 null;
457472
458 if (next) |n| {473 if (next) |n| {
459 if (curr.n_value == n.n_value) {474 if (curr.nlist.n_value == n.nlist.n_value) {
460 continue;475 continue;
461 }476 }
462 }477 }
463478
464 const start_addr = curr.n_value - sect.addr;479 const start_addr = curr.nlist.n_value - sect.addr;
465 const end_addr = if (next) |n| n.n_value - sect.addr else sect.size;480 const end_addr = if (next) |n| n.nlist.n_value - sect.addr else sect.size;
466 const alignment = sect.@"align";
467481
468 const tb_code = code[start_addr..end_addr];482 const tb_code = code[start_addr..end_addr];
469 const size = tb_code.len;483 const size = tb_code.len;
470484
471 log.warn("TextBlock", .{});485 log.warn("TextBlock", .{});
472 for (indices.items) |id| {486 for (indices.items) |id| {
473 log.warn(" | symbol {s}", .{self.getString(syms[id].n_strx)});487 const sym = self.symbols.items[syms[id].index];
488 log.warn(" | symbol = {s}", .{sym.name});
474 }489 }
475 log.warn(" | start_addr = 0x{x}", .{start_addr});490 log.warn(" | start_addr = {}", .{start_addr});
476 log.warn(" | end_addr = 0x{x}", .{end_addr});491 log.warn(" | end_addr = {}", .{end_addr});
477 log.warn(" | size = {}", .{size});492 log.warn(" | size = {}", .{size});
478 log.warn(" | alignment = 0x{x}", .{alignment});493 log.warn(" | alignment = 0x{x}", .{alignment});
494 log.warn(" | segment_id = {}", .{match.seg});
495 log.warn(" | section_id = {}", .{match.sect});
496 log.warn(" | relocs: {any}", .{SymWithIndex.filterRelocs(relocs, start_addr, end_addr)});
479497
480 indices.clearRetainingCapacity();498 indices.clearRetainingCapacity();
481 }499 }
src/link/MachO/Zld.zig+44-41
...@@ -234,6 +234,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -234,6 +234,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
234 try self.parseInputFiles(files, args.syslibroot);234 try self.parseInputFiles(files, args.syslibroot);
235 try self.parseLibs(args.libs, args.syslibroot);235 try self.parseLibs(args.libs, args.syslibroot);
236 try self.resolveSymbols();236 try self.resolveSymbols();
237 try self.parseTextBlocks();
237 try self.resolveStubsAndGotEntries();238 try self.resolveStubsAndGotEntries();
238 try self.updateMetadata();239 try self.updateMetadata();
239 try self.sortSections();240 try self.sortSections();
...@@ -322,10 +323,10 @@ fn mapAndUpdateSections(...@@ -322,10 +323,10 @@ fn mapAndUpdateSections(
322323
323 log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{324 log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
324 object.name.?,325 object.name.?,
325 parseName(&source_sect.inner.segname),326 segmentName(source_sect.inner),
326 parseName(&source_sect.inner.sectname),327 sectionName(source_sect.inner),
327 parseName(&target_sect.segname),328 segmentName(target_sect.*),
328 parseName(&target_sect.sectname),329 sectionName(target_sect.*),
329 offset,330 offset,
330 offset + size,331 offset + size,
331 });332 });
...@@ -343,12 +344,12 @@ fn updateMetadata(self: *Zld) !void {...@@ -343,12 +344,12 @@ fn updateMetadata(self: *Zld) !void {
343 for (self.objects.items) |object| {344 for (self.objects.items) |object| {
344 // Find ideal section alignment and update section mappings345 // Find ideal section alignment and update section mappings
345 for (object.sections.items) |sect, sect_id| {346 for (object.sections.items) |sect, sect_id| {
346 const match = (try self.getMatchingSection(sect)) orelse {347 const match = (try self.getMatchingSection(sect.inner)) orelse {
347 log.debug("{s}: unhandled section type 0x{x} for '{s},{s}'", .{348 log.debug("{s}: unhandled section type 0x{x} for '{s},{s}'", .{
348 object.name.?,349 object.name.?,
349 sect.flags(),350 sect.inner.flags,
350 sect.segname(),351 segmentName(sect.inner),
351 sect.sectname(),352 sectionName(sect.inner),
352 });353 });
353 continue;354 continue;
354 };355 };
...@@ -441,15 +442,15 @@ const MatchingSection = struct {...@@ -441,15 +442,15 @@ const MatchingSection = struct {
441 sect: u16,442 sect: u16,
442};443};
443444
444fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {445pub fn getMatchingSection(self: *Zld, sect: macho.section_64) !?MatchingSection {
445 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;446 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
446 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;447 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
447 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;448 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
448 const segname = sect.segname();449 const segname = segmentName(sect);
449 const sectname = sect.sectname();450 const sectname = sectionName(sect);
450451
451 const res: ?MatchingSection = blk: {452 const res: ?MatchingSection = blk: {
452 switch (sect.sectionType()) {453 switch (sectionType(sect)) {
453 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {454 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
454 if (self.text_const_section_index == null) {455 if (self.text_const_section_index == null) {
455 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);456 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
...@@ -649,7 +650,7 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {...@@ -649,7 +650,7 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {
649 };650 };
650 },651 },
651 macho.S_REGULAR => {652 macho.S_REGULAR => {
652 if (sect.isCode()) {653 if (sectionIsCode(sect)) {
653 if (self.text_section_index == null) {654 if (self.text_section_index == null) {
654 self.text_section_index = @intCast(u16, text_seg.sections.items.len);655 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
655 try text_seg.addSection(self.allocator, "__text", .{656 try text_seg.addSection(self.allocator, "__text", .{
...@@ -662,11 +663,11 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {...@@ -662,11 +663,11 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {
662 .sect = self.text_section_index.?,663 .sect = self.text_section_index.?,
663 };664 };
664 }665 }
665 if (sect.isDebug()) {666 if (sectionIsDebug(sect)) {
666 // TODO debug attributes667 // TODO debug attributes
667 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {668 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
668 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{669 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
669 sect.flags(), segname, sectname,670 sect.flags, segname, sectname,
670 });671 });
671 }672 }
672 break :blk null;673 break :blk null;
...@@ -829,7 +830,7 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {...@@ -829,7 +830,7 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {
829830
830 if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {831 if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {
831 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{832 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
832 sect.flags(), segname, sectname,833 sect.flags, segname, sectname,
833 });834 });
834 }835 }
835836
...@@ -956,8 +957,8 @@ fn sortSections(self: *Zld) !void {...@@ -956,8 +957,8 @@ fn sortSections(self: *Zld) !void {
956957
957 log.debug("remapping in {s}: '{s},{s}': {} => {}", .{958 log.debug("remapping in {s}: '{s},{s}': {} => {}", .{
958 object.name.?,959 object.name.?,
959 parseName(&sect.inner.segname),960 segmentName(sect.inner),
960 parseName(&sect.inner.sectname),961 sectionName(sect.inner),
961 target_map.section_id,962 target_map.section_id,
962 new_index,963 new_index,
963 });964 });
...@@ -1086,8 +1087,8 @@ fn allocateSymbol(self: *Zld, symbol: *Symbol) !void {...@@ -1086,8 +1087,8 @@ fn allocateSymbol(self: *Zld, symbol: *Symbol) !void {
1086 const source_sect = &object.sections.items[reg.section];1087 const source_sect = &object.sections.items[reg.section];
1087 const target_map = source_sect.target_map orelse {1088 const target_map = source_sect.target_map orelse {
1088 log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{1089 log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{
1089 parseName(&source_sect.inner.segname),1090 segmentName(source_sect.inner),
1090 parseName(&source_sect.inner.sectname),1091 sectionName(source_sect.inner),
1091 symbol.name,1092 symbol.name,
1092 });1093 });
1093 return;1094 return;
...@@ -1464,7 +1465,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {...@@ -1464,7 +1465,7 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
1464fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {1465fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
1465 log.debug("resolving symbols in '{s}'", .{object.name});1466 log.debug("resolving symbols in '{s}'", .{object.name});
14661467
1467 for (object.symtab.items) |sym| {1468 for (object.symtab.items) |sym, sym_id| {
1468 const sym_name = object.getString(sym.n_strx);1469 const sym_name = object.getString(sym.n_strx);
14691470
1470 if (Symbol.isStab(sym)) {1471 if (Symbol.isStab(sym)) {
...@@ -1497,6 +1498,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {...@@ -1497,6 +1498,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
1497 .file = object,1498 .file = object,
1498 },1499 },
1499 };1500 };
1501 const index = @intCast(u32, self.locals.items.len);
1500 try self.locals.append(self.allocator, symbol);1502 try self.locals.append(self.allocator, symbol);
1501 try object.symbols.append(self.allocator, symbol);1503 try object.symbols.append(self.allocator, symbol);
1502 continue;1504 continue;
...@@ -1665,6 +1667,12 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1665,6 +1667,12 @@ fn resolveSymbols(self: *Zld) !void {
1665 if (has_undefined) return error.UndefinedSymbolReference;1667 if (has_undefined) return error.UndefinedSymbolReference;
1666}1668}
16671669
1670fn parseTextBlocks(self: *Zld) !void {
1671 for (self.objects.items) |object| {
1672 try object.parseTextBlocks(self);
1673 }
1674}
1675
1668fn resolveStubsAndGotEntries(self: *Zld) !void {1676fn resolveStubsAndGotEntries(self: *Zld) !void {
1669 for (self.objects.items) |object| {1677 for (self.objects.items) |object| {
1670 log.debug("resolving stubs and got entries from {s}", .{object.name});1678 log.debug("resolving stubs and got entries from {s}", .{object.name});
...@@ -1718,11 +1726,11 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1718,11 +1726,11 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1718 log.debug("relocating object {s}", .{object.name});1726 log.debug("relocating object {s}", .{object.name});
17191727
1720 for (object.sections.items) |sect| {1728 for (object.sections.items) |sect| {
1721 if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or1729 if (sectionType(sect.inner) == macho.S_MOD_INIT_FUNC_POINTERS or
1722 sect.inner.flags == macho.S_MOD_TERM_FUNC_POINTERS) continue;1730 sectionType(sect.inner) == macho.S_MOD_TERM_FUNC_POINTERS) continue;
17231731
1724 const segname = parseName(&sect.inner.segname);1732 const segname = segmentName(sect.inner);
1725 const sectname = parseName(&sect.inner.sectname);1733 const sectname = sectionName(sect.inner);
17261734
1727 log.debug("relocating section '{s},{s}'", .{ segname, sectname });1735 log.debug("relocating section '{s},{s}'", .{ segname, sectname });
17281736
...@@ -1759,7 +1767,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1759,7 +1767,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1759 args.source_target_sect_addr = source_sect.inner.addr;1767 args.source_target_sect_addr = source_sect.inner.addr;
1760 }1768 }
17611769
1762 const flags = @truncate(u8, target_sect.flags & 0xff);1770 const sect_type = sectionType(target_sect);
1763 const should_rebase = rebase: {1771 const should_rebase = rebase: {
1764 if (!unsigned.is_64bit) break :rebase false;1772 if (!unsigned.is_64bit) break :rebase false;
17651773
...@@ -1780,8 +1788,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1780,8 +1788,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1780 };1788 };
17811789
1782 if (!is_right_segment) break :rebase false;1790 if (!is_right_segment) break :rebase false;
1783 if (flags != macho.S_LITERAL_POINTERS and1791 if (sect_type != macho.S_LITERAL_POINTERS and
1784 flags != macho.S_REGULAR)1792 sect_type != macho.S_REGULAR)
1785 {1793 {
1786 break :rebase false;1794 break :rebase false;
1787 }1795 }
...@@ -1804,7 +1812,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1804,7 +1812,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
18041812
1805 // TLV is handled via a separate offset mechanism.1813 // TLV is handled via a separate offset mechanism.
1806 // Calculate the offset to the initializer.1814 // Calculate the offset to the initializer.
1807 if (flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {1815 if (sect_type == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
1808 // TODO we don't want to save offset to tlv_bootstrap1816 // TODO we don't want to save offset to tlv_bootstrap
1809 if (mem.eql(u8, object.symbols.items[rel.target.symbol].name, "__tlv_bootstrap")) break :tlv;1817 if (mem.eql(u8, object.symbols.items[rel.target.symbol].name, "__tlv_bootstrap")) break :tlv;
18101818
...@@ -1858,13 +1866,13 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1858,13 +1866,13 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1858 target_sect_off + sect.code.len,1866 target_sect_off + sect.code.len,
1859 });1867 });
18601868
1861 if (target_sect.flags == macho.S_ZEROFILL or1869 if (sectionType(target_sect) == macho.S_ZEROFILL or
1862 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or1870 sectionType(target_sect) == macho.S_THREAD_LOCAL_ZEROFILL or
1863 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)1871 sectionType(target_sect) == macho.S_THREAD_LOCAL_VARIABLES)
1864 {1872 {
1865 log.debug("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{1873 log.debug("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{
1866 parseName(&target_sect.segname),1874 segmentName(target_sect),
1867 parseName(&target_sect.sectname),1875 sectionName(target_sect),
1868 target_sect_off,1876 target_sect_off,
1869 target_sect_off + sect.code.len,1877 target_sect_off + sect.code.len,
1870 });1878 });
...@@ -1926,8 +1934,8 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T...@@ -1926,8 +1934,8 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T
1926 log.debug(" | section offset", .{});1934 log.debug(" | section offset", .{});
1927 const source_sect = object.sections.items[sect_id];1935 const source_sect = object.sections.items[sect_id];
1928 log.debug(" | section '{s},{s}'", .{1936 log.debug(" | section '{s},{s}'", .{
1929 parseName(&source_sect.inner.segname),1937 segmentName(source_sect.inner),
1930 parseName(&source_sect.inner.sectname),1938 sectionName(source_sect.inner),
1931 });1939 });
1932 const target_map = source_sect.target_map orelse unreachable;1940 const target_map = source_sect.target_map orelse unreachable;
1933 const target_seg = self.load_commands.items[target_map.segment_id].Segment;1941 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
...@@ -2999,8 +3007,3 @@ fn writeHeader(self: *Zld) !void {...@@ -2999,8 +3007,3 @@ fn writeHeader(self: *Zld) !void {
29993007
3000 try self.file.?.pwriteAll(mem.asBytes(&header), 0);3008 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
3001}3009}
3002
3003pub fn parseName(name: *const [16]u8) []const u8 {
3004 const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
3005 return name[0..len];
3006}
src/link/MachO/commands.zig+38
...@@ -425,6 +425,44 @@ fn makeStaticString(bytes: []const u8) [16]u8 {...@@ -425,6 +425,44 @@ fn makeStaticString(bytes: []const u8) [16]u8 {
425 return buf;425 return buf;
426}426}
427427
428fn parseName(name: *const [16]u8) []const u8 {
429 const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
430 return name[0..len];
431}
432
433pub fn segmentName(sect: macho.section_64) []const u8 {
434 return parseName(&sect.segname);
435}
436
437pub fn sectionName(sect: macho.section_64) []const u8 {
438 return parseName(&sect.sectname);
439}
440
441pub fn sectionType(sect: macho.section_64) u8 {
442 return @truncate(u8, sect.flags & 0xff);
443}
444
445pub fn sectionAttrs(sect: macho.section_64) u32 {
446 return sect.flags & 0xffffff00;
447}
448
449pub fn sectionIsCode(sect: macho.section_64) bool {
450 const attr = sectionAttrs(sect);
451 return attr & macho.S_ATTR_PURE_INSTRUCTIONS != 0 or attr & macho.S_ATTR_SOME_INSTRUCTIONS != 0;
452}
453
454pub fn sectionIsDebug(sect: macho.section_64) bool {
455 return sectionAttrs(sect) & macho.S_ATTR_DEBUG != 0;
456}
457
458pub fn sectionIsDontDeadStrip(sect: macho.section_64) bool {
459 return sectionAttrs(sect) & macho.S_ATTR_NO_DEAD_STRIP != 0;
460}
461
462pub fn sectionIsDontDeadStripIfReferencesLive(sect: macho.section_64) bool {
463 return sectionAttrs(sect) & macho.S_ATTR_LIVE_SUPPORT != 0;
464}
465
428fn testRead(allocator: *Allocator, buffer: []const u8, expected: anytype) !void {466fn testRead(allocator: *Allocator, buffer: []const u8, expected: anytype) !void {
429 var stream = io.fixedBufferStream(buffer);467 var stream = io.fixedBufferStream(buffer);
430 var given = try LoadCommand.read(allocator, stream.reader());468 var given = try LoadCommand.read(allocator, stream.reader());