aboutsummaryrefslogtreecommitdiff
path: root/src/link/MachO/Object.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-07-31 15:01:37 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-08-01 09:06:56 +0200
commit06396ddd7d632704681bbd6278f18dcc2b6bf20c (patch)
tree068f069096fe341c19a63e0de66e52c19e22ad5b /src/link/MachO/Object.zig
parente73777333dd66570ddacdb7de56a390de01b33c5 (diff)
downloadzig-06396ddd7d632704681bbd6278f18dcc2b6bf20c.tar.gz
zig-06396ddd7d632704681bbd6278f18dcc2b6bf20c.zip
macho: don't allocate Objects on the heap
instead, ownership is transferred to MachO. This makes Object management align closer with data-oriented design.
Diffstat (limited to 'src/link/MachO/Object.zig')
-rw-r--r--src/link/MachO/Object.zig60
1 files changed, 26 insertions, 34 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 1250f015ed..6a1bf8fd57 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -127,36 +127,6 @@ const DebugInfo = struct {
}
};
-pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?*Object {
- const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
- error.FileNotFound => return null,
- else => |e| return e,
- };
- errdefer file.close();
-
- const object = try allocator.create(Object);
- errdefer allocator.destroy(object);
-
- const name = try allocator.dupe(u8, path);
- errdefer allocator.free(name);
-
- object.* = .{
- .name = name,
- .file = file,
- };
-
- object.parse(allocator, arch) catch |err| switch (err) {
- error.EndOfStream, error.NotObject => {
- object.deinit(allocator);
- allocator.destroy(object);
- return null;
- },
- else => |e| return e,
- };
-
- return object;
-}
-
pub fn deinit(self: *Object, allocator: *Allocator) void {
for (self.load_commands.items) |*lc| {
lc.deinit(allocator);
@@ -184,6 +154,22 @@ pub fn deinit(self: *Object, allocator: *Allocator) void {
}
}
+pub fn isObject(file: fs.File) !bool {
+ const reader = file.reader();
+ const is_object = blk: {
+ if (reader.readStruct(macho.mach_header_64)) |header| {
+ break :blk header.filetype == macho.MH_OBJECT;
+ } else |err| {
+ switch (err) {
+ error.EndOfStream => break :blk false,
+ else => |e| return e,
+ }
+ }
+ };
+ try file.seekTo(0);
+ return is_object;
+}
+
pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
var reader = self.file.reader();
if (self.file_offset) |offset| {
@@ -481,7 +467,12 @@ const TextBlockParser = struct {
}
};
-pub fn parseTextBlocks(self: *Object, allocator: *Allocator, macho_file: *MachO) !void {
+pub fn parseTextBlocks(
+ self: *Object,
+ allocator: *Allocator,
+ object_id: u16,
+ macho_file: *MachO,
+) !void {
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
log.debug("analysing {s}", .{self.name});
@@ -668,13 +659,14 @@ pub fn parseTextBlocks(self: *Object, allocator: *Allocator, macho_file: *MachO)
if (is_ext) {
if (macho_file.symbol_resolver.get(sym.n_strx)) |resolv| {
assert(resolv.where == .global);
- const global_object = macho_file.objects.items[resolv.file];
- if (global_object != self) {
+ if (resolv.file != object_id) {
log.debug("deduping definition of {s} in {s}", .{
macho_file.getString(sym.n_strx),
self.name,
});
- log.debug(" already defined in {s}", .{global_object.name});
+ log.debug(" already defined in {s}", .{
+ macho_file.objects.items[resolv.file].name,
+ });
continue;
}
}