authorgravatar for julien.philippon@epitech.euErsikan <julien.philippon@epitech.eu> 2021-03-12 23:46:51+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-21 11:33:12-08:00
loge15a267668bae168f2bba06cc3706c54bc062522
treeb84e6f17eda1e677dbb7a9adcf630741ae94c05b
parent44061cd760cba603ddc2afa10d882ce71c5d389b

elf: Put constant data in the .rodata section

Allocate a new program header and a new section to accomodate the read-only data section ".rodata". Separate TextBlock into multiple TextBlockList, to separate decl in different sections. If a Decl is not a function, it is added to the .rodata section.

1 files changed, 106 insertions(+), 40 deletions(-)

src/link/Elf.zig+106-40
...@@ -54,13 +54,14 @@ phdr_load_re_index: ?u16 = null,...@@ -54,13 +54,14 @@ phdr_load_re_index: ?u16 = null,
54/// The index into the program headers of the global offset table.54/// The index into the program headers of the global offset table.
55/// It needs PT_LOAD and Read flags.55/// It needs PT_LOAD and Read flags.
56phdr_got_index: ?u16 = null,56phdr_got_index: ?u16 = null,
57/// The index into the program headers of a PT_LOAD program header with Read flag
58phdr_load_ro_index: ?u16 = null,
57entry_addr: ?u64 = null,59entry_addr: ?u64 = null,
5860
59debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){},61debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){},
60shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){},62shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){},
61shstrtab_index: ?u16 = null,63shstrtab_index: ?u16 = null,
6264
63text_section_index: ?u16 = null,
64symtab_section_index: ?u16 = null,65symtab_section_index: ?u16 = null,
65got_section_index: ?u16 = null,66got_section_index: ?u16 = null,
66debug_info_section_index: ?u16 = null,67debug_info_section_index: ?u16 = null,
...@@ -115,8 +116,8 @@ error_flags: File.ErrorFlags = File.ErrorFlags{},...@@ -115,8 +116,8 @@ error_flags: File.ErrorFlags = File.ErrorFlags{},
115/// overcapacity can be negative. A simple way to have negative overcapacity is to116/// overcapacity can be negative. A simple way to have negative overcapacity is to
116/// allocate a fresh text block, which will have ideal capacity, and then grow it117/// allocate a fresh text block, which will have ideal capacity, and then grow it
117/// by 1 byte. It will then have -1 overcapacity.118/// by 1 byte. It will then have -1 overcapacity.
118text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{},119text_block_list: TextBlockList = .{},
119last_text_block: ?*TextBlock = null,120rodata_block_list: TextBlockList = .{},
120121
121/// A list of `SrcFn` whose Line Number Programs have surplus capacity.122/// A list of `SrcFn` whose Line Number Programs have surplus capacity.
122/// This is the same concept as `text_block_free_list`; see those doc comments.123/// This is the same concept as `text_block_free_list`; see those doc comments.
...@@ -204,6 +205,14 @@ pub const TextBlock = struct {...@@ -204,6 +205,14 @@ pub const TextBlock = struct {
204 }205 }
205};206};
206207
208/// A list of text blocks in a specific section
209const TextBlockList = struct {
210 free_list: std.ArrayListUnmanaged(*TextBlock) = .{},
211 last_block: ?*TextBlock = null,
212 phdr_index: ?u16 = null,
213 section_index: ?u16 = null,
214};
215
207pub const Export = struct {216pub const Export = struct {
208 sym_index: ?u32 = null,217 sym_index: ?u32 = null,
209};218};
...@@ -314,7 +323,8 @@ pub fn deinit(self: *Elf) void {...@@ -314,7 +323,8 @@ pub fn deinit(self: *Elf) void {
314 self.global_symbol_free_list.deinit(self.base.allocator);323 self.global_symbol_free_list.deinit(self.base.allocator);
315 self.local_symbol_free_list.deinit(self.base.allocator);324 self.local_symbol_free_list.deinit(self.base.allocator);
316 self.offset_table_free_list.deinit(self.base.allocator);325 self.offset_table_free_list.deinit(self.base.allocator);
317 self.text_block_free_list.deinit(self.base.allocator);326 self.text_block_list.free_list.deinit(self.base.allocator);
327 self.rodata_block_list.free_list.deinit(self.base.allocator);
318 self.dbg_line_fn_free_list.deinit(self.base.allocator);328 self.dbg_line_fn_free_list.deinit(self.base.allocator);
319 self.dbg_info_decl_free_list.deinit(self.base.allocator);329 self.dbg_info_decl_free_list.deinit(self.base.allocator);
320 self.offset_table.deinit(self.base.allocator);330 self.offset_table.deinit(self.base.allocator);
...@@ -450,6 +460,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -450,6 +460,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
450 const ptr_size: u8 = self.ptrWidthBytes();460 const ptr_size: u8 = self.ptrWidthBytes();
451 if (self.phdr_load_re_index == null) {461 if (self.phdr_load_re_index == null) {
452 self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len);462 self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len);
463 self.text_block_list.phdr_index = self.phdr_load_re_index;
453 const file_size = self.base.options.program_code_size_hint;464 const file_size = self.base.options.program_code_size_hint;
454 const p_align = 0x1000;465 const p_align = 0x1000;
455 const off = self.findFreeSpace(file_size, p_align);466 const off = self.findFreeSpace(file_size, p_align);
...@@ -492,6 +503,29 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -492,6 +503,29 @@ pub fn populateMissingMetadata(self: *Elf) !void {
492 });503 });
493 self.phdr_table_dirty = true;504 self.phdr_table_dirty = true;
494 }505 }
506 if (self.phdr_load_ro_index == null) {
507 self.phdr_load_ro_index = @intCast(u16, self.program_headers.items.len);
508 self.rodata_block_list.phdr_index = self.phdr_load_ro_index;
509 // TODO Find a hint about how much data need to be in rodata ?
510 const file_size = 1024;
511 // Same reason as for GOT
512 const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size);
513 const off = self.findFreeSpace(file_size, p_align);
514 log.debug("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
515 // TODO Same as for GOT
516 const rodata_addr: u32 = if (self.base.options.target.cpu.arch.ptrBitWidth() >= 32) 0x6000000 else 0xD000;
517 try self.program_headers.append(self.base.allocator, .{
518 .p_type = elf.PT_LOAD,
519 .p_offset = off,
520 .p_filesz = file_size,
521 .p_vaddr = rodata_addr,
522 .p_paddr = rodata_addr,
523 .p_memsz = file_size,
524 .p_align = p_align,
525 .p_flags = elf.PF_R,
526 });
527 self.phdr_table_dirty = true;
528 }
495 if (self.shstrtab_index == null) {529 if (self.shstrtab_index == null) {
496 self.shstrtab_index = @intCast(u16, self.sections.items.len);530 self.shstrtab_index = @intCast(u16, self.sections.items.len);
497 assert(self.shstrtab.items.len == 0);531 assert(self.shstrtab.items.len == 0);
...@@ -513,8 +547,8 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -513,8 +547,8 @@ pub fn populateMissingMetadata(self: *Elf) !void {
513 self.shstrtab_dirty = true;547 self.shstrtab_dirty = true;
514 self.shdr_table_dirty = true;548 self.shdr_table_dirty = true;
515 }549 }
516 if (self.text_section_index == null) {550 if (self.text_block_list.section_index == null) {
517 self.text_section_index = @intCast(u16, self.sections.items.len);551 self.text_block_list.section_index = @intCast(u16, self.sections.items.len);
518 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];552 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
519553
520 try self.sections.append(self.base.allocator, .{554 try self.sections.append(self.base.allocator, .{
...@@ -549,6 +583,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -549,6 +583,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
549 });583 });
550 self.shdr_table_dirty = true;584 self.shdr_table_dirty = true;
551 }585 }
586 if (self.rodata_block_list.section_index == null) {
587 self.rodata_block_list.section_index = @intCast(u16, self.sections.items.len);
588 const phdr = &self.program_headers.items[self.phdr_load_ro_index.?];
589
590 try self.sections.append(self.base.allocator, .{
591 .sh_name = try self.makeString(".rodata"),
592 .sh_type = elf.SHT_PROGBITS,
593 .sh_flags = elf.SHF_ALLOC,
594 .sh_addr = phdr.p_vaddr,
595 .sh_offset = phdr.p_offset,
596 .sh_size = phdr.p_filesz,
597 .sh_link = 0,
598 .sh_info = 0,
599 .sh_addralign = phdr.p_align,
600 .sh_entsize = 0,
601 });
602 self.shdr_table_dirty = true;
603 }
552 if (self.symtab_section_index == null) {604 if (self.symtab_section_index == null) {
553 self.symtab_section_index = @intCast(u16, self.sections.items.len);605 self.symtab_section_index = @intCast(u16, self.sections.items.len);
554 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);606 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);
...@@ -1927,17 +1979,17 @@ fn writeElfHeader(self: *Elf) !void {...@@ -1927,17 +1979,17 @@ fn writeElfHeader(self: *Elf) !void {
1927 try self.base.file.?.pwriteAll(hdr_buf[0..index], 0);1979 try self.base.file.?.pwriteAll(hdr_buf[0..index], 0);
1928}1980}
19291981
1930fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {1982fn freeTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock) void {
1931 var already_have_free_list_node = false;1983 var already_have_free_list_node = false;
1932 {1984 {
1933 var i: usize = 0;1985 var i: usize = 0;
1934 // TODO turn text_block_free_list into a hash map1986 // TODO turn text_block_free_list into a hash map
1935 while (i < self.text_block_free_list.items.len) {1987 while (i < block_list.free_list.items.len) {
1936 if (self.text_block_free_list.items[i] == text_block) {1988 if (block_list.free_list.items[i] == text_block) {
1937 _ = self.text_block_free_list.swapRemove(i);1989 _ = block_list.free_list.swapRemove(i);
1938 continue;1990 continue;
1939 }1991 }
1940 if (self.text_block_free_list.items[i] == text_block.prev) {1992 if (block_list.free_list.items[i] == text_block.prev) {
1941 already_have_free_list_node = true;1993 already_have_free_list_node = true;
1942 }1994 }
1943 i += 1;1995 i += 1;
...@@ -1945,9 +1997,9 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {...@@ -1945,9 +1997,9 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
1945 }1997 }
1946 // TODO process free list for dbg info just like we do above for vaddrs1998 // TODO process free list for dbg info just like we do above for vaddrs
19471999
1948 if (self.last_text_block == text_block) {2000 if (block_list.last_block == text_block) {
1949 // TODO shrink the .text section size here2001 // TODO shrink the .text section size here
1950 self.last_text_block = text_block.prev;2002 block_list.last_block = text_block.prev;
1951 }2003 }
1952 if (self.dbg_info_decl_first == text_block) {2004 if (self.dbg_info_decl_first == text_block) {
1953 self.dbg_info_decl_first = text_block.dbg_info_next;2005 self.dbg_info_decl_first = text_block.dbg_info_next;
...@@ -1963,7 +2015,7 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {...@@ -1963,7 +2015,7 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
1963 if (!already_have_free_list_node and prev.freeListEligible(self.*)) {2015 if (!already_have_free_list_node and prev.freeListEligible(self.*)) {
1964 // The free list is heuristics, it doesn't have to be perfect, so we can2016 // The free list is heuristics, it doesn't have to be perfect, so we can
1965 // ignore the OOM here.2017 // ignore the OOM here.
1966 self.text_block_free_list.append(self.base.allocator, prev) catch {};2018 block_list.free_list.append(self.base.allocator, prev) catch {};
1967 }2019 }
1968 } else {2020 } else {
1969 text_block.prev = null;2021 text_block.prev = null;
...@@ -1990,25 +2042,24 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {...@@ -1990,25 +2042,24 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
1990 }2042 }
1991}2043}
19922044
1993fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64) void {2045fn shrinkTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock, new_block_size: u64) void {
1994 _ = self;2046 _ = self;
2047 _ = block_list;
1995 _ = text_block;2048 _ = text_block;
1996 _ = new_block_size;2049 _ = new_block_size;
1997 // TODO check the new capacity, and if it crosses the size threshold into a big enough
1998 // capacity, insert a free list node for it.
1999}2050}
20002051
2001fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {2052fn growTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
2002 const sym = self.local_symbols.items[text_block.local_sym_index];2053 const sym = self.local_symbols.items[text_block.local_sym_index];
2003 const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value;2054 const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value;
2004 const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*);2055 const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*);
2005 if (!need_realloc) return sym.st_value;2056 if (!need_realloc) return sym.st_value;
2006 return self.allocateTextBlock(text_block, new_block_size, alignment);2057 return self.allocateTextBlock(block_list, text_block, new_block_size, alignment);
2007}2058}
20082059
2009fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {2060fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
2010 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];2061 const phdr = &self.program_headers.items[block_list.phdr_index.?];
2011 const shdr = &self.sections.items[self.text_section_index.?];2062 const shdr = &self.sections.items[block_list.section_index.?];
2012 const new_block_ideal_capacity = padToIdeal(new_block_size);2063 const new_block_ideal_capacity = padToIdeal(new_block_size);
20132064
2014 // We use these to indicate our intention to update metadata, placing the new block,2065 // We use these to indicate our intention to update metadata, placing the new block,
...@@ -2023,8 +2074,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al...@@ -2023,8 +2074,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
2023 // The list is unordered. We'll just take the first thing that works.2074 // The list is unordered. We'll just take the first thing that works.
2024 const vaddr = blk: {2075 const vaddr = blk: {
2025 var i: usize = 0;2076 var i: usize = 0;
2026 while (i < self.text_block_free_list.items.len) {2077 while (i < block_list.free_list.items.len) {
2027 const big_block = self.text_block_free_list.items[i];2078 const big_block = block_list.free_list.items[i];
2028 // We now have a pointer to a live text block that has too much capacity.2079 // We now have a pointer to a live text block that has too much capacity.
2029 // Is it enough that we could fit this new text block?2080 // Is it enough that we could fit this new text block?
2030 const sym = self.local_symbols.items[big_block.local_sym_index];2081 const sym = self.local_symbols.items[big_block.local_sym_index];
...@@ -2039,7 +2090,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al...@@ -2039,7 +2090,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
2039 // should be deleted because the block that it points to has grown to take up2090 // should be deleted because the block that it points to has grown to take up
2040 // more of the extra capacity.2091 // more of the extra capacity.
2041 if (!big_block.freeListEligible(self.*)) {2092 if (!big_block.freeListEligible(self.*)) {
2042 _ = self.text_block_free_list.swapRemove(i);2093 _ = block_list.free_list.swapRemove(i);
2043 } else {2094 } else {
2044 i += 1;2095 i += 1;
2045 }2096 }
...@@ -2057,7 +2108,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al...@@ -2057,7 +2108,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
2057 free_list_removal = i;2108 free_list_removal = i;
2058 }2109 }
2059 break :blk new_start_vaddr;2110 break :blk new_start_vaddr;
2060 } else if (self.last_text_block) |last| {2111 } else if (block_list.last_block) |last| {
2061 const sym = self.local_symbols.items[last.local_sym_index];2112 const sym = self.local_symbols.items[last.local_sym_index];
2062 const ideal_capacity = padToIdeal(sym.st_size);2113 const ideal_capacity = padToIdeal(sym.st_size);
2063 const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity;2114 const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity;
...@@ -2077,7 +2128,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al...@@ -2077,7 +2128,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
2077 if (needed_size > text_capacity) {2128 if (needed_size > text_capacity) {
2078 // Must move the entire text section.2129 // Must move the entire text section.
2079 const new_offset = self.findFreeSpace(needed_size, 0x1000);2130 const new_offset = self.findFreeSpace(needed_size, 0x1000);
2080 const text_size = if (self.last_text_block) |last| blk: {2131 const text_size = if (block_list.last_block) |last| blk: {
2081 const sym = self.local_symbols.items[last.local_sym_index];2132 const sym = self.local_symbols.items[last.local_sym_index];
2082 break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr;2133 break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr;
2083 } else 0;2134 } else 0;
...@@ -2086,7 +2137,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al...@@ -2086,7 +2137,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
2086 shdr.sh_offset = new_offset;2137 shdr.sh_offset = new_offset;
2087 phdr.p_offset = new_offset;2138 phdr.p_offset = new_offset;
2088 }2139 }
2089 self.last_text_block = text_block;2140 block_list.last_block = text_block;
20902141
2091 shdr.sh_size = needed_size;2142 shdr.sh_size = needed_size;
2092 phdr.p_memsz = needed_size;2143 phdr.p_memsz = needed_size;
...@@ -2124,11 +2175,19 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al...@@ -2124,11 +2175,19 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
2124 text_block.next = null;2175 text_block.next = null;
2125 }2176 }
2126 if (free_list_removal) |i| {2177 if (free_list_removal) |i| {
2127 _ = self.text_block_free_list.swapRemove(i);2178 _ = block_list.free_list.swapRemove(i);
2128 }2179 }
2129 return vaddr;2180 return vaddr;
2130}2181}
21312182
2183/// Get the block list corresponding to a specific decl
2184/// For example, if the decl is a function, it returns the list of the section .text
2185fn getDeclBlockList(self: *Elf, decl: *const Module.Decl) *TextBlockList {
2186 // const is_fn = decl.val.tag() == .function;
2187 const is_fn = decl.ty.zigTypeTag() == .Fn;
2188 return if (is_fn) &self.text_block_list else &self.rodata_block_list;
2189}
2190
2132pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {2191pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
2133 if (self.llvm_object) |_| return;2192 if (self.llvm_object) |_| return;
21342193
...@@ -2172,8 +2231,10 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {...@@ -2172,8 +2231,10 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
2172 if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl);2231 if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl);
2173 }2232 }
21742233
2234 const block_list = self.getDeclBlockList(decl);
2235
2175 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.2236 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
2176 self.freeTextBlock(&decl.link.elf);2237 self.freeTextBlock(block_list, &decl.link.elf);
2177 if (decl.link.elf.local_sym_index != 0) {2238 if (decl.link.elf.local_sym_index != 0) {
2178 self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {};2239 self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {};
2179 self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};2240 self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};
...@@ -2216,6 +2277,8 @@ fn deinitRelocs(gpa: Allocator, table: *File.DbgInfoTypeRelocsTable) void {...@@ -2216,6 +2277,8 @@ fn deinitRelocs(gpa: Allocator, table: *File.DbgInfoTypeRelocsTable) void {
2216fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8) !*elf.Elf64_Sym {2277fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8) !*elf.Elf64_Sym {
2217 const required_alignment = decl.ty.abiAlignment(self.base.options.target);2278 const required_alignment = decl.ty.abiAlignment(self.base.options.target);
22182279
2280 const block_list = self.getDeclBlockList(decl);
2281
2219 assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes()2282 assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes()
2220 const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index];2283 const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index];
2221 if (local_sym.st_size != 0) {2284 if (local_sym.st_size != 0) {
...@@ -2223,7 +2286,7 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8...@@ -2223,7 +2286,7 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8
2223 const need_realloc = code.len > capacity or2286 const need_realloc = code.len > capacity or
2224 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);2287 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
2225 if (need_realloc) {2288 if (need_realloc) {
2226 const vaddr = try self.growTextBlock(&decl.link.elf, code.len, required_alignment);2289 const vaddr = try self.growTextBlock(block_list, &decl.link.elf, code.len, required_alignment);
2227 log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl.name, local_sym.st_value, vaddr });2290 log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl.name, local_sym.st_value, vaddr });
2228 if (vaddr != local_sym.st_value) {2291 if (vaddr != local_sym.st_value) {
2229 local_sym.st_value = vaddr;2292 local_sym.st_value = vaddr;
...@@ -2233,27 +2296,28 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8...@@ -2233,27 +2296,28 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8
2233 try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);2296 try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);
2234 }2297 }
2235 } else if (code.len < local_sym.st_size) {2298 } else if (code.len < local_sym.st_size) {
2236 self.shrinkTextBlock(&decl.link.elf, code.len);2299 self.shrinkTextBlock(block_list, &decl.link.elf, code.len);
2237 }2300 }
2238 local_sym.st_size = code.len;2301 local_sym.st_size = code.len;
2239 local_sym.st_name = try self.updateString(local_sym.st_name, mem.sliceTo(decl.name, 0));2302 local_sym.st_name = try self.updateString(local_sym.st_name, mem.sliceTo(decl.name, 0));
2240 local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits;2303 local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits;
2241 local_sym.st_other = 0;2304 local_sym.st_other = 0;
2242 local_sym.st_shndx = self.text_section_index.?;2305 local_sym.st_shndx = block_list.section_index.?;
2243 // TODO this write could be avoided if no fields of the symbol were changed.2306 // TODO this write could be avoided if no fields of the symbol were changed.
2244 try self.writeSymbol(decl.link.elf.local_sym_index);2307 try self.writeSymbol(decl.link.elf.local_sym_index);
2245 } else {2308 } else {
2246 const decl_name = mem.sliceTo(decl.name, 0);2309 const decl_name = mem.sliceTo(decl.name, 0);
2247 const name_str_index = try self.makeString(decl_name);2310 const name_str_index = try self.makeString(decl_name);
2248 const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment);2311 const vaddr = try self.allocateTextBlock(block_list, &decl.link.elf, code.len, required_alignment);
2312 errdefer self.freeTextBlock(block_list, &decl.link.elf);
2249 log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, vaddr });2313 log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, vaddr });
2250 errdefer self.freeTextBlock(&decl.link.elf);2314 errdefer self.freeTextBlock(block_list, &decl.link.elf);
22512315
2252 local_sym.* = .{2316 local_sym.* = .{
2253 .st_name = name_str_index,2317 .st_name = name_str_index,
2254 .st_info = (elf.STB_LOCAL << 4) | stt_bits,2318 .st_info = (elf.STB_LOCAL << 4) | stt_bits,
2255 .st_other = 0,2319 .st_other = 0,
2256 .st_shndx = self.text_section_index.?,2320 .st_shndx = block_list.section_index.?,
2257 .st_value = vaddr,2321 .st_value = vaddr,
2258 .st_size = code.len,2322 .st_size = code.len,
2259 };2323 };
...@@ -2263,8 +2327,8 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8...@@ -2263,8 +2327,8 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8
2263 try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);2327 try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);
2264 }2328 }
22652329
2266 const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr;2330 const section_offset = local_sym.st_value - self.program_headers.items[block_list.phdr_index.?].p_vaddr;
2267 const file_offset = self.sections.items[self.text_section_index.?].sh_offset + section_offset;2331 const file_offset = self.sections.items[block_list.section_index.?].sh_offset + section_offset;
2268 try self.base.file.?.pwriteAll(code, file_offset);2332 try self.base.file.?.pwriteAll(code, file_offset);
22692333
2270 return local_sym;2334 return local_sym;
...@@ -2772,6 +2836,8 @@ pub fn updateDeclExports(...@@ -2772,6 +2836,8 @@ pub fn updateDeclExports(
2772 if (decl.link.elf.local_sym_index == 0) return;2836 if (decl.link.elf.local_sym_index == 0) return;
2773 const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];2837 const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];
27742838
2839 const block_list = self.getDeclBlockList(decl);
2840
2775 for (exports) |exp| {2841 for (exports) |exp| {
2776 if (exp.options.section) |section_name| {2842 if (exp.options.section) |section_name| {
2777 if (!mem.eql(u8, section_name, ".text")) {2843 if (!mem.eql(u8, section_name, ".text")) {
...@@ -2808,7 +2874,7 @@ pub fn updateDeclExports(...@@ -2808,7 +2874,7 @@ pub fn updateDeclExports(
2808 .st_name = try self.updateString(sym.st_name, exp.options.name),2874 .st_name = try self.updateString(sym.st_name, exp.options.name),
2809 .st_info = (stb_bits << 4) | stt_bits,2875 .st_info = (stb_bits << 4) | stt_bits,
2810 .st_other = 0,2876 .st_other = 0,
2811 .st_shndx = self.text_section_index.?,2877 .st_shndx = block_list.section_index.?,
2812 .st_value = decl_sym.st_value,2878 .st_value = decl_sym.st_value,
2813 .st_size = decl_sym.st_size,2879 .st_size = decl_sym.st_size,
2814 };2880 };
...@@ -2822,7 +2888,7 @@ pub fn updateDeclExports(...@@ -2822,7 +2888,7 @@ pub fn updateDeclExports(
2822 .st_name = name,2888 .st_name = name,
2823 .st_info = (stb_bits << 4) | stt_bits,2889 .st_info = (stb_bits << 4) | stt_bits,
2824 .st_other = 0,2890 .st_other = 0,
2825 .st_shndx = self.text_section_index.?,2891 .st_shndx = block_list.section_index.?,
2826 .st_value = decl_sym.st_value,2892 .st_value = decl_sym.st_value,
2827 .st_size = decl_sym.st_size,2893 .st_size = decl_sym.st_size,
2828 };2894 };