authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-05 16:31:20+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log7b4063d55899b0e35711c848f7b19de6f928282b
tree0e941076bd3d8f9f155f66f4b808682b973fb7ce
parent5649242025cd885a6a2f0607d96f54b1926b0a5a

zld: convert section in linked list of TextBlocks


3 files changed, 266 insertions(+), 247 deletions(-)

src/link/MachO/Object.zig+182-212
......@@ -28,7 +28,6 @@ name: ?[]const u8 = null,
2828mtime: ?u64 = null,
2929
3030load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
31sections: std.ArrayListUnmanaged(Section) = .{},
3231
3332segment_cmd_index: ?u16 = null,
3433symtab_cmd_index: ?u16 = null,
......@@ -49,32 +48,10 @@ dwarf_debug_ranges_index: ?u16 = null,
4948symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
5049strtab: std.ArrayListUnmanaged(u8) = .{},
5150
52symbols: std.ArrayListUnmanaged(*Symbol) = .{},
53stabs: std.ArrayListUnmanaged(*Symbol) = .{},
5451initializers: std.ArrayListUnmanaged(u32) = .{},
5552data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
5653
57pub const Section = struct {
58 inner: macho.section_64,
59 code: []u8,
60 relocs: ?[]*Relocation,
61 target_map: ?struct {
62 segment_id: u16,
63 section_id: u16,
64 offset: u32,
65 } = null,
66
67 pub fn deinit(self: *Section, allocator: *Allocator) void {
68 allocator.free(self.code);
69
70 if (self.relocs) |relocs| {
71 for (relocs) |rel| {
72 allocator.destroy(rel);
73 }
74 allocator.free(relocs);
75 }
76 }
77};
54symbols: std.ArrayListUnmanaged(*Symbol) = .{},
7855
7956const DebugInfo = struct {
8057 inner: dwarf.DwarfInfo,
......@@ -177,19 +154,11 @@ pub fn deinit(self: *Object) void {
177154 lc.deinit(self.allocator);
178155 }
179156 self.load_commands.deinit(self.allocator);
180
181 for (self.sections.items) |*sect| {
182 sect.deinit(self.allocator);
183 }
184 self.sections.deinit(self.allocator);
185
186 self.symbols.deinit(self.allocator);
187 self.stabs.deinit(self.allocator);
188
189157 self.data_in_code_entries.deinit(self.allocator);
190158 self.initializers.deinit(self.allocator);
191159 self.symtab.deinit(self.allocator);
192160 self.strtab.deinit(self.allocator);
161 self.symbols.deinit(self.allocator);
193162
194163 if (self.name) |n| {
195164 self.allocator.free(n);
......@@ -231,10 +200,8 @@ pub fn parse(self: *Object) !void {
231200 self.header = header;
232201
233202 try self.readLoadCommands(reader);
234 try self.parseSections();
235203 try self.parseSymtab();
236204 try self.parseDataInCode();
237 try self.parseInitializers();
238205}
239206
240207pub fn readLoadCommands(self: *Object, reader: anytype) !void {
......@@ -305,250 +272,253 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
305272 }
306273}
307274
308pub fn parseSections(self: *Object) !void {
309 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
310
311 log.debug("parsing sections in {s}", .{self.name.?});
312
313 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);
275const NlistWithIndex = struct {
276 nlist: macho.nlist_64,
277 index: u32,
314278
315 for (seg.sections.items) |sect| {
316 log.debug("parsing section '{s},{s}'", .{ segmentName(sect), sectionName(sect) });
317 // Read sections' code
318 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
319 _ = try self.file.?.preadAll(code, sect.offset);
320
321 var section = Section{
322 .inner = sect,
323 .code = code,
324 .relocs = null,
325 };
279 pub fn cmp(_: void, lhs: @This(), rhs: @This()) bool {
280 return lhs.nlist.n_value < rhs.nlist.n_value;
281 }
326282
327 // Parse relocations
328 if (sect.nreloc > 0) {
329 var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
330 defer self.allocator.free(raw_relocs);
283 fn filterNlistsInSection(symbols: []@This(), sect_id: u8) []@This() {
284 var start: usize = 0;
285 var end: usize = symbols.len;
331286
332 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
287 while (true) {
288 var change = false;
289 if (symbols[start].nlist.n_sect != sect_id) {
290 start += 1;
291 change = true;
292 }
293 if (symbols[end - 1].nlist.n_sect != sect_id) {
294 end -= 1;
295 change = true;
296 }
333297
334 section.relocs = try reloc.parse(
335 self.allocator,
336 self.arch.?,
337 section.code,
338 mem.bytesAsSlice(macho.relocation_info, raw_relocs),
339 );
298 if (start == end) break;
299 if (!change) break;
340300 }
341301
342 self.sections.appendAssumeCapacity(section);
302 return symbols[start..end];
343303 }
344}
345
346pub fn parseTextBlocks(self: *Object, zld: *Zld) !*TextBlock {
347 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
304};
348305
349 log.warn("analysing {s}", .{self.name.?});
306fn filterRelocs(relocs: []macho.relocation_info, start: u64, end: u64) []macho.relocation_info {
307 if (relocs.len == 0) return relocs;
350308
351 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
309 var start_id: usize = 0;
310 var end_id: usize = relocs.len;
352311
353 const SymWithIndex = struct {
354 nlist: macho.nlist_64,
355 index: u32,
356
357 pub fn cmp(_: void, lhs: @This(), rhs: @This()) bool {
358 return lhs.nlist.n_value < rhs.nlist.n_value;
312 while (true) {
313 var change = false;
314 if (relocs[start_id].r_address > end) {
315 start_id += 1;
316 change = true;
359317 }
360
361 fn filterSymsInSection(symbols: []@This(), sect_id: u8) []@This() {
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];
318 if (relocs[end_id - 1].r_address < start) {
319 end_id -= 1;
320 change = true;
381321 }
382322
383 fn filterRelocs(relocs: []macho.relocation_info, start: u64, end: u64) []macho.relocation_info {
384 if (relocs.len == 0) return relocs;
323 if (start_id == end_id) break;
324 if (!change) break;
325 }
385326
386 var start_id: usize = 0;
387 var end_id: usize = relocs.len;
327 return relocs[start_id..end_id];
328}
388329
389 while (true) {
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 }
330const SeniorityContext = struct {
331 zld: *Zld,
332};
333fn cmpSymBySeniority(context: SeniorityContext, lhs: u32, rhs: u32) bool {
334 const lreg = context.zld.locals.items[lhs].payload.regular;
335 const rreg = context.zld.locals.items[rhs].payload.regular;
336
337 return switch (rreg.linkage) {
338 .global => true,
339 .linkage_unit => lreg.linkage == .translation_unit,
340 else => false,
341 };
342}
399343
400 if (start_id == end_id) break;
401 if (!change) break;
402 }
344pub fn parseTextBlocks(self: *Object, zld: *Zld) !?*TextBlock {
345 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
403346
404 return relocs[start_id..end_id];
405 }
406 };
347 log.warn("analysing {s}", .{self.name.?});
407348
349 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
350 // We only care about defined symbols, so filter every other out.
408351 const nlists = self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym];
409352
410 var sorted_syms = std.ArrayList(SymWithIndex).init(self.allocator);
411 defer sorted_syms.deinit();
412 try sorted_syms.ensureTotalCapacity(nlists.len);
353 var sorted_nlists = std.ArrayList(NlistWithIndex).init(self.allocator);
354 defer sorted_nlists.deinit();
355 try sorted_nlists.ensureTotalCapacity(nlists.len);
413356
414357 for (nlists) |nlist, index| {
415 sorted_syms.appendAssumeCapacity(.{
358 sorted_nlists.appendAssumeCapacity(.{
416359 .nlist = nlist,
417360 .index = @intCast(u32, index + dysymtab.ilocalsym),
418361 });
419362 }
420363
421 std.sort.sort(SymWithIndex, sorted_syms.items, {}, SymWithIndex.cmp);
364 std.sort.sort(NlistWithIndex, sorted_nlists.items, {}, NlistWithIndex.cmp);
365
366 var last_block: ?*TextBlock = null;
422367
423368 for (seg.sections.items) |sect, sect_id| {
424 log.warn("section {s},{s}", .{ segmentName(sect), sectionName(sect) });
369 log.warn("putting section '{s},{s}' as a TextBlock", .{
370 segmentName(sect),
371 sectionName(sect),
372 });
425373
374 // Get matching segment/section in the final artifact.
426375 const match = (try zld.getMatchingSection(sect)) orelse {
427376 log.warn("unhandled section", .{});
428377 continue;
429378 };
430379
431 // Read code
380 // Read section's code
432381 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
433382 defer self.allocator.free(code);
434383 _ = try self.file.?.preadAll(code, sect.offset);
435384
436 // Read and parse relocs
437 const raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
438 defer self.allocator.free(raw_relocs);
439 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
440 const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
385 // Is there any padding between symbols within the section?
386 const is_padded = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;
441387
388 // Section alignment will be the assumed alignment per symbol.
442389 const alignment = sect.@"align";
443390
444 if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) {
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 }
391 next: {
392 if (is_padded) blocks: {
393 const filtered_nlists = NlistWithIndex.filterNlistsInSection(
394 sorted_nlists.items,
395 @intCast(u8, sect_id + 1),
396 );
397
398 if (filtered_nlists.len == 0) break :blocks;
459399
460 var indices = std.ArrayList(u32).init(self.allocator);
461 defer indices.deinit();
400 var nlist_indices = std.ArrayList(u32).init(self.allocator);
401 defer nlist_indices.deinit();
462402
463 var i: u32 = 0;
464 while (i < syms.len) : (i += 1) {
465 const curr = syms[i];
466 try indices.append(i);
403 var i: u32 = 0;
404 while (i < filtered_nlists.len) : (i += 1) {
405 const curr = filtered_nlists[i];
406 try nlist_indices.append(curr.index);
467407
468 const next: ?SymWithIndex = if (i + 1 < syms.len)
469 syms[i + 1]
470 else
471 null;
408 const next: ?NlistWithIndex = if (i + 1 < filtered_nlists.len)
409 filtered_nlists[i + 1]
410 else
411 null;
472412
473 if (next) |n| {
474 if (curr.nlist.n_value == n.nlist.n_value) {
475 continue;
413 if (next) |n| {
414 if (curr.nlist.n_value == n.nlist.n_value) {
415 continue;
416 }
476417 }
477 }
478418
479 const start_addr = curr.nlist.n_value - sect.addr;
480 const end_addr = if (next) |n| n.nlist.n_value - sect.addr else sect.size;
419 // Bubble-up senior symbol as the main link to the text block.
420 for (nlist_indices.items) |*index| {
421 const sym = self.symbols.items[index.*];
422 if (sym.payload != .regular) {
423 log.err("expected a regular symbol, found {s}", .{sym.payload});
424 log.err(" when remapping {s}", .{sym.name});
425 return error.SymbolIsNotRegular;
426 }
427 assert(sym.payload.regular.local_sym_index != 0); // This means the symbol has not been properly resolved.
428 index.* = sym.payload.regular.local_sym_index;
429 }
481430
482 const tb_code = code[start_addr..end_addr];
483 const size = tb_code.len;
431 std.sort.sort(u32, nlist_indices.items, SeniorityContext{ .zld = zld }, cmpSymBySeniority);
484432
485 log.warn("TextBlock", .{});
486 for (indices.items) |id| {
487 const sym = self.symbols.items[syms[id].index];
488 log.warn(" | symbol = {s}", .{sym.name});
489 }
490 log.warn(" | start_addr = {}", .{start_addr});
491 log.warn(" | end_addr = {}", .{end_addr});
492 log.warn(" | size = {}", .{size});
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)});
497
498 indices.clearRetainingCapacity();
499 }
500 } else {
501 return error.TODOOneLargeTextBlock;
502 }
503 }
504}
433 const local_sym_index = nlist_indices.pop();
434 const sym = zld.locals.items[local_sym_index];
435 if (sym.payload.regular.file) |file| {
436 if (file != self) {
437 log.warn("deduping definition of {s} in {s}", .{ sym.name, self.name.? });
438 continue;
439 }
440 }
505441
506const SectionAsTextBlocksArgs = struct {
507 sect: macho.section_64,
508 code: []u8,
509 subsections_via_symbols: bool = false,
510 relocs: ?[]macho.relocation_info = null,
511 segment_id: u16 = 0,
512 section_id: u16 = 0,
513};
442 const start_addr = curr.nlist.n_value - sect.addr;
443 const end_addr = if (next) |n| n.nlist.n_value - sect.addr else sect.size;
444
445 const tb_code = code[start_addr..end_addr];
446 const size = tb_code.len;
447
448 const block = try self.allocator.create(TextBlock);
449 errdefer self.allocator.destroy(block);
450
451 block.* = .{
452 .local_sym_index = local_sym_index,
453 .aliases = std.ArrayList(u32).init(self.allocator),
454 .references = std.ArrayList(u32).init(self.allocator),
455 .code = tb_code,
456 .relocs = std.ArrayList(*Relocation).init(self.allocator),
457 .size = size,
458 .alignment = alignment,
459 .segment_id = match.seg,
460 .section_id = match.sect,
461 };
462 try block.aliases.appendSlice(nlist_indices.items);
463
464 // TODO parse relocs
465
466 if (last_block) |last| {
467 last.next = block;
468 block.prev = last;
469 }
470 last_block = block;
514471
515fn sectionAsTextBlocks(self: *Object, args: SectionAsTextBlocksArgs) !*TextBlock {
516 const sect = args.sect;
472 nlist_indices.clearRetainingCapacity();
473 }
517474
518 log.warn("putting section '{s},{s}' as a TextBlock", .{ segmentName(sect), sectionName(sect) });
475 break :next;
476 }
519477
520 // Section alignment will be the assumed alignment per symbol.
521 const alignment = sect.@"align";
478 // Since there is no symbol to refer to this block, we create
479 // a temp one.
480 const name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{
481 self.name.?,
482 segmentName(sect),
483 sectionName(sect),
484 });
485 defer self.allocator.free(name);
486 const symbol = try Symbol.new(self.allocator, name);
487 symbol.payload = .{
488 .regular = .{
489 .linkage = .translation_unit,
490 .file = self,
491 },
492 };
493 const local_sym_index = @intCast(u32, zld.locals.items.len);
494 try zld.locals.append(zld.allocator, symbol);
522495
523 const first_block: *TextBlock = blk: {
524 if (args.subsections_via_symbols) {
525 return error.TODO;
526 } else {
527496 const block = try self.allocator.create(TextBlock);
528497 errdefer self.allocator.destroy(block);
529498
530499 block.* = .{
531 .ref = .{
532 .section = undefined, // Will be populated when we allocated final sections.
533 },
534 .code = args.code,
535 .relocs = null,
500 .local_sym_index = local_sym_index,
501 .aliases = std.ArrayList(u32).init(self.allocator),
502 .references = std.ArrayList(u32).init(self.allocator),
503 .code = code,
504 .relocs = std.ArrayList(*Relocation).init(self.allocator),
536505 .size = sect.size,
537506 .alignment = alignment,
538 .segment_id = args.segment_id,
539 .section_id = args.section_id,
507 .segment_id = match.seg,
508 .section_id = match.sect,
540509 };
541510
542511 // TODO parse relocs
543 if (args.relocs) |relocs| {
544 block.relocs = try reloc.parse(self.allocator, self.arch.?, args.code, relocs, symbols);
545 }
546512
547 break :blk block;
513 if (last_block) |last| {
514 last.next = block;
515 block.prev = last;
516 }
517 last_block = block;
548518 }
549 };
519 }
550520
551 return first_block;
521 return last_block;
552522}
553523
554524pub fn parseInitializers(self: *Object) !void {
src/link/MachO/Symbol.zig+8-3
......@@ -40,10 +40,13 @@ pub const Regular = struct {
4040 linkage: Linkage,
4141
4242 /// Symbol address.
43 address: u64,
43 address: u64 = 0,
4444
45 /// Section ID where the symbol resides.
46 section: u8,
45 /// Segment ID
46 segment_id: u16 = 0,
47
48 /// Section ID
49 section: u16 = 0,
4750
4851 /// Whether the symbol is a weak ref.
4952 weak_ref: bool = false,
......@@ -52,6 +55,8 @@ pub const Regular = struct {
5255 /// null means self-reference.
5356 file: ?*Object = null,
5457
58 local_sym_index: u32 = 0,
59
5560 pub const Linkage = enum {
5661 translation_unit,
5762 linkage_unit,
src/link/MachO/Zld.zig+76-32
......@@ -104,6 +104,7 @@ objc_classrefs_section_index: ?u16 = null,
104104objc_data_section_index: ?u16 = null,
105105
106106locals: std.ArrayListUnmanaged(*Symbol) = .{},
107imports: std.ArrayListUnmanaged(*Symbol) = .{},
107108globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
108109
109110/// Offset into __DATA,__common section.
......@@ -118,6 +119,8 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
118119
119120stub_helper_stubs_start_off: ?u64 = null,
120121
122last_text_block: ?*TextBlock = null,
123
121124pub const Output = struct {
122125 tag: enum { exe, dylib },
123126 path: []const u8,
......@@ -135,12 +138,11 @@ const TlvOffset = struct {
135138};
136139
137140pub const TextBlock = struct {
138 allocator: *Allocator,
139141 local_sym_index: u32,
140142 aliases: std.ArrayList(u32),
141143 references: std.ArrayList(u32),
142144 code: []u8,
143 relocs: ?std.ArrayList(*Relocation) = null,
145 relocs: std.ArrayList(*Relocation),
144146 size: u64,
145147 alignment: u32,
146148 segment_id: u16,
......@@ -151,14 +153,33 @@ pub const TextBlock = struct {
151153 pub fn deinit(block: *TextBlock, allocator: *Allocator) void {
152154 block.aliases.deinit();
153155 block.references.deinit();
154 if (block.relocs) |relocs| {
155 for (relocs.items) |reloc| {
156 allocator.destroy(reloc);
157 }
158 relocs.deinit();
156 for (block.relocs.items) |reloc| {
157 allocator.destroy(reloc);
159158 }
159 block.relocs.deinit();
160160 allocator.free(code);
161161 }
162
163 fn print(self: *const TextBlock, zld: *Zld) void {
164 if (self.prev) |prev| {
165 prev.print(zld);
166 }
167
168 log.warn("TextBlock", .{});
169 log.warn(" | {}: '{s}'", .{ self.local_sym_index, zld.locals.items[self.local_sym_index].name });
170 log.warn(" | Aliases:", .{});
171 for (self.aliases.items) |index| {
172 log.warn(" | {}: '{s}'", .{ index, zld.locals.items[index].name });
173 }
174 log.warn(" | References:", .{});
175 for (self.references.items) |index| {
176 log.warn(" | {}: '{s}'", .{ index, zld.locals.items[index].name });
177 }
178 log.warn(" | size = {}", .{self.size});
179 log.warn(" | align = {}", .{self.alignment});
180 log.warn(" | segment_id = {}", .{self.segment_id});
181 log.warn(" | section_id = {}", .{self.section_id});
182 }
162183};
163184
164185/// Default path to dyld
......@@ -200,11 +221,13 @@ pub fn deinit(self: *Zld) void {
200221 }
201222 self.dylibs.deinit(self.allocator);
202223
203 for (self.globals.values()) |sym| {
224 self.globals.deinit(self.allocator);
225
226 for (self.imports.items) |sym| {
204227 sym.deinit(self.allocator);
205228 self.allocator.destroy(sym);
206229 }
207 self.globals.deinit(self.allocator);
230 self.imports.deinit(self.allocator);
208231
209232 for (self.locals.items) |sym| {
210233 sym.deinit(self.allocator);
......@@ -252,20 +275,21 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
252275 try self.parseLibs(args.libs, args.syslibroot);
253276 try self.resolveSymbols();
254277 try self.parseTextBlocks();
255 try self.resolveStubsAndGotEntries();
256 try self.updateMetadata();
257 try self.sortSections();
258 try self.addRpaths(args.rpaths);
259 try self.addDataInCodeLC();
260 try self.addCodeSignatureLC();
261 try self.allocateTextSegment();
262 try self.allocateDataConstSegment();
263 try self.allocateDataSegment();
264 self.allocateLinkeditSegment();
265 try self.allocateSymbols();
266 try self.allocateTentativeSymbols();
267 try self.allocateProxyBindAddresses();
268 try self.flush();
278 return error.TODO;
279 // try self.resolveStubsAndGotEntries();
280 // try self.updateMetadata();
281 // try self.sortSections();
282 // try self.addRpaths(args.rpaths);
283 // try self.addDataInCodeLC();
284 // try self.addCodeSignatureLC();
285 // try self.allocateTextSegment();
286 // try self.allocateDataConstSegment();
287 // try self.allocateDataSegment();
288 // self.allocateLinkeditSegment();
289 // try self.allocateSymbols();
290 // try self.allocateTentativeSymbols();
291 // try self.allocateProxyBindAddresses();
292 // try self.flush();
269293}
270294
271295fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {
......@@ -1509,13 +1533,11 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
15091533 symbol.payload = .{
15101534 .regular = .{
15111535 .linkage = .translation_unit,
1512 .address = sym.n_value,
1513 .section = sym.n_sect - 1,
15141536 .weak_ref = Symbol.isWeakRef(sym),
15151537 .file = object,
1538 .local_sym_index = @intCast(u32, self.locals.items.len),
15161539 },
15171540 };
1518 const index = @intCast(u32, self.locals.items.len);
15191541 try self.locals.append(self.allocator, symbol);
15201542 try object.symbols.append(self.allocator, symbol);
15211543 continue;
......@@ -1550,8 +1572,6 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
15501572 symbol.payload = .{
15511573 .regular = .{
15521574 .linkage = linkage,
1553 .address = sym.n_value,
1554 .section = sym.n_sect - 1,
15551575 .weak_ref = Symbol.isWeakRef(sym),
15561576 .file = object,
15571577 },
......@@ -1581,6 +1601,11 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
15811601}
15821602
15831603fn resolveSymbols(self: *Zld) !void {
1604 // TODO mimicking insertion of null symbol from incremental linker.
1605 // This will need to moved.
1606 const null_sym = try Symbol.new(self.allocator, "");
1607 try self.locals.append(self.allocator, null_sym);
1608
15841609 // First pass, resolve symbols in provided objects.
15851610 for (self.objects.items) |object| {
15861611 try self.resolveSymbolsInObject(object);
......@@ -1609,11 +1634,18 @@ fn resolveSymbols(self: *Zld) !void {
16091634 }
16101635 }
16111636
1637 // Put any globally defined regular symbol as local.
16121638 // Mark if we need to allocate zerofill section for tentative definitions
16131639 for (self.globals.values()) |symbol| {
1614 if (symbol.payload == .tentative) {
1615 self.has_tentative_defs = true;
1616 break;
1640 switch (symbol.payload) {
1641 .regular => |*reg| {
1642 reg.local_sym_index = @intCast(u32, self.locals.items.len);
1643 try self.locals.append(self.allocator, symbol);
1644 },
1645 .tentative => {
1646 self.has_tentative_defs = true;
1647 },
1648 else => {},
16171649 }
16181650 }
16191651
......@@ -1639,6 +1671,7 @@ fn resolveSymbols(self: *Zld) !void {
16391671 .file = dylib,
16401672 },
16411673 };
1674 try self.imports.append(self.allocator, symbol);
16421675 continue :loop;
16431676 }
16441677 }
......@@ -1667,6 +1700,7 @@ fn resolveSymbols(self: *Zld) !void {
16671700 symbol.payload = .{
16681701 .proxy = .{},
16691702 };
1703 try self.imports.append(self.allocator, symbol);
16701704 }
16711705 }
16721706
......@@ -1686,7 +1720,17 @@ fn resolveSymbols(self: *Zld) !void {
16861720
16871721fn parseTextBlocks(self: *Zld) !void {
16881722 for (self.objects.items) |object| {
1689 _ = try object.parseTextBlocks(self);
1723 if (try object.parseTextBlocks(self)) |block| {
1724 if (self.last_text_block) |last| {
1725 last.next = block;
1726 block.prev = last;
1727 }
1728 self.last_text_block = block;
1729 }
1730 }
1731
1732 if (self.last_text_block) |block| {
1733 block.print(self);
16901734 }
16911735}
16921736