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 {
378378 return self.fail(src, "TODO handle a larger string constant", .{});
379379
380380 // Emit the string literal directly into the code; jump over it.
381 const offset = self.code.items.len;
382381 try self.genRelativeFwdJump(src, smaller_len);
382 const offset = self.code.items.len;
383383 try self.code.appendSlice(bytes);
384384 return MCValue{ .embedded_in_code = offset };
385385 },
src-self-hosted/link.zig+150-92
......@@ -174,7 +174,7 @@ const Update = struct {
174174 if (program_header.p_offset <= start) continue;
175175 if (program_header.p_offset < min_pos) min_pos = program_header.p_offset;
176176 }
177 return min_pos;
177 return min_pos - start;
178178 }
179179
180180 fn findFreeSpace(self: *Update, object_size: u64, min_alignment: u16) u64 {
......@@ -233,7 +233,7 @@ const Update = struct {
233233 // There must always be a null section in index 0
234234 try self.sections.append(.{
235235 .sh_name = 0,
236 .sh_type = 0,
236 .sh_type = elf.SHT_NULL,
237237 .sh_flags = 0,
238238 .sh_addr = 0,
239239 .sh_offset = 0,
......@@ -247,6 +247,8 @@ const Update = struct {
247247 }
248248 if (self.shstrtab_index == null) {
249249 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
250252 const off = self.findFreeSpace(self.shstrtab.items.len, 1);
251253 //std.debug.warn("found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });
252254 try self.sections.append(.{
......@@ -299,7 +301,6 @@ const Update = struct {
299301 .sh_size = file_size,
300302 // The section header index of the associated string table.
301303 .sh_link = self.shstrtab_index.?,
302 // One greater than the symbol table index of the last local symbol (binding STB_LOCAL).
303304 .sh_info = @intCast(u32, self.module.exports.len),
304305 .sh_addralign = min_align,
305306 .sh_entsize = each_size,
......@@ -332,136 +333,105 @@ const Update = struct {
332333 phdr_table_dirty = true;
333334 }
334335 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
335 if (shdr_table_dirty) {
336 const allocated_size = self.allocatedSize(self.shdr_table_offset.?);
337 const needed_size = self.sections.items.len * phsize;
336
337 try self.writeCodeAndSymbols(phdr_table_dirty, shdr_table_dirty);
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
339343 if (needed_size > allocated_size) {
340 self.shdr_table_offset = null; // free the space
341 self.shdr_table_offset = self.findFreeSpace(needed_size, phalign);
344 self.phdr_table_offset = null; // free the space
345 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);
342346 }
343347
344 const allocator = self.sections.allocator;
348 const allocator = self.program_headers.allocator;
345349 switch (ptr_width) {
346350 .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);
348352 defer allocator.free(buf);
349353
350 for (buf) |*shdr, i| {
351 shdr.* = .{
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 };
354 for (buf) |*phdr, i| {
355 phdr.* = progHeaderTo32(self.program_headers.items[i]);
363356 if (foreign_endian) {
364 bswapAllFields(elf.Elf32_Shdr, shdr);
357 bswapAllFields(elf.Elf32_Phdr, phdr);
365358 }
366359 }
367 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
360 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
368361 },
369362 .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);
371364 defer allocator.free(buf);
372365
373 for (buf) |*shdr, i| {
374 shdr.* = .{
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 };
366 for (buf) |*phdr, i| {
367 phdr.* = self.program_headers.items[i];
386368 if (foreign_endian) {
387 bswapAllFields(elf.Elf64_Shdr, shdr);
369 bswapAllFields(elf.Elf64_Phdr, phdr);
388370 }
389371 }
390 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
372 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
391373 },
392374 }
393375 }
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) {
398 const allocated_size = self.allocatedSize(self.phdr_table_offset.?);
399 const needed_size = self.program_headers.items.len * phsize;
390 try self.file.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
391 if (!shdr_table_dirty) {
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
401401 if (needed_size > allocated_size) {
402 self.phdr_table_offset = null; // free the space
403 self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);
402 self.shdr_table_offset = null; // free the space
403 self.shdr_table_offset = self.findFreeSpace(needed_size, phalign);
404404 }
405405
406 const allocator = self.program_headers.allocator;
406 const allocator = self.sections.allocator;
407407 switch (ptr_width) {
408408 .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);
410410 defer allocator.free(buf);
411411
412 for (buf) |*phdr, i| {
413 phdr.* = .{
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 };
412 for (buf) |*shdr, i| {
413 shdr.* = sectHeaderTo32(self.sections.items[i]);
423414 if (foreign_endian) {
424 bswapAllFields(elf.Elf32_Phdr, phdr);
415 bswapAllFields(elf.Elf32_Shdr, shdr);
425416 }
426417 }
427 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
418 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
428419 },
429420 .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);
431422 defer allocator.free(buf);
432423
433 for (buf) |*phdr, i| {
434 phdr.* = .{
435 .p_type = self.program_headers.items[i].p_type,
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 };
424 for (buf) |*shdr, i| {
425 shdr.* = self.sections.items[i];
426 //std.debug.warn("writing section {}\n", .{shdr.*});
444427 if (foreign_endian) {
445 bswapAllFields(elf.Elf64_Phdr, phdr);
428 bswapAllFields(elf.Elf64_Shdr, shdr);
446429 }
447430 }
448 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
431 try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
449432 },
450433 }
451434 }
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 }
465435 if (self.entry_addr == null) {
466436 const msg = try std.fmt.allocPrint(self.errors.allocator, "no entry point found", .{});
467437 errdefer self.errors.allocator.free(msg);
......@@ -592,7 +562,7 @@ const Update = struct {
592562 try self.file.pwriteAll(hdr_buf[0..index], 0);
593563 }
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 {
596566 // index 0 is always a null symbol
597567 try self.symbols.resize(1);
598568 self.symbols.items[0] = .{
......@@ -606,6 +576,7 @@ const Update = struct {
606576
607577 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
608578 var vaddr: u64 = phdr.p_vaddr;
579 var file_off: u64 = phdr.p_offset;
609580
610581 var code = std.ArrayList(u8).init(self.sections.allocator);
611582 defer code.deinit();
......@@ -625,6 +596,7 @@ const Update = struct {
625596 }
626597 continue;
627598 }
599 try self.file.pwriteAll(code.items, file_off);
628600
629601 if (mem.eql(u8, exp.name, "_start")) {
630602 self.entry_addr = vaddr;
......@@ -645,12 +617,67 @@ const Update = struct {
645617 phdr.p_memsz = vaddr - phdr.p_vaddr;
646618 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 }
649631 }
650632
651633 return self.writeSymbols();
652634 }
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
654681 fn writeSymbols(self: *Update) !void {
655682 const ptr_width: enum { p32, p64 } = switch (self.module.target.cpu.arch.ptrBitWidth()) {
656683 32 => .p32,
......@@ -667,8 +694,11 @@ const Update = struct {
667694 if (needed_size > allocated_size) {
668695 syms_sect.sh_size = 0; // free the space
669696 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 });
671698 }
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);
672702 const allocator = self.symbols.allocator;
673703 const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
674704 switch (ptr_width) {
......@@ -760,3 +790,31 @@ fn satMul(a: var, b: var) @TypeOf(a, b) {
760790fn bswapAllFields(comptime S: type, ptr: *S) void {
761791 @panic("TODO implement bswapAllFields");
762792}
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}