Skip to content

Commit 03e9799

Browse files
authored
Don't pad .text to page size for pulley (#10285)
* Don't pad .text to page size for pulley When targeting pulley we aren't directly emitting executable code in the .text section and we don't have a good idea of the true target page size so we end up with ELF files that can have a significant amount of extra padding around the .text section with no benefit to the consumer. The change here aligns with the already present section flag SH_WASMTIME_NOT_EXECUTED. Padding elimination for the .rodata.wasm section is already handled by the presence/absence of the memory-init-on-cow configuration. For a basic wasip1 hello-world rust program with the combination of this patch and `-O memory-init-cow=n` I saw a reduction in the compiled wasm ELF from 421KB to 189KB with the sections no longer showing as being padded out significantly: ``` $ objdump --section-headers target/wasm32-wasip1/release/hello-wasm-world-0x00.cwasm target/wasm32-wasip1/release/hello-wasm-world-0x00.cwasm: file format elf64-littleriscv Sections: Idx Name Size VMA Type 0 00000000 0000000000000000 1 .wasmtime.engine 00000353 0000000000000000 DATA 2 .wasmtime.bti 00000001 0000000000000000 DATA 3 .text 00011bdc 0000000000000000 4 .wasmtime.addrmap 00011c5c 0000000000000000 DATA 5 .wasmtime.traps 00000ae0 0000000000000000 DATA 6 .rodata.wasm 000019e8 0000000000000000 DATA 7 .name.wasm 000027a6 0000000000000000 DATA 8 .wasmtime.info 000010f9 0000000000000000 DATA 9 .symtab 00001788 0000000000000000 10 .strtab 000040f0 0000000000000000 11 .shstrtab 00000089 0000000000000000 ``` * code_memory: don't unpublish non-published memory For the case that we construct a CodeMemory with a custom_code_memory implementation but we don't end up publishing memory, do not try to unpublish the memory. This could happen in a few cases: - The .text didn't require being made executable - There's an error or other circumstances cause the CodeMemory to be dropped prior to publish being called. Within the context of the .text size optimizations for pulley, this caused CI failures for a default pulley target as the errant unpublish was now being called on non-aligned memory. Prior to the .text optimizations there was still an mprotect being called to change bits on the .text region which just happened to be benign. * In addition to published, check needs_executable before custom unpublishing Changing the placement of published or introducing new state could be other ways of addressing the problem of doing a custom unpublish but those approaches would potentially create other issues with avoiding duplicate relocations. Given where this code would be used and the ability for the `custom_code_memory` to provide their own protections, this seems very much so Good Enough and gets the tests passing again while providing more reasonable behavior for user code.
1 parent 5b9e876 commit 03e9799

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

crates/cranelift/src/obj.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ use wasmtime_environ::{Compiler, TripleExt, Unsigned};
3030

3131
const TEXT_SECTION_NAME: &[u8] = b".text";
3232

33+
fn text_align(compiler: &dyn Compiler) -> u64 {
34+
// text pages will not be made executable with pulley, so the section
35+
// doesn't need to be padded out to page alignment boundaries.
36+
if compiler.triple().is_pulley() {
37+
0x1
38+
} else {
39+
compiler.page_size_align()
40+
}
41+
}
42+
3343
/// A helper structure used to assemble the final text section of an executable,
3444
/// plus unwinding information and other related details.
3545
///
@@ -282,7 +292,7 @@ impl<'a> ModuleTextBuilder<'a> {
282292
let text = self.text.finish(&mut self.ctrl_plane);
283293
self.obj
284294
.section_mut(self.text_section)
285-
.set_data(text, self.compiler.page_size_align());
295+
.set_data(text, text_align(self.compiler));
286296

287297
// Append the unwind information for all our functions, if necessary.
288298
self.unwind_info
@@ -440,8 +450,7 @@ impl<'a> UnwindInfoBuilder<'a> {
440450
// This write will align the text section to a page boundary and then
441451
// return the offset at that point. This gives us the full size of the
442452
// text section at that point, after alignment.
443-
let text_section_size =
444-
obj.append_section_data(text_section, &[], compiler.page_size_align());
453+
let text_section_size = obj.append_section_data(text_section, &[], text_align(compiler));
445454

446455
if self.windows_xdata.len() > 0 {
447456
assert!(self.systemv_unwind_info.len() == 0);

crates/wasmtime/src/runtime/code_memory.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ impl Drop for CodeMemory {
4545
// If there is a custom code memory handler, restore the
4646
// original (non-executable) state of the memory.
4747
if let Some(mem) = self.custom_code_memory.as_ref() {
48-
let text = self.text();
49-
mem.unpublish_executable(text.as_ptr(), text.len())
50-
.expect("Executable memory unpublish failed");
48+
if self.published && self.needs_executable {
49+
let text = self.text();
50+
mem.unpublish_executable(text.as_ptr(), text.len())
51+
.expect("Executable memory unpublish failed");
52+
}
5153
}
5254

5355
// Drop the registrations before `self.mmap` since they (implicitly) refer to it.

0 commit comments

Comments
 (0)