From fa484d22d284248096900f1e6f8b809f45bd4b08 Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 20:57:06 +0900 Subject: [PATCH 01/10] short: shorten the shorter prestub --- scripts/static-pie-gen.py | 2 +- scripts/static-pie-prestub-amd64-shorter.asm | 5 ++--- scripts/static-pie-prestub-amd64-shorter.bin | Bin 98 -> 96 bytes scripts/static-pie-template-amd64-shorter.rs | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/static-pie-gen.py b/scripts/static-pie-gen.py index 64b72daf..61a2f886 100644 --- a/scripts/static-pie-gen.py +++ b/scripts/static-pie-gen.py @@ -68,7 +68,7 @@ sol = "".join(sol) # binary (raw) -code_raw_b91 = base91.encode(memory_bin[:-4], use_rle=True).decode('ascii') +code_raw_b91 = base91.encode(memory_bin, use_rle=True).decode('ascii') code_raw_b91_len = len(code_raw_b91) code_raw_b91 = '"' + code_raw_b91 + '"' diff --git a/scripts/static-pie-prestub-amd64-shorter.asm b/scripts/static-pie-prestub-amd64-shorter.asm index fed8872a..9886b386 100644 --- a/scripts/static-pie-prestub-amd64-shorter.asm +++ b/scripts/static-pie-prestub-amd64-shorter.asm @@ -78,9 +78,8 @@ _decode_zeros: ; Jump to entrypoint _jump_to_entrypoint: - mov eax, dword [rdi-4] - pop rcx - add rax, rcx + pop rax + add rax, qword [rdi-8] push rsp pop rcx call rax \ No newline at end of file diff --git a/scripts/static-pie-prestub-amd64-shorter.bin b/scripts/static-pie-prestub-amd64-shorter.bin index 1f12607d06b6d2421752c5870b665c1cdccd2696..7b5d9308a9d45d92a77b62a9348235a679031c83 100644 GIT binary patch delta 14 VcmYdFm=Mkx;lb?wBP8F1`z-N delta 16 XcmYdDnh?(2?fxgygYiU2 Date: Thu, 30 Nov 2023 21:17:52 +0900 Subject: [PATCH 02/10] short: update amd64_elf.rs --- src/platform/loader/amd64_elf.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/platform/loader/amd64_elf.rs b/src/platform/loader/amd64_elf.rs index 07ae8431..f8ff2bce 100644 --- a/src/platform/loader/amd64_elf.rs +++ b/src/platform/loader/amd64_elf.rs @@ -49,6 +49,8 @@ There are currently three files licensed under GPLv2+: #![allow(clippy::cmp_null)] +use core::mem::MaybeUninit; + // Dynamic section entry types const DT_RELA: u64 = 7; const DT_RELASZ: u64 = 8; @@ -78,14 +80,14 @@ pub unsafe extern "sysv64" fn relocate( ) { let mut ptr_dyn: *const Elf64Dyn = addr_dynamic_section as *const Elf64Dyn; let mut ptr_rela = 0; - let mut relasz = 0; - let mut relaent = 0; + let mut relasz = MaybeUninit::::uninit(); + let mut relaent = MaybeUninit::::uninit(); loop { match (*ptr_dyn).d_tag { 0 => { break; } DT_RELA => { ptr_rela = addr_image_base + (*ptr_dyn).d_val_or_ptr; }, - DT_RELASZ => { relasz = (*ptr_dyn).d_val_or_ptr; }, - DT_RELAENT => { relaent = (*ptr_dyn).d_val_or_ptr; }, + DT_RELASZ => { relasz.write((*ptr_dyn).d_val_or_ptr); }, + DT_RELAENT => { relaent.write((*ptr_dyn).d_val_or_ptr); }, _ => () } ptr_dyn = ptr_dyn.add(1); @@ -99,9 +101,9 @@ pub unsafe extern "sysv64" fn relocate( if ptr_rela == 0 { return; } - relasz += ptr_rela; + relasz.write(relasz.assume_init() + ptr_rela); - while ptr_rela < relasz { + while ptr_rela < relasz.assume_init() { let pst_rela = ptr_rela as *mut Elf64Rela; let ul_offset = (*pst_rela).r_offset; let ul_info = (*pst_rela).r_info; @@ -116,6 +118,6 @@ pub unsafe extern "sysv64" fn relocate( /* not implemented */ panic!(); } - ptr_rela += relaent; + ptr_rela += relaent.assume_init(); } } \ No newline at end of file From dd8c4f39649cd6a36e46abd9af1088d02253b57d Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 21:28:42 +0900 Subject: [PATCH 03/10] short: prevent potential aberrant shortening --- scripts/static-pie-gen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/static-pie-gen.py b/scripts/static-pie-gen.py index 61a2f886..1508a146 100644 --- a/scripts/static-pie-gen.py +++ b/scripts/static-pie-gen.py @@ -121,7 +121,7 @@ # template template_candidates = [template_path] -if lang_name == "Rust" and "x86_64" in target_name and "short" in template_path: +if lang_name == "Rust" and "x86_64" in target_name and "short" in template_path and len(memory_bin) <= 4096: template_candidates.append(template_path.replace("short", "shorter")) out = None From 811c82113fbd9fc86240e6939cba512a4d75fff7 Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 21:30:29 +0900 Subject: [PATCH 04/10] short add Visual Studio Code task for short --- .vscode/tasks.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 7e68140f..61a5980d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -35,6 +35,14 @@ "$rustc" ], }, + { + "label": "build-release-amd64-rs-short-submit", + "type": "shell", + "command": "mkdir -p ./target/x86_64-unknown-linux-gnu-short/release; ./release-rs.sh --features short > ./target/x86_64-unknown-linux-gnu-short/release/loader.rs; code --reuse-window ./target/x86_64-unknown-linux-gnu-short/release/loader.rs", + "problemMatcher": [ + "$rustc" + ], + }, { "label": "build-release-i686-submit", "type": "shell", From 21dbb4d6124d25c7ed8e91937e7000930875cf6c Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 22:16:47 +0900 Subject: [PATCH 05/10] short: update mod.rs --- src/platform/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 5f2e0f30..46a3b091 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -45,9 +45,14 @@ pub fn init(platform_data_by_loader: usize) { } #[cfg(not(test))] pub fn try_exit() { - let pd = services::platform_data(); - if pd.env_id == services::ENV_ID_LINUX { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(all(target_arch = "x86_64", feature = "short")))] { + let pd = services::platform_data(); + if pd.env_id == services::ENV_ID_LINUX { + #[cfg(not(target_arch = "wasm32"))] + unsafe { os::linux::syscall::exit_group(services::get_exit_status() as usize); } + } + } + #[cfg(all(target_arch = "x86_64", feature = "short"))] { unsafe { os::linux::syscall::exit_group(services::get_exit_status() as usize); } } } From 38b70459e28c9e1518870959ce2f28cc89703f4a Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 22:22:17 +0900 Subject: [PATCH 06/10] short: synthesize PLATFORM_DATA in ELF (not stub) --- scripts/static-pie-gen.py | 4 +++- scripts/static-pie-prestub-amd64-shorter.asm | 20 ++----------------- scripts/static-pie-prestub-amd64-shorter.bin | Bin 96 -> 82 bytes scripts/static-pie-template-amd64-shorter.rs | 2 +- src/bin/codegen.rs | 8 +++++--- 5 files changed, 11 insertions(+), 23 deletions(-) diff --git a/scripts/static-pie-gen.py b/scripts/static-pie-gen.py index 1508a146..c0c43d63 100644 --- a/scripts/static-pie-gen.py +++ b/scripts/static-pie-gen.py @@ -68,7 +68,9 @@ sol = "".join(sol) # binary (raw) -code_raw_b91 = base91.encode(memory_bin, use_rle=True).decode('ascii') +code_raw = memory_bin[:-8] +code_raw += (len(code_raw) + 8 - loader_fdict['entrypoint_offset']).to_bytes(8, byteorder='little') +code_raw_b91 = base91.encode(code_raw, use_rle=True).decode('ascii') code_raw_b91_len = len(code_raw_b91) code_raw_b91 = '"' + code_raw_b91 + '"' diff --git a/scripts/static-pie-prestub-amd64-shorter.asm b/scripts/static-pie-prestub-amd64-shorter.asm index 9886b386..ea1c3201 100644 --- a/scripts/static-pie-prestub-amd64-shorter.asm +++ b/scripts/static-pie-prestub-amd64-shorter.asm @@ -11,11 +11,6 @@ BITS 64 ORG 0 section .text -; Align stack to 16 byte boundary -; [rsp+ 32, rsp+120): PLATFORM_DATA -; [rsp+ 0, rsp+ 32): (shadow space for win64 calling convention) - enter 56, 0 - ; svc_alloc_rwx for Linux _svc_alloc_rwx: push 9 @@ -34,15 +29,7 @@ _svc_alloc_rwx: syscall pop rsi ; restore rsi -; PLATFORM_DATA -_t: ; PLATFORM_DATA[32..39] = ptr_alloc_rwx - push rdx ; PLATFORM_DATA[24..31] = win_GetProcAddress - push rax ; PLATFORM_DATA[16..23] = win_kernel32 - push 1 ; PLATFORM_DATA[ 8..15] = env_flags (0=None, 1=ENV_FLAGS_LINUX_STYLE_CHKSTK) - push 2 ; PLATFORM_DATA[ 0.. 7] = env_id (1=Windows, 2=Linux) - ; Current state: rax = new buffer - push rax xchg rax, rdi ; rdi = new buffer ; Base91 decoder @@ -78,8 +65,5 @@ _decode_zeros: ; Jump to entrypoint _jump_to_entrypoint: - pop rax - add rax, qword [rdi-8] - push rsp - pop rcx - call rax \ No newline at end of file + sub rdi, qword [rdi-8] + jmp rdi \ No newline at end of file diff --git a/scripts/static-pie-prestub-amd64-shorter.bin b/scripts/static-pie-prestub-amd64-shorter.bin index 7b5d9308a9d45d92a77b62a9348235a679031c83..6ad336168204b5dc0e09ec66e023aeb43875b187 100644 GIT binary patch delta 39 vcmYcYlFH(YnCWVGGR*LQ7GvBd_ADjGsI32v5&W!i6IG4aJhbb7{C^Gr5Y-OR delta 30 lcmWGaU^!vIz%W6IJt!cHF^ef+qLdM5ga@33UJf diff --git a/scripts/static-pie-template-amd64-shorter.rs b/scripts/static-pie-template-amd64-shorter.rs index 70933ec1..ddfe621b 100644 --- a/scripts/static-pie-template-amd64-shorter.rs +++ b/scripts/static-pie-template-amd64-shorter.rs @@ -5,4 +5,4 @@ $$$$solution_src$$$$ } // SOLUTION END -#[no_link]extern crate std;#[no_mangle]unsafe fn _start(){std::arch::asm!(".quad 9958096a000038c8h,16aff3156c93145h,6a5a41226a07b25eh,50525e050f5841ffh,0b0974850026a016ah,99232cac0de0c11fh,0ac92c8fe16742572h,0aad0015bc06b242ch,0f77510c4f608e8c1h,48ff4fb60f92dfebh,58d5eb92aaf3cfffh,0d0ff5954f8470348h",in("rsi")r$$$$binary_raw_base91$$$$.as_ptr())} \ No newline at end of file +#[no_link]extern crate std;#[no_mangle]unsafe fn _start(){std::arch::asm!(".quad 56c931459958096ah,6a07b25e016aff31h,0f5841ff6a5a4122h,0e0c11fb097485e05h,74257299232cac0dh,6b242cac92c8fe16h,8e8c1aad0015bc0h,92dfebf77510c4f6h,0f3cfff48ff4fb60fh,0f87f2b48d5eb92aah,59391",in("rsi")r$$$$binary_raw_base91$$$$.as_ptr())} \ No newline at end of file diff --git a/src/bin/codegen.rs b/src/bin/codegen.rs index c18f0bc6..a3db1249 100644 --- a/src/bin/codegen.rs +++ b/src/bin/codegen.rs @@ -86,12 +86,14 @@ unsafe extern "win64" fn _start() -> ! { #[cfg(feature = "short")] asm!( "clc", // Not needed but packager wants it - "push rcx", // Align stack - "mov rbx, rcx", // Save PLATFORM_DATA table + "sub rsp, 80", // 16 + 80 = 96 = 16*6 -> stack alignment preserved + "push 1", // env_flags = 1 (ENV_FLAGS_LINUX_STYLE_CHKSTK) + "push 2", // env_id = 2 (ENV_ID_LINUX) "lea rdi, [rip + __ehdr_start]", "lea rsi, [rip + _DYNAMIC]", "call {0}", - "mov rdi, rbx", + "push rsp", + "pop rcx", "call {1}", // This won't return since on Linux we invoke SYS_exitgroup in binary sym loader::amd64_elf::relocate, sym _start_rust, From d68c1dba7442182a780620c7b332184310b91637 Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 22:26:06 +0900 Subject: [PATCH 07/10] short: shorten the shorter prestub --- scripts/static-pie-prestub-amd64-shorter.asm | 4 +--- scripts/static-pie-prestub-amd64-shorter.bin | 2 +- scripts/static-pie-template-amd64-shorter.rs | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/static-pie-prestub-amd64-shorter.asm b/scripts/static-pie-prestub-amd64-shorter.asm index ea1c3201..39878f3f 100644 --- a/scripts/static-pie-prestub-amd64-shorter.asm +++ b/scripts/static-pie-prestub-amd64-shorter.asm @@ -56,11 +56,9 @@ _decode_output: jnz _decode_output jmp _decode_loop _decode_zeros: - xchg eax, edx movzx ecx, byte [rdi-1] dec rdi - rep stosb - xchg eax, edx + rep stosb ; the fact we jumped to here ensures al=0 jmp _decode_loop_2 ; Jump to entrypoint diff --git a/scripts/static-pie-prestub-amd64-shorter.bin b/scripts/static-pie-prestub-amd64-shorter.bin index 6ad33616..d133d946 100644 --- a/scripts/static-pie-prestub-amd64-shorter.bin +++ b/scripts/static-pie-prestub-amd64-shorter.bin @@ -1 +1 @@ -j X™E1ÉV1ÿj^²j"AZjÿAX^H—°Áà ¬,#™r%tþÈ’¬,$kÀ[ЪÁèöÄu÷ëß’¶OÿHÿÏóª’ëÕH+øÿç \ No newline at end of file +j X™E1ÉV1ÿj^²j"AZjÿAX^H—°Áà ¬,#™r#tþÈ’¬,$kÀ[ЪÁèöÄu÷ë߶OÿHÿÏóªë×H+øÿç \ No newline at end of file diff --git a/scripts/static-pie-template-amd64-shorter.rs b/scripts/static-pie-template-amd64-shorter.rs index ddfe621b..4c6a8470 100644 --- a/scripts/static-pie-template-amd64-shorter.rs +++ b/scripts/static-pie-template-amd64-shorter.rs @@ -5,4 +5,4 @@ $$$$solution_src$$$$ } // SOLUTION END -#[no_link]extern crate std;#[no_mangle]unsafe fn _start(){std::arch::asm!(".quad 56c931459958096ah,6a07b25e016aff31h,0f5841ff6a5a4122h,0e0c11fb097485e05h,74257299232cac0dh,6b242cac92c8fe16h,8e8c1aad0015bc0h,92dfebf77510c4f6h,0f3cfff48ff4fb60fh,0f87f2b48d5eb92aah,59391",in("rsi")r$$$$binary_raw_base91$$$$.as_ptr())} \ No newline at end of file +#[no_link]extern crate std;#[no_mangle]unsafe fn _start(){std::arch::asm!(".quad 56c931459958096ah,6a07b25e016aff31h,0f5841ff6a5a4122h,0e0c11fb097485e05h,74237299232cac0dh,6b242cac92c8fe16h,8e8c1aad0015bc0h,0fdfebf77510c4f6h,0aaf3cfff48ff4fb6h,0e7fff87f2b48d7ebh",in("rsi")r$$$$binary_raw_base91$$$$.as_ptr())} \ No newline at end of file From 4bb0da78d61d8dcbdcfb57b8d2d03dd46f46324b Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 22:28:16 +0900 Subject: [PATCH 08/10] Update static-pie-prestub-amd64-shorter.asm Fix comment --- scripts/static-pie-prestub-amd64-shorter.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/static-pie-prestub-amd64-shorter.asm b/scripts/static-pie-prestub-amd64-shorter.asm index 39878f3f..895f6edc 100644 --- a/scripts/static-pie-prestub-amd64-shorter.asm +++ b/scripts/static-pie-prestub-amd64-shorter.asm @@ -34,7 +34,7 @@ _svc_alloc_rwx: ; Base91 decoder _decode: - mov al, 0x1f ; syscall preserves rax; hence at this point rax=9 + mov al, 0x1f ; syscall preserves all registers except rcx, r11, rax; hence at this point rax=(previous rdi)=0 _decode_loop: shl eax, 13 _decode_loop_2: From 6dcd596a58bf6776639df58cf5ed0cee84b8841b Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 22:48:19 +0900 Subject: [PATCH 09/10] short: shorten the shorter prestub --- scripts/static-pie-prestub-amd64-shorter.asm | 2 +- scripts/static-pie-prestub-amd64-shorter.bin | 2 +- scripts/static-pie-template-amd64-shorter.rs | 2 +- src/bin/codegen.rs | 8 +++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/scripts/static-pie-prestub-amd64-shorter.asm b/scripts/static-pie-prestub-amd64-shorter.asm index 895f6edc..37c1e807 100644 --- a/scripts/static-pie-prestub-amd64-shorter.asm +++ b/scripts/static-pie-prestub-amd64-shorter.asm @@ -64,4 +64,4 @@ _decode_zeros: ; Jump to entrypoint _jump_to_entrypoint: sub rdi, qword [rdi-8] - jmp rdi \ No newline at end of file + call rdi \ No newline at end of file diff --git a/scripts/static-pie-prestub-amd64-shorter.bin b/scripts/static-pie-prestub-amd64-shorter.bin index d133d946..bf1c3b48 100644 --- a/scripts/static-pie-prestub-amd64-shorter.bin +++ b/scripts/static-pie-prestub-amd64-shorter.bin @@ -1 +1 @@ -j X™E1ÉV1ÿj^²j"AZjÿAX^H—°Áà ¬,#™r#tþÈ’¬,$kÀ[ЪÁèöÄu÷ë߶OÿHÿÏóªë×H+øÿç \ No newline at end of file +j X™E1ÉV1ÿj^²j"AZjÿAX^H—°Áà ¬,#™r#tþÈ’¬,$kÀ[ЪÁèöÄu÷ë߶OÿHÿÏóªë×H+øÿ× \ No newline at end of file diff --git a/scripts/static-pie-template-amd64-shorter.rs b/scripts/static-pie-template-amd64-shorter.rs index 4c6a8470..87d7034a 100644 --- a/scripts/static-pie-template-amd64-shorter.rs +++ b/scripts/static-pie-template-amd64-shorter.rs @@ -5,4 +5,4 @@ $$$$solution_src$$$$ } // SOLUTION END -#[no_link]extern crate std;#[no_mangle]unsafe fn _start(){std::arch::asm!(".quad 56c931459958096ah,6a07b25e016aff31h,0f5841ff6a5a4122h,0e0c11fb097485e05h,74237299232cac0dh,6b242cac92c8fe16h,8e8c1aad0015bc0h,0fdfebf77510c4f6h,0aaf3cfff48ff4fb6h,0e7fff87f2b48d7ebh",in("rsi")r$$$$binary_raw_base91$$$$.as_ptr())} \ No newline at end of file +#[no_link]extern crate std;#[no_mangle]unsafe fn _start(){std::arch::asm!(".quad 56c931459958096ah,6a07b25e016aff31h,0f5841ff6a5a4122h,0e0c11fb097485e05h,74237299232cac0dh,6b242cac92c8fe16h,8e8c1aad0015bc0h,0fdfebf77510c4f6h,0aaf3cfff48ff4fb6h,0d7fff87f2b48d7ebh",in("rsi")r$$$$binary_raw_base91$$$$.as_ptr())} \ No newline at end of file diff --git a/src/bin/codegen.rs b/src/bin/codegen.rs index a3db1249..9289009e 100644 --- a/src/bin/codegen.rs +++ b/src/bin/codegen.rs @@ -83,17 +83,15 @@ unsafe extern "win64" fn _start() -> ! { ); // For "short", we always assume we are running with loader on Linux, // since "short" is only meaningful when submitting to online judges (not local test runs). + // Note that the stub will ensure that stack is aligned before caling _start. + // Also, for "short" on x86_64 Linux, we don't need PLATFORM_DATA, so we don't fabricate it. #[cfg(feature = "short")] asm!( "clc", // Not needed but packager wants it - "sub rsp, 80", // 16 + 80 = 96 = 16*6 -> stack alignment preserved - "push 1", // env_flags = 1 (ENV_FLAGS_LINUX_STYLE_CHKSTK) - "push 2", // env_id = 2 (ENV_ID_LINUX) + "push rax", // Align stack "lea rdi, [rip + __ehdr_start]", "lea rsi, [rip + _DYNAMIC]", "call {0}", - "push rsp", - "pop rcx", "call {1}", // This won't return since on Linux we invoke SYS_exitgroup in binary sym loader::amd64_elf::relocate, sym _start_rust, From 55b515ec60ce2636ce9329006ab6593492ec477c Mon Sep 17 00:00:00 2001 From: Byeongkeun Ahn <7p54ks3@naver.com> Date: Thu, 30 Nov 2023 22:48:24 +0900 Subject: [PATCH 10/10] Update static-pie-gen.py --- scripts/static-pie-gen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/static-pie-gen.py b/scripts/static-pie-gen.py index c0c43d63..0345ef7a 100644 --- a/scripts/static-pie-gen.py +++ b/scripts/static-pie-gen.py @@ -123,7 +123,7 @@ # template template_candidates = [template_path] -if lang_name == "Rust" and "x86_64" in target_name and "short" in template_path and len(memory_bin) <= 4096: +if lang_name == "Rust" and "x86_64" in target_name and "short" in template_path and len(code_raw) <= 4096: template_candidates.append(template_path.replace("short", "shorter")) out = None