aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-06-14 12:56:53 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-06-14 12:56:53 +0200
commit66a93ebfbf3724775ce56f91d74578c896fbfec5 (patch)
tree727560cd23c4eb37af0c383acd27ea0bd52bcc30
parent86ebd4b975d2f1e01f468e06daab6e28c06f9719 (diff)
downloadzig-66a93ebfbf3724775ce56f91d74578c896fbfec5.tar.gz
zig-66a93ebfbf3724775ce56f91d74578c896fbfec5.zip
zld: clean up parsing section by type and attrs
-rw-r--r--src/link/MachO/Object.zig37
-rw-r--r--src/link/MachO/Zld.zig329
2 files changed, 244 insertions, 122 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 4501d63fff..c4a044b446 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -70,6 +70,43 @@ pub const Section = struct {
allocator.free(relocs);
}
}
+
+ pub fn segname(self: Section) []const u8 {
+ return parseName(&self.inner.segname);
+ }
+
+ pub fn sectname(self: Section) []const u8 {
+ return parseName(&self.inner.sectname);
+ }
+
+ pub fn flags(self: Section) u32 {
+ return self.inner.flags;
+ }
+
+ pub fn sectionType(self: Section) u8 {
+ return @truncate(u8, self.flags() & 0xff);
+ }
+
+ pub fn sectionAttrs(self: Section) u32 {
+ return self.flags() & 0xffffff00;
+ }
+
+ pub fn isCode(self: Section) bool {
+ const attr = self.sectionAttrs();
+ return attr & macho.S_ATTR_PURE_INSTRUCTIONS != 0 and attr & macho.S_ATTR_SOME_INSTRUCTIONS != 0;
+ }
+
+ pub fn isDebug(self: Section) bool {
+ return self.sectionAttrs() & macho.S_ATTR_DEBUG != 0;
+ }
+
+ pub fn dontDeadStrip(self: Section) bool {
+ return self.sectionAttrs() & macho.S_ATTR_NO_DEAD_STRIP != 0;
+ }
+
+ pub fn dontDeadStripIfReferencesLive(self: Section) bool {
+ return self.sectionAttrs() & macho.S_ATTR_LIVE_SUPPORT != 0;
+ }
};
const DebugInfo = struct {
diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig
index 824ea1bb56..70f219bafd 100644
--- a/src/link/MachO/Zld.zig
+++ b/src/link/MachO/Zld.zig
@@ -409,7 +409,7 @@ fn mapAndUpdateSections(
const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment);
- log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
+ log.warn("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
object.name.?,
parseName(&source_sect.inner.segname),
parseName(&source_sect.inner.sectname),
@@ -435,19 +435,17 @@ fn updateMetadata(self: *Zld) !void {
const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
// Create missing metadata
- for (object_seg.sections.items) |source_sect, sect_id| {
- if (sect_id == object.text_section_index.?) continue;
- const segname = parseName(&source_sect.segname);
- const sectname = parseName(&source_sect.sectname);
- const flags = source_sect.flags;
+ for (object.sections.items) |sect, sect_id| {
+ const segname = sect.segname();
+ const sectname = sect.sectname();
- switch (flags) {
- macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => {
- if (self.text_section_index != null) continue;
+ switch (sect.sectionType()) {
+ macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
+ if (self.text_const_section_index != null) continue;
- self.text_section_index = @intCast(u16, text_seg.sections.items.len);
+ self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
try text_seg.addSection(self.allocator, .{
- .sectname = makeStaticString("__text"),
+ .sectname = makeStaticString("__const"),
.segname = makeStaticString("__TEXT"),
.addr = 0,
.size = 0,
@@ -455,70 +453,12 @@ fn updateMetadata(self: *Zld) !void {
.@"align" = 0,
.reloff = 0,
.nreloc = 0,
- .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
+ .flags = macho.S_REGULAR,
.reserved1 = 0,
.reserved2 = 0,
.reserved3 = 0,
});
- },
- macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
- if (mem.eql(u8, segname, "__TEXT")) {
- if (mem.eql(u8, sectname, "__ustring")) {
- if (self.ustring_section_index != null) continue;
-
- self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.allocator, .{
- .sectname = makeStaticString("__ustring"),
- .segname = makeStaticString("__TEXT"),
- .addr = 0,
- .size = 0,
- .offset = 0,
- .@"align" = 0,
- .reloff = 0,
- .nreloc = 0,
- .flags = macho.S_REGULAR,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- });
- } else {
- if (self.text_const_section_index != null) continue;
-
- self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.allocator, .{
- .sectname = makeStaticString("__const"),
- .segname = makeStaticString("__TEXT"),
- .addr = 0,
- .size = 0,
- .offset = 0,
- .@"align" = 0,
- .reloff = 0,
- .nreloc = 0,
- .flags = macho.S_REGULAR,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- });
- }
- } else if (mem.eql(u8, segname, "__DATA") or mem.eql(u8, segname, "__DATA_CONST")) {
- if (self.data_const_section_index != null) continue;
-
- self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
- try data_const_seg.addSection(self.allocator, .{
- .sectname = makeStaticString("__const"),
- .segname = makeStaticString("__DATA_CONST"),
- .addr = 0,
- .size = 0,
- .offset = 0,
- .@"align" = 0,
- .reloff = 0,
- .nreloc = 0,
- .flags = macho.S_REGULAR,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- });
- }
+ continue;
},
macho.S_CSTRING_LITERALS => {
if (self.cstring_section_index != null) continue;
@@ -538,6 +478,7 @@ fn updateMetadata(self: *Zld) !void {
.reserved2 = 0,
.reserved3 = 0,
});
+ continue;
},
macho.S_MOD_INIT_FUNC_POINTERS => {
if (self.mod_init_func_section_index != null) continue;
@@ -557,6 +498,7 @@ fn updateMetadata(self: *Zld) !void {
.reserved2 = 0,
.reserved3 = 0,
});
+ continue;
},
macho.S_MOD_TERM_FUNC_POINTERS => {
if (self.mod_term_func_section_index != null) continue;
@@ -576,6 +518,7 @@ fn updateMetadata(self: *Zld) !void {
.reserved2 = 0,
.reserved3 = 0,
});
+ continue;
},
macho.S_ZEROFILL => {
if (mem.eql(u8, sectname, "__common")) {
@@ -615,6 +558,7 @@ fn updateMetadata(self: *Zld) !void {
.reserved3 = 0,
});
}
+ continue;
},
macho.S_THREAD_LOCAL_VARIABLES => {
if (self.tlv_section_index != null) continue;
@@ -634,6 +578,7 @@ fn updateMetadata(self: *Zld) !void {
.reserved2 = 0,
.reserved3 = 0,
});
+ continue;
},
macho.S_THREAD_LOCAL_REGULAR => {
if (self.tlv_data_section_index != null) continue;
@@ -653,6 +598,7 @@ fn updateMetadata(self: *Zld) !void {
.reserved2 = 0,
.reserved3 = 0,
});
+ continue;
},
macho.S_THREAD_LOCAL_ZEROFILL => {
if (self.tlv_bss_section_index != null) continue;
@@ -672,58 +618,185 @@ fn updateMetadata(self: *Zld) !void {
.reserved2 = 0,
.reserved3 = 0,
});
- },
- macho.S_COALESCED |
- macho.S_ATTR_NO_TOC |
- macho.S_ATTR_STRIP_STATIC_SYMS |
- macho.S_ATTR_LIVE_SUPPORT => {
- log.debug("TODO __eh_frame section: type 0x{x}, name '{s},{s}'", .{
- flags, segname, sectname,
- });
continue;
},
- macho.S_REGULAR | macho.S_ATTR_DEBUG => {
- if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
- log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
- flags, segname, sectname,
+ macho.S_COALESCED => {
+ if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
+ log.debug("TODO __eh_frame section: type 0x{x}, name '{s},{s}'", .{
+ sect.flags(), segname, sectname,
});
+ continue;
}
- continue;
},
- else => {
+ macho.S_REGULAR => {
+ if (sect.isCode()) {
+ if (self.text_section_index != null) continue;
+
+ self.text_section_index = @intCast(u16, text_seg.sections.items.len);
+ try text_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__text"),
+ .segname = makeStaticString("__TEXT"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ continue;
+ }
+ if (sect.isDebug()) {
+ if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
+ log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
+ sect.flags(), segname, sectname,
+ });
+ }
+ continue;
+ }
+
+ if (mem.eql(u8, segname, "__TEXT")) {
+ if (mem.eql(u8, sectname, "__ustring")) {
+ if (self.ustring_section_index != null) continue;
+
+ self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
+ try text_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__ustring"),
+ .segname = makeStaticString("__TEXT"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ } else {
+ if (self.text_const_section_index != null) continue;
+
+ self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
+ try text_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__const"),
+ .segname = makeStaticString("__TEXT"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ }
+ continue;
+ }
+
+ if (mem.eql(u8, segname, "__DATA_CONST")) {
+ if (self.data_const_section_index != null) continue;
+
+ self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
+ try data_const_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__const"),
+ .segname = makeStaticString("__DATA_CONST"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ continue;
+ }
+
+ if (mem.eql(u8, segname, "__DATA")) {
+ if (mem.eql(u8, sectname, "__const")) {
+ if (self.data_const_section_index != null) continue;
+
+ self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
+ try data_const_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__const"),
+ .segname = makeStaticString("__DATA_CONST"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ } else {
+ if (self.data_section_index != null) continue;
+
+ self.data_section_index = @intCast(u16, data_seg.sections.items.len);
+ try data_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__data"),
+ .segname = makeStaticString("__DATA"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ }
+
+ continue;
+ }
+
if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {
- log.debug("TODO LLVM bitcode section: type 0x{x}, name '{s},{s}'", .{
- flags, segname, sectname,
+ log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
+ sect.flags(), segname, sectname,
});
continue;
}
- log.err("unhandled section type 0x{x} for '{s},{s}'", .{ flags, segname, sectname });
- return error.UnhandledSection;
},
+ else => {},
}
+
+ log.err("{s}: unhandled section type 0x{x} for '{s},{s}'", .{
+ object.name.?,
+ sect.flags(),
+ segname,
+ sectname,
+ });
+ return error.UnhandledSection;
}
// Find ideal section alignment.
- for (object_seg.sections.items) |source_sect| {
- if (self.getMatchingSection(source_sect)) |res| {
+ for (object.sections.items) |sect| {
+ if (self.getMatchingSection(sect)) |res| {
const target_seg = &self.load_commands.items[res.seg].Segment;
const target_sect = &target_seg.sections.items[res.sect];
- target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
+ target_sect.@"align" = math.max(target_sect.@"align", sect.inner.@"align");
}
}
// Update section mappings
- for (object_seg.sections.items) |source_sect, sect_id| {
- const source_sect_id = @intCast(u16, sect_id);
- if (self.getMatchingSection(source_sect)) |res| {
- try self.mapAndUpdateSections(object, source_sect_id, res.seg, res.sect);
+ for (object.sections.items) |sect, sect_id| {
+ if (self.getMatchingSection(sect)) |res| {
+ try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);
continue;
}
-
- log.debug("section '{s},{s}' will be unmapped", .{
- parseName(&source_sect.segname),
- parseName(&source_sect.sectname),
- });
+ log.warn("section '{s},{s}' will be unmapped", .{ sect.segname(), sect.sectname() });
}
}
@@ -819,13 +892,13 @@ const MatchingSection = struct {
sect: u16,
};
-fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
- const segname = parseName(&section.segname);
- const sectname = parseName(&section.sectname);
+fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
+ const segname = sect.segname();
+ const sectname = sect.sectname();
const res: ?MatchingSection = blk: {
- switch (section.flags) {
- macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
+ switch (sect.sectionType()) {
+ macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
break :blk .{
.seg = self.text_segment_cmd_index.?,
.sect = self.text_const_section_index.?,
@@ -855,11 +928,12 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
.seg = self.data_segment_cmd_index.?,
.sect = self.common_section_index.?,
};
+ } else {
+ break :blk .{
+ .seg = self.data_segment_cmd_index.?,
+ .sect = self.bss_section_index.?,
+ };
}
- break :blk .{
- .seg = self.data_segment_cmd_index.?,
- .sect = self.bss_section_index.?,
- };
},
macho.S_THREAD_LOCAL_VARIABLES => {
break :blk .{
@@ -879,31 +953,43 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
.sect = self.tlv_bss_section_index.?,
};
},
- macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => {
- break :blk .{
- .seg = self.text_segment_cmd_index.?,
- .sect = self.text_section_index.?,
- };
+ macho.S_COALESCED => {
+ // TODO coalesced sections
+ break :blk null;
},
macho.S_REGULAR => {
+ if (sect.isCode()) {
+ break :blk .{
+ .seg = self.text_segment_cmd_index.?,
+ .sect = self.text_section_index.?,
+ };
+ }
+ if (sect.isDebug()) {
+ // TODO debug attributes
+ break :blk null;
+ }
+
if (mem.eql(u8, segname, "__TEXT")) {
if (mem.eql(u8, sectname, "__ustring")) {
break :blk .{
.seg = self.text_segment_cmd_index.?,
.sect = self.ustring_section_index.?,
};
+ } else {
+ break :blk .{
+ .seg = self.text_segment_cmd_index.?,
+ .sect = self.text_const_section_index.?,
+ };
}
- break :blk .{
- .seg = self.text_segment_cmd_index.?,
- .sect = self.text_const_section_index.?,
- };
}
+
if (mem.eql(u8, segname, "__DATA_CONST")) {
break :blk .{
.seg = self.data_const_segment_cmd_index.?,
.sect = self.data_const_section_index.?,
};
}
+
if (mem.eql(u8, segname, "__DATA")) {
if (mem.eql(u8, sectname, "__const")) {
break :blk .{
@@ -916,11 +1002,10 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
.sect = self.data_section_index.?,
};
}
+
break :blk null;
},
- else => {
- break :blk null;
- },
+ else => break :blk null,
}
};