lib/tldr/src/formats/elf/layout/output.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const root = @import("../../../root.zig");
2 const elf = @import("../root.zig");
3
4 const model = root.model;
5 const OutputSection = elf.layout.OutputSection;
6 const output_section_count = elf.output_section.output_section_count;
7 const ehdr_size = elf.format.ehdr_size;
8 const phdr_size = elf.format.phdr_size;
9 const alignForward = elf.format.alignForward;
10 const alignForwardU64 = elf.format.alignForwardU64;
11 const reserveSize = elf.layout.reserveSize;
12
13 pub fn countLive(output_sections: []const OutputSection) usize {
14 var count: usize = 0;
15 for (output_sections) |section| {
16 if (section.logicalSize() != 0) count += 1;
17 }
18 return count;
19 }
20
21 pub fn assign(
22 output_sections: *[output_section_count]OutputSection,
23 options: model.LinkOptions,
24 program_header_count: usize,
25 ) model.Error!void {
26 var file_offset = ehdr_size + program_header_count * phdr_size;
27 var address_cursor = options.image_base;
28 var section_index: u16 = 1;
29 var previous_alloc_was_tls = false;
30 for (output_sections) |*section| {
31 const logical_size = section.logicalSize();
32 if (logical_size == 0) continue;
33 file_offset = alignForward(file_offset, @intCast(@max(section.alignment, 1)));
34 section.file_offset = @intCast(file_offset);
35 section.address = if (section.kind.isAllocated())
36 if (section.kind.isTls() and previous_alloc_was_tls)
37 address_cursor
38 else
39 loadAddressForFileOffset(address_cursor, section.file_offset, options.page_size)
40 else
41 0;
42 section.reserved_size = reserveSize(logical_size, section.alignment, options);
43 section.section_index = section_index;
44 section_index += 1;
45 if (section.kind.isAllocated()) {
46 address_cursor = section.address + section.reserved_size;
47 previous_alloc_was_tls = section.kind.isTls();
48 }
49 file_offset += @intCast(section.fileLoadSize());
50 }
51 }
52
53 fn loadAddressForFileOffset(address_cursor: u64, file_offset: u64, page_size: u64) u64 {
54 if (page_size <= 1) return address_cursor + file_offset;
55 return alignForwardU64(address_cursor, page_size) + file_offset % page_size;
56 }