zld: draft out splitting sections into blocks

This commit is contained in:
Jakub Konka 2021-07-03 20:30:18 +02:00
parent 669ac92af0
commit 453c16d8ac
2 changed files with 117 additions and 13 deletions

View File

@ -15,6 +15,7 @@ const Allocator = mem.Allocator;
const Arch = std.Target.Cpu.Arch;
const Relocation = reloc.Relocation;
const Symbol = @import("Symbol.zig");
const TextBlock = @import("Zld.zig").TextBlock;
usingnamespace @import("commands.zig");
@ -271,6 +272,7 @@ pub fn parse(self: *Object) !void {
try self.parseSymtab();
try self.parseDataInCode();
try self.parseInitializers();
try self.parseDummy();
}
pub fn readLoadCommands(self: *Object, reader: anytype) !void {
@ -379,6 +381,110 @@ pub fn parseSections(self: *Object) !void {
}
}
fn cmpNlist(_: void, lhs: macho.nlist_64, rhs: macho.nlist_64) bool {
return lhs.n_value < rhs.n_value;
}
fn filterSymsInSection(symbols: []macho.nlist_64, sect_id: u8) []macho.nlist_64 {
var start: usize = 0;
var end: usize = symbols.len;
while (true) {
var change = false;
if (symbols[start].n_sect != sect_id) {
start += 1;
change = true;
}
if (symbols[end - 1].n_sect != sect_id) {
end -= 1;
change = true;
}
if (start == end) break;
if (!change) break;
}
return symbols[start..end];
}
pub fn parseDummy(self: *Object) !void {
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
log.warn("analysing {s}", .{self.name.?});
const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
var sorted_syms = std.ArrayList(macho.nlist_64).init(self.allocator);
defer sorted_syms.deinit();
try sorted_syms.appendSlice(self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym]);
std.sort.sort(macho.nlist_64, sorted_syms.items, {}, cmpNlist);
for (seg.sections.items) |sect, sect_id| {
log.warn("section {s},{s}", .{ parseName(&sect.segname), parseName(&sect.sectname) });
// Read code
var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
defer self.allocator.free(code);
_ = try self.file.?.preadAll(code, sect.offset);
// Read and parse relocs
const raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
defer self.allocator.free(raw_relocs);
_ = try self.file.?.preadAll(raw_relocs, sect.reloff);
const relocs = try reloc.parse(
self.allocator,
self.arch.?,
code,
mem.bytesAsSlice(macho.relocation_info, raw_relocs),
);
if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) {
const syms = filterSymsInSection(sorted_syms.items, @intCast(u8, sect_id + 1));
var indices = std.ArrayList(u32).init(self.allocator);
defer indices.deinit();
var i: u32 = 0;
while (i < syms.len) : (i += 1) {
const curr = syms[i];
try indices.append(i);
const next: ?macho.nlist_64 = if (i + 1 < syms.len)
syms[i + 1]
else
null;
if (next) |n| {
if (curr.n_value == n.n_value) {
continue;
}
}
const start_addr = curr.n_value - sect.addr;
const end_addr = if (next) |n| n.n_value - sect.addr else sect.size;
const alignment = sect.@"align";
const tb_code = code[start_addr..end_addr];
const size = tb_code.len;
log.warn("TextBlock", .{});
for (indices.items) |id| {
log.warn(" | symbol {s}", .{self.getString(syms[id].n_strx)});
}
log.warn(" | start_addr = 0x{x}", .{start_addr});
log.warn(" | end_addr = 0x{x}", .{end_addr});
log.warn(" | size = {}", .{size});
log.warn(" | alignment = 0x{x}", .{alignment});
indices.clearRetainingCapacity();
}
} else {
return error.TODOOneLargeTextBlock;
}
}
}
pub fn parseInitializers(self: *Object) !void {
const index = self.mod_init_func_section_index orelse return;
const section = self.sections.items[index];

View File

@ -17,6 +17,7 @@ const Archive = @import("Archive.zig");
const CodeSignature = @import("CodeSignature.zig");
const Dylib = @import("Dylib.zig");
const Object = @import("Object.zig");
const Relocation = reloc.Relocation;
const StringTable = @import("StringTable.zig");
const Symbol = @import("Symbol.zig");
const Trie = @import("Trie.zig");
@ -133,6 +134,16 @@ const TlvOffset = struct {
}
};
pub const TextBlock = struct {
local_sym_index: ?u32 = null,
size: u64,
alignment: u32,
code: []u8,
relocs: []*Relocation,
segment_id: u16,
section_id: u16,
};
/// Default path to dyld
const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld";
@ -236,19 +247,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
try self.allocateSymbols();
try self.allocateTentativeSymbols();
try self.allocateProxyBindAddresses();
// log.warn("globals", .{});
// for (self.globals.values()) |value| {
// log.warn(" | {s}: {}", .{ value.name, value.payload });
// }
// for (self.objects.items) |object| {
// log.warn("object {s}", .{object.name.?});
// for (object.symbols.items) |sym| {
// log.warn(" | {s}: {}", .{ sym.name, sym.payload });
// }
// }
try self.flush();
}