authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-03 20:30:18+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log453c16d8acead9bc5ef19155474ba8af37d151cf
treee1998a2e93b8a28c6ad2f538482794f6565ef048
parent669ac92af0626b77442415e54be3f604c5b49535

zld: draft out splitting sections into blocks


2 files changed, 117 insertions(+), 13 deletions(-)

src/link/MachO/Object.zig+106
......@@ -15,6 +15,7 @@ const Allocator = mem.Allocator;
1515const Arch = std.Target.Cpu.Arch;
1616const Relocation = reloc.Relocation;
1717const Symbol = @import("Symbol.zig");
18const TextBlock = @import("Zld.zig").TextBlock;
1819
1920usingnamespace @import("commands.zig");
2021
......@@ -271,6 +272,7 @@ pub fn parse(self: *Object) !void {
271272 try self.parseSymtab();
272273 try self.parseDataInCode();
273274 try self.parseInitializers();
275 try self.parseDummy();
274276}
275277
276278pub fn readLoadCommands(self: *Object, reader: anytype) !void {
......@@ -379,6 +381,110 @@ pub fn parseSections(self: *Object) !void {
379381 }
380382}
381383
384fn cmpNlist(_: void, lhs: macho.nlist_64, rhs: macho.nlist_64) bool {
385 return lhs.n_value < rhs.n_value;
386}
387
388fn filterSymsInSection(symbols: []macho.nlist_64, sect_id: u8) []macho.nlist_64 {
389 var start: usize = 0;
390 var end: usize = symbols.len;
391
392 while (true) {
393 var change = false;
394 if (symbols[start].n_sect != sect_id) {
395 start += 1;
396 change = true;
397 }
398 if (symbols[end - 1].n_sect != sect_id) {
399 end -= 1;
400 change = true;
401 }
402
403 if (start == end) break;
404 if (!change) break;
405 }
406
407 return symbols[start..end];
408}
409
410pub fn parseDummy(self: *Object) !void {
411 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
412
413 log.warn("analysing {s}", .{self.name.?});
414
415 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
416
417 var sorted_syms = std.ArrayList(macho.nlist_64).init(self.allocator);
418 defer sorted_syms.deinit();
419 try sorted_syms.appendSlice(self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym]);
420
421 std.sort.sort(macho.nlist_64, sorted_syms.items, {}, cmpNlist);
422
423 for (seg.sections.items) |sect, sect_id| {
424 log.warn("section {s},{s}", .{ parseName(&sect.segname), parseName(&sect.sectname) });
425 // Read code
426 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
427 defer self.allocator.free(code);
428 _ = try self.file.?.preadAll(code, sect.offset);
429
430 // Read and parse relocs
431 const raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
432 defer self.allocator.free(raw_relocs);
433 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
434
435 const relocs = try reloc.parse(
436 self.allocator,
437 self.arch.?,
438 code,
439 mem.bytesAsSlice(macho.relocation_info, raw_relocs),
440 );
441
442 if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) {
443 const syms = filterSymsInSection(sorted_syms.items, @intCast(u8, sect_id + 1));
444
445 var indices = std.ArrayList(u32).init(self.allocator);
446 defer indices.deinit();
447
448 var i: u32 = 0;
449 while (i < syms.len) : (i += 1) {
450 const curr = syms[i];
451 try indices.append(i);
452
453 const next: ?macho.nlist_64 = if (i + 1 < syms.len)
454 syms[i + 1]
455 else
456 null;
457
458 if (next) |n| {
459 if (curr.n_value == n.n_value) {
460 continue;
461 }
462 }
463
464 const start_addr = curr.n_value - sect.addr;
465 const end_addr = if (next) |n| n.n_value - sect.addr else sect.size;
466 const alignment = sect.@"align";
467
468 const tb_code = code[start_addr..end_addr];
469 const size = tb_code.len;
470
471 log.warn("TextBlock", .{});
472 for (indices.items) |id| {
473 log.warn(" | symbol {s}", .{self.getString(syms[id].n_strx)});
474 }
475 log.warn(" | start_addr = 0x{x}", .{start_addr});
476 log.warn(" | end_addr = 0x{x}", .{end_addr});
477 log.warn(" | size = {}", .{size});
478 log.warn(" | alignment = 0x{x}", .{alignment});
479
480 indices.clearRetainingCapacity();
481 }
482 } else {
483 return error.TODOOneLargeTextBlock;
484 }
485 }
486}
487
382488pub fn parseInitializers(self: *Object) !void {
383489 const index = self.mod_init_func_section_index orelse return;
384490 const section = self.sections.items[index];
src/link/MachO/Zld.zig+11-13
......@@ -17,6 +17,7 @@ const Archive = @import("Archive.zig");
1717const CodeSignature = @import("CodeSignature.zig");
1818const Dylib = @import("Dylib.zig");
1919const Object = @import("Object.zig");
20const Relocation = reloc.Relocation;
2021const StringTable = @import("StringTable.zig");
2122const Symbol = @import("Symbol.zig");
2223const Trie = @import("Trie.zig");
......@@ -133,6 +134,16 @@ const TlvOffset = struct {
133134 }
134135};
135136
137pub const TextBlock = struct {
138 local_sym_index: ?u32 = null,
139 size: u64,
140 alignment: u32,
141 code: []u8,
142 relocs: []*Relocation,
143 segment_id: u16,
144 section_id: u16,
145};
146
136147/// Default path to dyld
137148const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld";
138149
......@@ -236,19 +247,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
236247 try self.allocateSymbols();
237248 try self.allocateTentativeSymbols();
238249 try self.allocateProxyBindAddresses();
239
240 // log.warn("globals", .{});
241 // for (self.globals.values()) |value| {
242 // log.warn(" | {s}: {}", .{ value.name, value.payload });
243 // }
244
245 // for (self.objects.items) |object| {
246 // log.warn("object {s}", .{object.name.?});
247 // for (object.symbols.items) |sym| {
248 // log.warn(" | {s}: {}", .{ sym.name, sym.payload });
249 // }
250 // }
251
252250 try self.flush();
253251}
254252