| ... | ... | @@ -409,16 +409,24 @@ fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 { |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | 411 | const AllocateSegmentOpts = struct { |
| 412 | | addr: u64, // TODO find free VM space |
| 413 | 412 | size: u64, |
| 414 | 413 | alignment: u64, |
| 414 | addr: ?u64 = null, // TODO find free VM space |
| 415 | 415 | flags: u32 = elf.PF_R, |
| 416 | 416 | }; |
| 417 | 417 | |
| 418 | | fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}!u16 { |
| 418 | pub fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}!u16 { |
| 419 | 419 | const index = @as(u16, @intCast(self.phdrs.items.len)); |
| 420 | 420 | try self.phdrs.ensureUnusedCapacity(self.base.allocator, 1); |
| 421 | 421 | const off = self.findFreeSpace(opts.size, opts.alignment); |
| 422 | // Memory is always allocated in sequence. |
| 423 | // TODO is this correct? Or should we implement something similar to `findFreeSpace`? |
| 424 | // How would that impact HCS? |
| 425 | const addr = opts.addr orelse blk: { |
| 426 | assert(self.phdr_table_load_index != null); |
| 427 | const phdr = &self.phdrs.items[index - 1]; |
| 428 | break :blk mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, opts.alignment); |
| 429 | }; |
| 422 | 430 | log.debug("allocating phdr({d})({c}{c}{c}) from 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| 423 | 431 | index, |
| 424 | 432 | if (opts.flags & elf.PF_R != 0) @as(u8, 'R') else '_', |
| ... | ... | @@ -426,15 +434,15 @@ fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}!u16 |
| 426 | 434 | if (opts.flags & elf.PF_X != 0) @as(u8, 'X') else '_', |
| 427 | 435 | off, |
| 428 | 436 | off + opts.size, |
| 429 | | opts.addr, |
| 430 | | opts.addr + opts.size, |
| 437 | addr, |
| 438 | addr + opts.size, |
| 431 | 439 | }); |
| 432 | 440 | self.phdrs.appendAssumeCapacity(.{ |
| 433 | 441 | .p_type = elf.PT_LOAD, |
| 434 | 442 | .p_offset = off, |
| 435 | 443 | .p_filesz = opts.size, |
| 436 | | .p_vaddr = opts.addr, |
| 437 | | .p_paddr = opts.addr, |
| 444 | .p_vaddr = addr, |
| 445 | .p_paddr = addr, |
| 438 | 446 | .p_memsz = opts.size, |
| 439 | 447 | .p_align = opts.alignment, |
| 440 | 448 | .p_flags = opts.flags, |
| ... | ... | @@ -446,12 +454,12 @@ fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}!u16 |
| 446 | 454 | const AllocateAllocSectionOpts = struct { |
| 447 | 455 | name: [:0]const u8, |
| 448 | 456 | phdr_index: u16, |
| 449 | | alignment: u16 = 1, |
| 450 | | flags: u16 = elf.SHF_ALLOC, |
| 457 | alignment: u64 = 1, |
| 458 | flags: u64 = elf.SHF_ALLOC, |
| 451 | 459 | type: u32 = elf.SHT_PROGBITS, |
| 452 | 460 | }; |
| 453 | 461 | |
| 454 | | fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{OutOfMemory}!u16 { |
| 462 | pub fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{OutOfMemory}!u16 { |
| 455 | 463 | const gpa = self.base.allocator; |
| 456 | 464 | const phdr = &self.phdrs.items[opts.phdr_index]; |
| 457 | 465 | const index = @as(u16, @intCast(self.shdrs.items.len)); |
| ... | ... | @@ -622,6 +630,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 622 | 630 | }); |
| 623 | 631 | const phdr = &self.phdrs.items[self.phdr_load_zerofill_index.?]; |
| 624 | 632 | phdr.p_offset = self.phdrs.items[self.phdr_load_rw_index.?].p_offset; // .bss overlaps .data |
| 633 | phdr.p_memsz = 1024; |
| 625 | 634 | } |
| 626 | 635 | |
| 627 | 636 | if (self.shstrtab_section_index == null) { |
| ... | ... | @@ -994,6 +1003,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 994 | 1003 | try positionals.append(.{ .path = key.status.success.object_path }); |
| 995 | 1004 | } |
| 996 | 1005 | |
| 1006 | // csu prelude |
| 1007 | var csu = try CsuObjects.init(arena, self.base.options, comp); |
| 1008 | if (csu.crt0) |v| try positionals.append(.{ .path = v }); |
| 1009 | if (csu.crti) |v| try positionals.append(.{ .path = v }); |
| 1010 | if (csu.crtbegin) |v| try positionals.append(.{ .path = v }); |
| 1011 | |
| 997 | 1012 | for (positionals.items) |obj| { |
| 998 | 1013 | const in_file = try std.fs.cwd().openFile(obj.path, .{}); |
| 999 | 1014 | defer in_file.close(); |
| ... | ... | @@ -1039,18 +1054,29 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1039 | 1054 | try self.handleAndReportParseError(lib.path, err, &parse_ctx); |
| 1040 | 1055 | } |
| 1041 | 1056 | |
| 1042 | | // Finally, as the last input object add compiler_rt if any. |
| 1057 | // Finally, as the last input objects we add compiler_rt and CSU postlude (if any). |
| 1058 | positionals.clearRetainingCapacity(); |
| 1059 | |
| 1060 | // compiler-rt. Since compiler_rt exports symbols like `memset`, it needs |
| 1061 | // to be after the shared libraries, so they are picked up from the shared |
| 1062 | // libraries, not libcompiler_rt. |
| 1043 | 1063 | const compiler_rt_path: ?[]const u8 = blk: { |
| 1044 | 1064 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| 1045 | 1065 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| 1046 | 1066 | break :blk null; |
| 1047 | 1067 | }; |
| 1048 | | if (compiler_rt_path) |path| { |
| 1049 | | const in_file = try std.fs.cwd().openFile(path, .{}); |
| 1068 | if (compiler_rt_path) |path| try positionals.append(.{ .path = path }); |
| 1069 | |
| 1070 | // csu postlude |
| 1071 | if (csu.crtend) |v| try positionals.append(.{ .path = v }); |
| 1072 | if (csu.crtn) |v| try positionals.append(.{ .path = v }); |
| 1073 | |
| 1074 | for (positionals.items) |obj| { |
| 1075 | const in_file = try std.fs.cwd().openFile(obj.path, .{}); |
| 1050 | 1076 | defer in_file.close(); |
| 1051 | 1077 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; |
| 1052 | | self.parsePositional(in_file, path, false, &parse_ctx) catch |err| |
| 1053 | | try self.handleAndReportParseError(path, err, &parse_ctx); |
| 1078 | self.parsePositional(in_file, obj.path, obj.must_link, &parse_ctx) catch |err| |
| 1079 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); |
| 1054 | 1080 | } |
| 1055 | 1081 | |
| 1056 | 1082 | // Handle any lazy symbols that were emitted by incremental compilation. |