I need to use Rust code in a naked function, because the function handles an x86_64 OS context switch on a timer interrupt, and RSP should be untouched at the beginning of the function body, to save everything before moving on. I have tried to use #[naked] for this, but it is really inflexible, because I can only write assembly code in it.
If I use a stable calling convention (like extern "C"), the function makes some room for locals on the stack by subtracting whatever it's needed from RSP. This is not OK because if I want to save the pushed registers I need to know the stack pointer address of the last one, but now I am unable to, because I do not know how much does Rust subtract from RSP.
My naked function would still work with local variables if I subtract a known value (even though larger than needed) from RSP AFTER saving the stack pointer, but obviously Rust steps in my way by not letting me use anything besides ASM if I don't want a prologue.
I hear you asking, why couldn't I just push the registers after the prologue? The answer is that I need to take the saved RIP, CS, RFLAGS, RSP and SS registers too, pushed by the CPU when the timer interrupt happens, but before the prologue. I have seen that a couple of years ago Rust allowed actual code in a naked function, but now it does not, and I couldn't find a fitting replacement yet. I really think RFC #2972 made naked functions useless in most cases, because in my opinion if the developer really pays attention to what code they are writing and how, inspecting the generated assembly too, and if they make sure that the naked function only gets called from known places, it wouldn't "likely depend on undefined behavior".
What could match my requirements?
Solved it! I made the interrupt handler a naked function, that does the context save and passes the stack address to an extern "C" function through the first parameter.
#[naked]
#[no_mangle]
pub unsafe fn timer_handler_naked_scheduler() {
asm!("push r15; push r14; push r13; push r12; push r11; push r10; push r9;\
push r8; push rdi; push rsi; push rdx; push rcx; push rbx; push rax; push rbp;\
mov rdi, rsp; call scheduler_part_2;", options(noreturn));
}
#[no_mangle]
pub unsafe extern "C" fn scheduler_part_2(context: *const TaskContext) {
serial_println!("{:x?}", *context);
pic::end_of_interrupt(interrupts::HardwareInterrupt::Timer);
task::restore_context(&*context);
}
Related
Warning: as the reference types proposal isn't complete yet, this code will not run without toggling flags or setting in order to enable executing experimental code.
If you are on Google Chrome or a Chromium browser, you will need to enable the following flag:
chrome://flags/#enable-experimental-webassembly-features
I had set up a simple handwritten Wasm module for personal use. I could've easily written it in JavaScript, but it was easier and made more sense to use Wasm, and since it was a simple, personal script, I wouldn't care if other people couldn't run it.
I had compiled it using wabt's wat2wasm.
The Wasm module was intended to be fed the entire globalThis object to import from.
From there, it took four TypedArray constructors: Uint8Array, Uint16Array, Uint32Array, and BigUint64Array.
Take note: no code was executed prior to the Wasm, thus there cannot be any interference.
Later, I had realized that that the Wasm wasn't working as intended at all, my math was correct, but the variables were wrong.
I had narrowed my problem down to just this:
;; global -> global variable
(import "globalThis" "Uint8Array" (global $Uint8Array externref))
(import "globalThis" "Uint16Array" (global $Uint16Array externref))
(import "globalThis" "Uint32Array" (global $Uint32Array externref))
(import "globalThis" "BigUint64Array" (global $BigUint64Array externref))
;; func -> function
(import "console" "log" (func $console::log (param externref)))
(start $_start)
(func $_start
global.get $Uint8Array
call $console::log
global.get $Uint16Array
call $console::log
global.get $Uint32Array
call $console::log
global.get $BigUint64Array
call $console::log
)
This Wasm was instantiated like so:
WebAssembly.instantiateStreaming(
fetch(
"test.wasm", {
mode : "same-origin",
credentials : "omit",
cache : "no-store",
redirect : "error",
referrer : "no-referrer"
}
), globalThis
).catch( console.error );
The interesting problem is that the logs all say the same thing: Uint8Array.
I was dumbfounded. This has to be literally impossible. The JavaScript file itself was not cached, the WebAssembly was being fetched with "no-cache," the web page itself wasn't cached.
Then I thought, because I was using XHTML, maybe it didn't happen in HTML files. It did there too.
I tried converting the Wasm file to a TypedArray and just using WebAssembly.instantiate, suddenly, it worked flawlessly.
At this point the server must be serving the wrong file, because the further I go, the more this seems like nonsense.
I almost want to say that this is a Chromium browser or V8 runtime error, but I need to narrow it down a bit more before I blindly attempt to present this as a bug.
I have set up two different versions of the same code, on Repl.it, and on CodeSandBox.io, so that hopefully someone can try running it themself, to confirm the bug, and maybe attempt to debug where I went wrong.
(Could this be a problem with Repl.it's server?)
This was a compiler bug fixed by Chromium in
https://chromium-review.googlesource.com/c/v8/v8/+/2551100.
This was the response that I had gotten from one of the developers:
This is indeed a timing issue that has been fixed in https://chromium-review.googlesource.com/c/v8/v8/+/2551100. The problem happens when there are only imported globals, and compilation of the WebAssembly functions finishes before the stream actually finishes. In this case, the offset calculation happens after the compiler uses the offsets, and therefore produces incorrect code.
A workaround is to define one global that is not imported, as this causes the offset calculation to happen earlier.
Seems like sending a small module that only imports globals instead of functions was breaking the code.
Their code had a threading race condition between the stream and the compiler.
I'm trying to deploy an app to production and getting a little confused by environment and application variables and what is happening at compile time vs runtime.
In my app, I have a genserver process that requires a token to operate. So I use config/releases.exs to set the token variable at runtime:
# config/releases.exs
import Config
config :my_app, :my_token, System.fetch_env!("MY_TOKEN")
Then I have a bit of code that looks a bit like this:
defmodule MyApp.SomeService do
use SomeBehaviour, token: Application.get_env(:my_app, :my_token),
other_config: :stuff
...
end
In production the genserver process (which does some http stuff) gives me 403 errors suggesting the token isn't there. So can I clarify, is the use keyword getting evaluated at compile time (in which case the application environment doest exist yet)?
If so, what is the correct way of getting runtime environment variables in to a service like this. Is it more correct to define the config in application.ex when starting the process? eg
children = [
{MyApp.SomeService, [
token: Application.get_env(:my_app, :my_token),
other_config: :stuff
]}
...
]
Supervisor.start_link(children, opts)
I may have answered my own questions here, but would be helpful to get someone who knows what they're doing confirm and point me in the right way. Thanks
elixir has two stages: compilation and runtime, both written in Elixir itself. To clearly understand what happens when one should figure out, that everything is macro and Elixir, during compilation stage, expands these macros until everything is expanded. That AST comes to runtime.
In your example, use SomeBehaviour, foo: :bar is implicitly calling SomeBehaviour.__using__/1 macro. To expand the AST, it requires the argument (keyword list) to be expanded as well. Hence, Application.get_env(:my_app, :my_token) call happens in compile time.
There are many possibilities to move it to runtime. If you are the owner of SomeBehaviour, make it accept the pair {:my_app, :my_token} and call Application.get_env/2 somewhere from inside it.
Or, as you suggested, pass it as a parameter to children; this code belongs to function body, meaning it won’t be attempted to expand during compilation stage, but would rather be passed as AST to the resulting BEAM to be executed in runtime.
I try to call windows function inside my custom assembly function
The pseudocode would be something like:
MYFUNC
PUSH EBP
PUSH WINDOWSFUNCTIONPARAMETER
CALL [IMPORTEDWINDOWSFUNCTION]
POP EBP
RET
So I know its safe to leave this like this if I call only one function inside,
because thie stack will be restored anyway.
The problem is- why can't i add esp, 0x04 after this? - The app crashes
Im not sure if i even need to do this but imo its safer to do it after function
calls, and somehow i cant get this working inside a function
I'm gratefull for any help :)
I am not sure what you mean by "after this". Basically:
On a x86 architecture, the stack grows downwards.
Depending on your calling convention, either the caller or the callee cleans up the stack.
You are calling a windows function, therefore i assume the called function cleans up the stack parameters. This leads me to the following conclusion:
If you execute "add esp, 0x04" after your API call, "pop ebp" will receive the return address instead of the previously saved ebp register. Therefore, the final "ret" will fail and not return to the caller of MYFUNC.
If you want to perform "add esp, 0x04" to remove the function parameter: thats not necessary because the windows API has removed it already.
EDIT:
If you have a simple example like the one above, I recommend to use a debugger like ollydbg, x64dbg, etc. They are free and show you the registers, stack, etc. while your app is running.
Normally in Javascript, if you reference the "magic" arguments variable from inside a function, it will contain all of the arguments passed to the function. In the Chrome developer tools (on Linux) though, that doesn't happen; if you:
Add a debugger statement to some function that doesn't have any declared arguments
Do something to trigger that function with an argument
When Chrome pauses on the debugger line, check arguments from the console.
You'll see that arguments is empty. Now, this can be fixed easily enough by just declaring arguments on the function; in other words, if you do:
function(a,b,c) {
debugger;
}
instead of:
function() {
debugger;
}
arguments will have the arguments (or at least the first three).
However, that really shouldn't be necessary, which leads me to my question: is there any setting I can change, or is there anything else I can do to fix this behavior and just make Chrome put EVERY passed-in argument in to arguments, not just the declared ones?
This recently has been redone in V8 JavaScript engine. Soon it will make its way into Chrome codebase, which eventually will get into stable release (possibly 28...* ?).
I have been studying this method of API hooking using the mechanisms for hotpatching in windows dlls.
http://www.codeproject.com/KB/winsdk/0xF9EB_Hooking.aspx
I was wondering if anyone would know of a way to extend that to hooking non exported functions such as a C++ constructor for an internal class inside of a DLL. I have already know the address via dis-assembly... the problem I am having is how to set up the right calling conventions so that I can call the original function inside of my hook function.
I'm already to the point to where my hook function gets called... the program crashes because I can't return the results of calling the original function.
Lets assume we are talking about hooking an internal class constructor with a prototype something like this:
public __thiscall <class_name>::<class_name>(<single pointer arg to another object>)
depending on how your module is loaded, you can generally just overwrite the relative or absolute addresses at their respective call sites, else you need to make a trampolining function, for which its easier to use something like MS Detours.
In terms of the correct prototype for __thiscall based class member functions, you need some trickery, as you can't generally use __thiscall outside classes. The fastest and easiest way is to use __fastcall and ignore the second parameter. So your first definition becomes void __fastcall myctor(myobj* pObj).
Define it as a typical __stdcall function except that you'll have this pointer in ecx register. If you need this pointer, then use the __asm keyword to get the value:
void __stdcall HookedConstructor( SomeObject *pObject){
HookedClass *pClass;
__asm mov pClass, ecx;
...
}
Note that you'll have to do this at the beginning of the call. Otherwise, the value of ecx register may be overwritten.