git: 8f06d9b09b05 - main - www/deno: map deno compile payload instead of copying it
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 04 Oct 2026 01:21:05 UTC
The branch main has been updated by delphij:
URL: https://cgit.FreeBSD.org/ports/commit/?id=8f06d9b09b054fb3bfc78453e49890cdeecd9bd9
commit 8f06d9b09b054fb3bfc78453e49890cdeecd9bd9
Author: Xin LI <delphij@FreeBSD.org>
AuthorDate: 2026-10-04 01:16:05 +0000
Commit: Xin LI <delphij@FreeBSD.org>
CommitDate: 2026-10-04 01:20:16 +0000
www/deno: map deno compile payload instead of copying it
Executables produced by `deno compile` read their embedded payload into
memory at startup on FreeBSD, so a 200 MB payload made a trivial app
start with 431 MB RSS instead of 48 MB. Map the payload section from
the executable instead, so it is paged in on demand like on other
platforms.
---
www/deno/Makefile | 2 +-
.../files/patch-cargo-crates_libsui-0.16.4_lib.rs | 348 ++++++++++++---------
2 files changed, 201 insertions(+), 149 deletions(-)
diff --git a/www/deno/Makefile b/www/deno/Makefile
index 44888a63b746..c77924498f2f 100644
--- a/www/deno/Makefile
+++ b/www/deno/Makefile
@@ -1,7 +1,7 @@
PORTNAME= deno
DISTVERSIONPREFIX= v
DISTVERSION= 2.9.7
-PORTREVISION= 1
+PORTREVISION= 2
CATEGORIES= www
MAINTAINER= ports@FreeBSD.org
diff --git a/www/deno/files/patch-cargo-crates_libsui-0.16.4_lib.rs b/www/deno/files/patch-cargo-crates_libsui-0.16.4_lib.rs
index 86682084421e..6b40d6be1706 100644
--- a/www/deno/files/patch-cargo-crates_libsui-0.16.4_lib.rs
+++ b/www/deno/files/patch-cargo-crates_libsui-0.16.4_lib.rs
@@ -1,163 +1,186 @@
-libc does not export PT_NOTE for FreeBSD.
-
FreeBSD's kernel only executes binaries whose program headers are in the
first page, so the relocated program header table produced by
Elf::append() makes `deno compile` output fail with ENOEXEC. For
-executables, append the payload as a non-allocated .note.sui section and
-read it back from the executable file at runtime. Shared libraries
-(desktop mode's libdenort.so) keep the upstream layout, which rtld handles.
+executables, keep the program headers and add the payload only as a
+non-allocated .note.sui section, which find_section() maps from the
+executable file at runtime. Shared libraries (desktop mode's
+libdenort.so) keep the upstream layout, which rtld handles. Also define
+PT_NOTE locally, as libc does not export it for FreeBSD.
--- cargo-crates/libsui-0.16.4/lib.rs.orig 2006-07-24 01:21:28 UTC
+++ cargo-crates/libsui-0.16.4/lib.rs
-@@ -1270,6 +1270,25 @@ impl<'a> Elf<'a> {
- return Err(Error::InvalidObject("Invalid program header table"));
- }
-
-+ // The FreeBSD kernel refuses to execute binaries whose program
-+ // headers are not within the first page. For anything it loads
-+ // itself (ET_EXEC, or a PIE with PT_INTERP), leave the program headers
-+ // in place and append the note as a non-allocated section, which the
-+ // runtime reads back from the executable file. Shared libraries are
-+ // mapped by rtld, which copes with relocated program headers.
-+ const ELFOSABI_FREEBSD: u8 = 9;
-+ const ET_EXEC: u16 = 2;
+@@ -1187,6 +1187,11 @@ impl<'a> Elf<'a> {
+ /// 3. Repoint `e_phoff`/`e_phnum` (and `PT_PHDR`, if present) at the new
+ /// table. The section header table is never touched, so relocations,
+ /// `.relr.dyn`, and everything else survive unchanged.
++ ///
++ /// FreeBSD executables are the exception: the kernel refuses to run them
++ /// unless the program headers lie within the first page, so they keep
++ /// their program headers and the note is only added as a non-allocated
++ /// section, which `find_section` reads back from the executable file.
+ pub fn append<W: Write>(
+ &self,
+ name: &str,
+@@ -1196,10 +1201,13 @@ impl<'a> Elf<'a> {
+ const PAGE: usize = 0x1000;
+ // Program/segment header type and flag constants (ELF64).
+ const PT_LOAD: u32 = 1;
+ const PT_INTERP: u32 = 3;
-+ if data[7] == ELFOSABI_FREEBSD
-+ && (r16(&data[0x10..0x12]) == ET_EXEC
-+ || (0..e_phnum).any(|i| {
-+ let off = e_phoff + i * e_phentsize;
-+ r32(&data[off..off + 4]) == PT_INTERP
-+ }))
-+ {
-+ return self.append_note_section(name, sectdata, writer);
-+ }
-+
- // Scan existing program headers: find the highest mapped virtual
- // address (so the note lands above everything), the PT_PHDR entry, and
+ const PT_NOTE: u32 = 4;
+ const PT_PHDR: u32 = 6;
+ const PF_R: u32 = 4;
+ const PHENTSIZE64: usize = 56;
++ const ET_EXEC: u16 = 2;
++ const ELFOSABI_FREEBSD: u8 = 9;
+
+ let data = self.data;
+ if data.len() < 64 || data[0..4] != *b"\x7fELF" {
+@@ -1275,6 +1283,7 @@ impl<'a> Elf<'a> {
// the first PT_LOAD's `p_vaddr - p_offset` bias.
-@@ -1505,12 +1524,120 @@ impl<'a> Elf<'a> {
- writer.write_all(&out)?;
- Ok(())
- }
-+
-+ /// Append `sectdata` as a non-allocated `.note.sui` section, touching
-+ /// only the section header table.
-+ fn append_note_section<W: Write>(
-+ &self,
-+ name: &str,
-+ sectdata: &[u8],
-+ writer: &mut W,
-+ ) -> Result<(), Error> {
-+ const SHENTSIZE64: usize = 64;
-+ const SHT_NOTE: u32 = 7;
+ let mut max_vaddr_end = 0u64;
+ let mut pt_phdr_index = None;
++ let mut has_interp = false;
+ let mut first_load_bias: Option<i64> = None;
+ for i in 0..e_phnum {
+ let off = e_phoff + i * e_phentsize;
+@@ -1291,6 +1300,7 @@ impl<'a> Elf<'a> {
+ first_load_bias = Some(p_vaddr as i64 - p_offset as i64);
+ }
+ }
++ PT_INTERP => has_interp = true,
+ PT_PHDR => pt_phdr_index = Some(i),
+ _ => {}
+ }
+@@ -1300,6 +1310,14 @@ impl<'a> Elf<'a> {
+ }
+ let first_load_bias = first_load_bias.unwrap_or(0);
+
++ // The FreeBSD kernel only executes binaries whose program headers lie
++ // within the first page (see sys/kern/imgact_elf.c), so leave them in
++ // place for anything it loads itself (ET_EXEC, or a PIE with
++ // PT_INTERP). Shared libraries are mapped by rtld, which copes with a
++ // relocated program header table.
++ let keep_phdrs =
++ data[7] == ELFOSABI_FREEBSD && (r16(&data[0x10..0x12]) == ET_EXEC || has_interp);
+
-+ let data = self.data;
-+ let le = data[5] == 1;
-+ let r16 = |b: &[u8]| -> u16 {
-+ let a = [b[0], b[1]];
-+ if le {
-+ u16::from_le_bytes(a)
-+ } else {
-+ u16::from_be_bytes(a)
-+ }
-+ };
-+ let r64 = |b: &[u8]| -> u64 {
-+ let mut a = [0u8; 8];
-+ a.copy_from_slice(&b[..8]);
-+ if le {
-+ u64::from_le_bytes(a)
-+ } else {
-+ u64::from_be_bytes(a)
-+ }
-+ };
-+ let w16 = |b: &mut [u8], v: u16| {
-+ let a = if le { v.to_le_bytes() } else { v.to_be_bytes() };
-+ b[..2].copy_from_slice(&a);
-+ };
-+ let w32 = |b: &mut [u8], v: u32| {
-+ let a = if le { v.to_le_bytes() } else { v.to_be_bytes() };
-+ b[..4].copy_from_slice(&a);
-+ };
-+ let w64 = |b: &mut [u8], v: u64| {
-+ let a = if le { v.to_le_bytes() } else { v.to_be_bytes() };
-+ b[..8].copy_from_slice(&a);
+ let note = build_elf_note_payload(name, sectdata);
+
+ // Layout of the appended region, all within one new PT_LOAD:
+@@ -1385,8 +1403,14 @@ impl<'a> Elf<'a> {
+ ));
+
+ let mut out = data.to_vec();
+- out.resize(new_phoff, 0);
+- out.extend_from_slice(&table);
++ let note_file_off = if keep_phdrs {
++ // Only the section added below refers to the note.
++ align_up(out.len(), 4)
++ } else {
++ out.resize(new_phoff, 0);
++ out.extend_from_slice(&table);
++ note_file_off
+ };
-+
-+ let e_shoff = r64(&data[0x28..0x30]) as usize;
-+ let e_shentsize = r16(&data[0x3a..0x3c]) as usize;
-+ let e_shnum = r16(&data[0x3c..0x3e]) as usize;
-+ let e_shstrndx = r16(&data[0x3e..0x40]) as usize;
-+ if e_shoff == 0
-+ || e_shentsize < SHENTSIZE64
-+ || e_shnum == 0
-+ || e_shnum >= 0xff00
-+ || e_shstrndx == 0
-+ || e_shstrndx >= e_shnum
-+ || e_shoff
-+ .checked_add(e_shnum * e_shentsize)
-+ .map(|end| end > data.len())
-+ .unwrap_or(true)
-+ {
-+ return Err(Error::InvalidObject("Invalid section header table"));
-+ }
-+ let hdr = &data[e_shoff + e_shstrndx * e_shentsize..];
-+ let shstr_off = r64(&hdr[24..32]) as usize;
-+ let shstr_size = r64(&hdr[32..40]) as usize;
-+ if shstr_off
-+ .checked_add(shstr_size)
-+ .map(|end| end > data.len())
-+ .unwrap_or(true)
-+ {
-+ return Err(Error::InvalidObject("Invalid section name table"));
+ out.resize(note_file_off, 0);
+ out.extend_from_slice(¬e);
+
+@@ -1431,13 +1455,19 @@ impl<'a> Elf<'a> {
+ .unwrap_or(false)
+ });
+
++ if keep_phdrs && shstr_range.is_none() {
++ return Err(Error::InvalidObject("No section header table for the note"));
+ }
+
-+ let note = build_elf_note_payload(name, sectdata);
-+ let mut out = data.to_vec();
-+ let note_off = align_up(out.len(), 4);
-+ out.resize(note_off, 0);
-+ out.extend_from_slice(¬e);
-+
-+ let mut new_shstr = data[shstr_off..shstr_off + shstr_size].to_vec();
-+ let note_name_index = new_shstr.len() as u32;
-+ new_shstr.extend_from_slice(b".note.sui\0");
-+ let shstr_new_off = out.len();
-+ out.extend_from_slice(&new_shstr);
-+ let sht_new_off = align_up(out.len(), 8);
-+ out.resize(sht_new_off, 0);
-+
-+ let mut sht = data[e_shoff..e_shoff + e_shnum * e_shentsize].to_vec();
-+ {
-+ let e = &mut sht[e_shstrndx * e_shentsize..];
-+ w64(&mut e[24..32], shstr_new_off as u64);
-+ w64(&mut e[32..40], new_shstr.len() as u64);
+ if let Some((shstr_off, shstr_size)) = shstr_range {
+ // Relocate and grow .shstrtab so it carries the new section names.
+ let mut new_shstr = data[shstr_off..shstr_off + shstr_size].to_vec();
+ let note_name_index = new_shstr.len() as u32;
+ new_shstr.extend_from_slice(b".note.sui\0");
+ let phdr_name_index = new_shstr.len() as u32;
+- new_shstr.extend_from_slice(b".sui.phdrs\0");
++ if !keep_phdrs {
++ new_shstr.extend_from_slice(b".sui.phdrs\0");
++ }
+
+ // .shstrtab and the section header table are non-allocated
+ // metadata: place them past the note, outside the new PT_LOAD.
+@@ -1467,24 +1497,30 @@ impl<'a> Elf<'a> {
+ // of the note: BFD `strip` parses SHT_NOTE contents, so folding the
+ // (non-note) program header bytes into `.note.sui` corrupts the note
+ // on strip and loses it.
+- let mut phdr_sh = vec![0u8; e_shentsize];
+- w32(&mut phdr_sh[0..4], phdr_name_index); // sh_name
+- w32(&mut phdr_sh[4..8], SHT_PROGBITS); // sh_type
+- w64(&mut phdr_sh[8..16], SHF_ALLOC); // sh_flags
+- w64(&mut phdr_sh[16..24], load_vaddr); // sh_addr
+- w64(&mut phdr_sh[24..32], new_phoff as u64); // sh_offset
+- w64(&mut phdr_sh[32..40], (note_file_off - new_phoff) as u64); // sh_size
+- w64(&mut phdr_sh[48..56], PAGE as u64); // sh_addralign
+- sht.extend_from_slice(&phdr_sh);
++ if !keep_phdrs {
++ let mut phdr_sh = vec![0u8; e_shentsize];
++ w32(&mut phdr_sh[0..4], phdr_name_index); // sh_name
++ w32(&mut phdr_sh[4..8], SHT_PROGBITS); // sh_type
++ w64(&mut phdr_sh[8..16], SHF_ALLOC); // sh_flags
++ w64(&mut phdr_sh[16..24], load_vaddr); // sh_addr
++ w64(&mut phdr_sh[24..32], new_phoff as u64); // sh_offset
++ w64(&mut phdr_sh[32..40], (note_file_off - new_phoff) as u64); // sh_size
++ w64(&mut phdr_sh[48..56], PAGE as u64); // sh_addralign
++ sht.extend_from_slice(&phdr_sh);
++ }
+
+ // The allocated SHT_NOTE section keeps the note reachable through the
+ // section table (what BFD-based tools rebuild from); the runtime
+- // reads it through its PT_NOTE program header regardless.
++ // reads it through its PT_NOTE program header regardless. Without
++ // a PT_NOTE (`keep_phdrs`), the section is not mapped and the
++ // runtime reads it from the file instead.
+ let mut note_sh = vec![0u8; e_shentsize];
+ w32(&mut note_sh[0..4], note_name_index); // sh_name
+ w32(&mut note_sh[4..8], SHT_NOTE); // sh_type
+- w64(&mut note_sh[8..16], SHF_ALLOC); // sh_flags
+- w64(&mut note_sh[16..24], note_vaddr); // sh_addr
++ if !keep_phdrs {
++ w64(&mut note_sh[8..16], SHF_ALLOC); // sh_flags
++ w64(&mut note_sh[16..24], note_vaddr); // sh_addr
++ }
+ w64(&mut note_sh[24..32], note_file_off as u64); // sh_offset
+ w64(&mut note_sh[32..40], note.len() as u64); // sh_size
+ w64(&mut note_sh[48..56], 4); // sh_addralign
+@@ -1492,13 +1528,15 @@ impl<'a> Elf<'a> {
+ out.extend_from_slice(&sht);
+
+ new_shoff = sht_new_off as u64;
+- new_shnum = (e_shnum + 2) as u16;
++ new_shnum = (e_shnum + if keep_phdrs { 1 } else { 2 }) as u16;
+ }
+
+ // Point the ELF header at the relocated, enlarged program header table
+ // (and section header table, if one was added).
+- w64(&mut out[0x20..0x28], new_phoff as u64);
+- w16(&mut out[0x38..0x3a], new_phnum as u16);
++ if !keep_phdrs {
++ w64(&mut out[0x20..0x28], new_phoff as u64);
++ w16(&mut out[0x38..0x3a], new_phnum as u16);
+ }
-+ let mut note_sh = vec![0u8; e_shentsize];
-+ w32(&mut note_sh[0..4], note_name_index); // sh_name
-+ w32(&mut note_sh[4..8], SHT_NOTE); // sh_type
-+ w64(&mut note_sh[24..32], note_off as u64); // sh_offset
-+ w64(&mut note_sh[32..40], note.len() as u64); // sh_size
-+ w64(&mut note_sh[48..56], 4); // sh_addralign
-+ sht.extend_from_slice(¬e_sh);
-+ out.extend_from_slice(&sht);
-+
-+ w64(&mut out[0x28..0x30], sht_new_off as u64);
-+ w16(&mut out[0x3c..0x3e], (e_shnum + 1) as u16);
-+
-+ writer.write_all(&out)?;
-+ Ok(())
-+ }
- }
+ w64(&mut out[0x28..0x30], new_shoff);
+ w16(&mut out[0x3c..0x3e], new_shnum);
+
+@@ -1509,9 +1547,12 @@ mod elf {
#[cfg(all(unix, not(target_vendor = "apple")))]
mod elf {
- use libc::{dl_iterate_phdr, dl_phdr_info, Elf64_Phdr, PT_NOTE};
+ use libc::{dl_iterate_phdr, dl_phdr_info, Elf64_Phdr};
use std::os::raw::{c_int, c_void};
-+ const PT_NOTE: u32 = 4;
++ // Not exported by the libc crate on every platform (e.g. FreeBSD).
++ const PT_NOTE: u32 = 4;
++
unsafe extern "C" fn sui_dl_iterate_phdr_callback(
info: *mut dl_phdr_info,
-@@ -1564,7 +1691,61 @@ mod elf {
+ _size: usize,
+@@ -1564,7 +1605,90 @@ mod elf {
);
}
@@ -170,11 +193,12 @@ read it back from the executable file at runtime. Shared libraries
+ section
+ }
+
-+ /// Find a section appended by `Elf::append_note_section`, which is not
-+ /// mapped into memory, by reading the executable file.
++ /// Find a section that `Elf::append` stored without a `PT_LOAD` (see
++ /// `keep_phdrs`) by mapping it from the executable file.
+ #[cfg(target_os = "freebsd")]
+ fn find_section_in_exe_file(name: &str) -> std::io::Result<Option<&'static [u8]>> {
+ use std::os::unix::fs::FileExt;
++ use std::os::unix::io::AsRawFd;
+ const SHT_NOTE: u32 = 7;
+ const SHF_ALLOC: u64 = 2;
+
@@ -205,16 +229,44 @@ read it back from the executable file at runtime. Shared libraries
+ if r32(&sh[4..8]) != SHT_NOTE || r64(&sh[8..16]) & SHF_ALLOC != 0 {
+ continue;
+ }
-+ let segment = read(r64(&sh[24..32]), r64(&sh[32..40]) as usize)?;
-+ let Some(found) = find_in_note_segment(&segment, 4, name) else {
++ let offset = r64(&sh[24..32]) as usize;
++ let len = r64(&sh[32..40]) as usize;
++ if len == 0 {
+ continue;
++ }
++ // Map the section rather than reading it, so that, as with a
++ // PT_LOAD, the (potentially large) payload is paged in on demand.
++ // SAFETY: sysconf is always safe to call for _SC_PAGESIZE.
++ let page = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
++ let map_offset = offset & !(page - 1);
++ let map_len = len + (offset - map_offset);
++ // SAFETY: a fresh read-only private mapping of the file; the
++ // kernel validates the range.
++ let ptr = unsafe {
++ libc::mmap(
++ std::ptr::null_mut(),
++ map_len,
++ libc::PROT_READ,
++ libc::MAP_PRIVATE,
++ file.as_raw_fd(),
++ map_offset as libc::off_t,
++ )
+ };
-+ let start = found.as_ptr() as usize - segment.as_ptr() as usize;
-+ let len = found.len();
-+ // Leaked deliberately: callers expect data that lives for the
-+ // rest of the process, like the mapped notes found above.
-+ let segment: &'static [u8] = Box::leak(segment.into_boxed_slice());
-+ return Ok(Some(&segment[start..start + len]));
++ if ptr == libc::MAP_FAILED {
++ return Err(std::io::Error::last_os_error());
++ }
++ // SAFETY: the mapping covers `offset..offset + len` of the file.
++ let segment: &'static [u8] = unsafe {
++ std::slice::from_raw_parts((ptr as *const u8).add(offset - map_offset), len)
++ };
++ if let Some(section_data) = find_in_note_segment(segment, 4, name) {
++ // The mapping is kept for the rest of the process, like the
++ // mapped notes `find_section_in_phdr_info` returns.
++ return Ok(Some(section_data));
++ }
++ // SAFETY: `ptr`/`map_len` describe the mapping created above, and
++ // nothing borrows from it.
++ unsafe { libc::munmap(ptr, map_len) };
+ }
+ Ok(None)
}