authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-24 02:09:30-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-24 02:09:30-04:00
log058937e44df7fe07c09ee9291170a74f58ec1562
tree60b3e7722c6d0d71a44a32e91735e18f0eaa7d3f
parent229e99ca37441c758155fca113aecc3c4529c3ea

bug fixes to make it work


2 files changed, 151 insertions(+), 93 deletions(-)

src-self-hosted/codegen.zig+1-1
...@@ -378,8 +378,8 @@ const Function = struct {...@@ -378,8 +378,8 @@ const Function = struct {
378 return self.fail(src, "TODO handle a larger string constant", .{});378 return self.fail(src, "TODO handle a larger string constant", .{});
379379
380 // Emit the string literal directly into the code; jump over it.380 // Emit the string literal directly into the code; jump over it.
381 const offset = self.code.items.len;
382 try self.genRelativeFwdJump(src, smaller_len);381 try self.genRelativeFwdJump(src, smaller_len);
382 const offset = self.code.items.len;
383 try self.code.appendSlice(bytes);383 try self.code.appendSlice(bytes);
384 return MCValue{ .embedded_in_code = offset };384 return MCValue{ .embedded_in_code = offset };
385 },385 },
src-self-hosted/link.zig+150-92
...@@ -174,7 +174,7 @@ const Update = struct {...@@ -174,7 +174,7 @@ const Update = struct {
174 if (program_header.p_offset <= start) continue;174 if (program_header.p_offset <= start) continue;
175 if (program_header.p_offset < min_pos) min_pos = program_header.p_offset;175 if (program_header.p_offset < min_pos) min_pos = program_header.p_offset;
176 }176 }
177 return min_pos;177 return min_pos - start;
178 }178 }
179179
180 fn findFreeSpace(self: *Update, object_size: u64, min_alignment: u16) u64 {180 fn findFreeSpace(self: *Update, object_size: u64, min_alignment: u16) u64 {
...@@ -233,7 +233,7 @@ const Update = struct {...@@ -233,7 +233,7 @@ const Update = struct {
233 // There must always be a null section in index 0233 // There must always be a null section in index 0
234 try self.sections.append(.{234 try self.sections.append(.{
235 .sh_name = 0,235 .sh_name = 0,
236 .sh_type = 0,236 .sh_type = elf.SHT_NULL,
237 .sh_flags = 0,237 .sh_flags = 0,
238 .sh_addr = 0,238 .sh_addr = 0,
239 .sh_offset = 0,239 .sh_offset = 0,
...@@ -247,6 +247,8 @@ const Update = struct {...@@ -247,6 +247,8 @@ const Update = struct {
247 }247 }
248 if (self.shstrtab_index == null) {248 if (self.shstrtab_index == null) {
249 self.shstrtab_index = @intCast(u16, self.sections.items.len);249 self.shstrtab_index = @intCast(u16, self.sections.items.len);
250 assert(self.shstrtab.items.len == 0);
251 try self.shstrtab.append(0); // need a 0 at position 0
250 const off = self.findFreeSpace(self.shstrtab.items.len, 1);252 const off = self.findFreeSpace(self.shstrtab.items.len, 1);
251 //std.debug.warn("found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });253 //std.debug.warn("found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });
252 try self.sections.append(.{254 try self.sections.append(.{
...@@ -299,7 +301,6 @@ const Update = struct {...@@ -299,7 +301,6 @@ const Update = struct {
299 .sh_size = file_size,301 .sh_size = file_size,
300 // The section header index of the associated string table.302 // The section header index of the associated string table.
301 .sh_link = self.shstrtab_index.?,303 .sh_link = self.shstrtab_index.?,
302 // One greater than the symbol table index of the last local symbol (binding STB_LOCAL).
303 .sh_info = @intCast(u32, self.module.exports.len),304 .sh_info = @intCast(u32, self.module.exports.len),
304 .sh_addralign = min_align,305 .sh_addralign = min_align,
305 .sh_entsize = each_size,306 .sh_entsize = each_size,
...@@ -332,136 +333,105 @@ const Update = struct {...@@ -332,136 +333,105 @@ const Update = struct {
332 phdr_table_dirty = true;333 phdr_table_dirty = true;
333 }334 }
334 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();335 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
335 if (shdr_table_dirty) {336
336 const allocated_size = self.allocatedSize(self.shdr_table_offset.?);337 try self.writeCodeAndSymbols(phdr_table_dirty, shdr_table_dirty);
337 const needed_size = self.sections.items.len * phsize;338
339 if (phdr_table_dirty) {
340 const allocated_size = self.allocatedSize(self.phdr_table_offset.?);
341 const needed_size = self.program_headers.items.len * phsize;
338342
339 if (needed_size > allocated_size) {343 if (needed_size > allocated_size) {
340 self.shdr_table_offset = null; // free the space344 self.phdr_table_offset = null; // free the space
341 self.shdr_table_offset = self.findFreeSpace(needed_size, phalign);345 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);
342 }346 }
343347
344 const allocator = self.sections.allocator;348 const allocator = self.program_headers.allocator;
345 switch (ptr_width) {349 switch (ptr_width) {
346 .p32 => {350 .p32 => {
347 const buf = try allocator.alloc(elf.Elf32_Shdr, self.sections.items.len);351 const buf = try allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
348 defer allocator.free(buf);352 defer allocator.free(buf);
349353
350 for (buf) |*shdr, i| {354 for (buf) |*phdr, i| {
351 shdr.* = .{355 phdr.* = progHeaderTo32(self.program_headers.items[i]);
352 .sh_name = self.sections.items[i].sh_name,
353 .sh_type = self.sections.items[i].sh_type,
354 .sh_flags = @intCast(u32, self.sections.items[i].sh_flags),
355 .sh_addr = @intCast(u32, self.sections.items[i].sh_addr),
356 .sh_offset = @intCast(u32, self.sections.items[i].sh_offset),
357 .sh_size = @intCast(u32, self.sections.items[i].sh_size),
358 .sh_link = self.sections.items[i].sh_link,
359 .sh_info = self.sections.items[i].sh_info,
360 .sh_addralign = @intCast(u32, self.sections.items[i].sh_addralign),
361 .sh_entsize = @intCast(u32, self.sections.items[i].sh_entsize),
362 };
363 if (foreign_endian) {356 if (foreign_endian) {
364 bswapAllFields(elf.Elf32_Shdr, shdr);357 bswapAllFields(elf.Elf32_Phdr, phdr);
365 }358 }
366 }359 }
367 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);360 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
368 },361 },
369 .p64 => {362 .p64 => {
370 const buf = try allocator.alloc(elf.Elf64_Shdr, self.sections.items.len);363 const buf = try allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
371 defer allocator.free(buf);364 defer allocator.free(buf);
372365
373 for (buf) |*shdr, i| {366 for (buf) |*phdr, i| {
374 shdr.* = .{367 phdr.* = self.program_headers.items[i];
375 .sh_name = self.sections.items[i].sh_name,
376 .sh_type = self.sections.items[i].sh_type,
377 .sh_flags = self.sections.items[i].sh_flags,
378 .sh_addr = self.sections.items[i].sh_addr,
379 .sh_offset = self.sections.items[i].sh_offset,
380 .sh_size = self.sections.items[i].sh_size,
381 .sh_link = self.sections.items[i].sh_link,
382 .sh_info = self.sections.items[i].sh_info,
383 .sh_addralign = self.sections.items[i].sh_addralign,
384 .sh_entsize = self.sections.items[i].sh_entsize,
385 };
386 if (foreign_endian) {368 if (foreign_endian) {
387 bswapAllFields(elf.Elf64_Shdr, shdr);369 bswapAllFields(elf.Elf64_Phdr, phdr);
388 }370 }
389 }371 }
390 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);372 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
391 },373 },
392 }374 }
393 }375 }
394376
395 try self.writeCodeAndSymbols(&phdr_table_dirty);377 {
378 const shstrtab_sect = &self.sections.items[self.shstrtab_index.?];
379 if (shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) {
380 const allocated_size = self.allocatedSize(shstrtab_sect.sh_offset);
381 const needed_size = self.shstrtab.items.len;
382
383 if (needed_size > allocated_size) {
384 shstrtab_sect.sh_size = 0; // free the space
385 shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);
386 }
387 shstrtab_sect.sh_size = needed_size;
388 //std.debug.warn("shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size });
396389
397 if (phdr_table_dirty) {390 try self.file.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
398 const allocated_size = self.allocatedSize(self.phdr_table_offset.?);391 if (!shdr_table_dirty) {
399 const needed_size = self.program_headers.items.len * phsize;392 // Then it won't get written with the others and we need to do it.
393 try self.writeSectHeader(self.shstrtab_index.?);
394 }
395 }
396 }
397 if (shdr_table_dirty) {
398 const allocated_size = self.allocatedSize(self.shdr_table_offset.?);
399 const needed_size = self.sections.items.len * phsize;
400400
401 if (needed_size > allocated_size) {401 if (needed_size > allocated_size) {
402 self.phdr_table_offset = null; // free the space402 self.shdr_table_offset = null; // free the space
403 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);403 self.shdr_table_offset = self.findFreeSpace(needed_size, phalign);
404 }404 }
405405
406 const allocator = self.program_headers.allocator;406 const allocator = self.sections.allocator;
407 switch (ptr_width) {407 switch (ptr_width) {
408 .p32 => {408 .p32 => {
409 const buf = try allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);409 const buf = try allocator.alloc(elf.Elf32_Shdr, self.sections.items.len);
410 defer allocator.free(buf);410 defer allocator.free(buf);
411411
412 for (buf) |*phdr, i| {412 for (buf) |*shdr, i| {
413 phdr.* = .{413 shdr.* = sectHeaderTo32(self.sections.items[i]);
414 .p_type = self.program_headers.items[i].p_type,
415 .p_flags = self.program_headers.items[i].p_flags,
416 .p_offset = @intCast(u32, self.program_headers.items[i].p_offset),
417 .p_vaddr = @intCast(u32, self.program_headers.items[i].p_vaddr),
418 .p_paddr = @intCast(u32, self.program_headers.items[i].p_paddr),
419 .p_filesz = @intCast(u32, self.program_headers.items[i].p_filesz),
420 .p_memsz = @intCast(u32, self.program_headers.items[i].p_memsz),
421 .p_align = @intCast(u32, self.program_headers.items[i].p_align),
422 };
423 if (foreign_endian) {414 if (foreign_endian) {
424 bswapAllFields(elf.Elf32_Phdr, phdr);415 bswapAllFields(elf.Elf32_Shdr, shdr);
425 }416 }
426 }417 }
427 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);418 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
428 },419 },
429 .p64 => {420 .p64 => {
430 const buf = try allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);421 const buf = try allocator.alloc(elf.Elf64_Shdr, self.sections.items.len);
431 defer allocator.free(buf);422 defer allocator.free(buf);
432423
433 for (buf) |*phdr, i| {424 for (buf) |*shdr, i| {
434 phdr.* = .{425 shdr.* = self.sections.items[i];
435 .p_type = self.program_headers.items[i].p_type,426 //std.debug.warn("writing section {}\n", .{shdr.*});
436 .p_flags = self.program_headers.items[i].p_flags,
437 .p_offset = self.program_headers.items[i].p_offset,
438 .p_vaddr = self.program_headers.items[i].p_vaddr,
439 .p_paddr = self.program_headers.items[i].p_paddr,
440 .p_filesz = self.program_headers.items[i].p_filesz,
441 .p_memsz = self.program_headers.items[i].p_memsz,
442 .p_align = self.program_headers.items[i].p_align,
443 };
444 if (foreign_endian) {427 if (foreign_endian) {
445 bswapAllFields(elf.Elf64_Phdr, phdr);428 bswapAllFields(elf.Elf64_Shdr, shdr);
446 }429 }
447 }430 }
448 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);431 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
449 },432 },
450 }433 }
451 }434 }
452
453 const shstrtab_sect = &self.sections.items[self.shstrtab_index.?];
454 if (shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) {
455 const allocated_size = self.allocatedSize(shstrtab_sect.sh_offset);
456 const needed_size = self.shstrtab.items.len;
457
458 if (needed_size > allocated_size) {
459 shstrtab_sect.sh_size = 0; // free the space
460 shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);
461 shstrtab_sect.sh_size = needed_size;
462 }
463 try self.file.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
464 }
465 if (self.entry_addr == null) {435 if (self.entry_addr == null) {
466 const msg = try std.fmt.allocPrint(self.errors.allocator, "no entry point found", .{});436 const msg = try std.fmt.allocPrint(self.errors.allocator, "no entry point found", .{});
467 errdefer self.errors.allocator.free(msg);437 errdefer self.errors.allocator.free(msg);
...@@ -592,7 +562,7 @@ const Update = struct {...@@ -592,7 +562,7 @@ const Update = struct {
592 try self.file.pwriteAll(hdr_buf[0..index], 0);562 try self.file.pwriteAll(hdr_buf[0..index], 0);
593 }563 }
594564
595 fn writeCodeAndSymbols(self: *Update, phdr_table_dirty: *bool) !void {565 fn writeCodeAndSymbols(self: *Update, phdr_table_dirty: bool, shdr_table_dirty: bool) !void {
596 // index 0 is always a null symbol566 // index 0 is always a null symbol
597 try self.symbols.resize(1);567 try self.symbols.resize(1);
598 self.symbols.items[0] = .{568 self.symbols.items[0] = .{
...@@ -606,6 +576,7 @@ const Update = struct {...@@ -606,6 +576,7 @@ const Update = struct {
606576
607 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];577 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
608 var vaddr: u64 = phdr.p_vaddr;578 var vaddr: u64 = phdr.p_vaddr;
579 var file_off: u64 = phdr.p_offset;
609580
610 var code = std.ArrayList(u8).init(self.sections.allocator);581 var code = std.ArrayList(u8).init(self.sections.allocator);
611 defer code.deinit();582 defer code.deinit();
...@@ -625,6 +596,7 @@ const Update = struct {...@@ -625,6 +596,7 @@ const Update = struct {
625 }596 }
626 continue;597 continue;
627 }598 }
599 try self.file.pwriteAll(code.items, file_off);
628600
629 if (mem.eql(u8, exp.name, "_start")) {601 if (mem.eql(u8, exp.name, "_start")) {
630 self.entry_addr = vaddr;602 self.entry_addr = vaddr;
...@@ -645,12 +617,67 @@ const Update = struct {...@@ -645,12 +617,67 @@ const Update = struct {
645 phdr.p_memsz = vaddr - phdr.p_vaddr;617 phdr.p_memsz = vaddr - phdr.p_vaddr;
646 phdr.p_filesz = phdr.p_memsz;618 phdr.p_filesz = phdr.p_memsz;
647619
648 phdr_table_dirty.* = true;620 const shdr = &self.sections.items[self.text_section_index.?];
621 shdr.sh_size = phdr.p_filesz;
622
623 if (!phdr_table_dirty) {
624 // Then it won't get written with the others and we need to do it.
625 try self.writeProgHeader(self.phdr_load_re_index.?);
626 }
627 if (!shdr_table_dirty) {
628 // Then it won't get written with the others and we need to do it.
629 try self.writeSectHeader(self.text_section_index.?);
630 }
649 }631 }
650632
651 return self.writeSymbols();633 return self.writeSymbols();
652 }634 }
653635
636 fn writeProgHeader(self: *Update, index: usize) !void {
637 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
638 const offset = self.program_headers.items[index].p_offset;
639 switch (self.module.target.cpu.arch.ptrBitWidth()) {
640 32 => {
641 var phdr = [1]elf.Elf32_Phdr{progHeaderTo32(self.program_headers.items[index])};
642 if (foreign_endian) {
643 bswapAllFields(elf.Elf32_Phdr, &phdr[0]);
644 }
645 return self.file.pwriteAll(mem.sliceAsBytes(&phdr), offset);
646 },
647 64 => {
648 var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]};
649 if (foreign_endian) {
650 bswapAllFields(elf.Elf64_Phdr, &phdr[0]);
651 }
652 return self.file.pwriteAll(mem.sliceAsBytes(&phdr), offset);
653 },
654 else => return error.UnsupportedArchitecture,
655 }
656 }
657
658 fn writeSectHeader(self: *Update, index: usize) !void {
659 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
660 const offset = self.sections.items[index].sh_offset;
661 switch (self.module.target.cpu.arch.ptrBitWidth()) {
662 32 => {
663 var shdr: [1]elf.Elf32_Shdr = undefined;
664 shdr[0] = sectHeaderTo32(self.sections.items[index]);
665 if (foreign_endian) {
666 bswapAllFields(elf.Elf32_Shdr, &shdr[0]);
667 }
668 return self.file.pwriteAll(mem.sliceAsBytes(&shdr), offset);
669 },
670 64 => {
671 var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]};
672 if (foreign_endian) {
673 bswapAllFields(elf.Elf64_Shdr, &shdr[0]);
674 }
675 return self.file.pwriteAll(mem.sliceAsBytes(&shdr), offset);
676 },
677 else => return error.UnsupportedArchitecture,
678 }
679 }
680
654 fn writeSymbols(self: *Update) !void {681 fn writeSymbols(self: *Update) !void {
655 const ptr_width: enum { p32, p64 } = switch (self.module.target.cpu.arch.ptrBitWidth()) {682 const ptr_width: enum { p32, p64 } = switch (self.module.target.cpu.arch.ptrBitWidth()) {
656 32 => .p32,683 32 => .p32,
...@@ -667,8 +694,11 @@ const Update = struct {...@@ -667,8 +694,11 @@ const Update = struct {
667 if (needed_size > allocated_size) {694 if (needed_size > allocated_size) {
668 syms_sect.sh_size = 0; // free the space695 syms_sect.sh_size = 0; // free the space
669 syms_sect.sh_offset = self.findFreeSpace(needed_size, sym_align);696 syms_sect.sh_offset = self.findFreeSpace(needed_size, sym_align);
670 syms_sect.sh_size = needed_size;697 //std.debug.warn("moved symtab to 0x{x} to 0x{x}\n", .{ syms_sect.sh_offset, syms_sect.sh_offset + needed_size });
671 }698 }
699 //std.debug.warn("symtab start=0x{x} end=0x{x}\n", .{ syms_sect.sh_offset, syms_sect.sh_offset + needed_size });
700 syms_sect.sh_size = needed_size;
701 syms_sect.sh_info = @intCast(u32, self.symbols.items.len);
672 const allocator = self.symbols.allocator;702 const allocator = self.symbols.allocator;
673 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();703 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
674 switch (ptr_width) {704 switch (ptr_width) {
...@@ -760,3 +790,31 @@ fn satMul(a: var, b: var) @TypeOf(a, b) {...@@ -760,3 +790,31 @@ fn satMul(a: var, b: var) @TypeOf(a, b) {
760fn bswapAllFields(comptime S: type, ptr: *S) void {790fn bswapAllFields(comptime S: type, ptr: *S) void {
761 @panic("TODO implement bswapAllFields");791 @panic("TODO implement bswapAllFields");
762}792}
793
794fn progHeaderTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr {
795 return .{
796 .p_type = phdr.p_type,
797 .p_flags = phdr.p_flags,
798 .p_offset = @intCast(u32, phdr.p_offset),
799 .p_vaddr = @intCast(u32, phdr.p_vaddr),
800 .p_paddr = @intCast(u32, phdr.p_paddr),
801 .p_filesz = @intCast(u32, phdr.p_filesz),
802 .p_memsz = @intCast(u32, phdr.p_memsz),
803 .p_align = @intCast(u32, phdr.p_align),
804 };
805}
806
807fn sectHeaderTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr {
808 return .{
809 .sh_name = shdr.sh_name,
810 .sh_type = shdr.sh_type,
811 .sh_flags = @intCast(u32, shdr.sh_flags),
812 .sh_addr = @intCast(u32, shdr.sh_addr),
813 .sh_offset = @intCast(u32, shdr.sh_offset),
814 .sh_size = @intCast(u32, shdr.sh_size),
815 .sh_link = shdr.sh_link,
816 .sh_info = shdr.sh_info,
817 .sh_addralign = @intCast(u32, shdr.sh_addralign),
818 .sh_entsize = @intCast(u32, shdr.sh_entsize),
819 };
820}