summaryrefslogtreecommitdiff
path: root/docs/guide
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2026-05-08 15:03:57 -0400
committerRusty Wagner <rusty.wagner@gmail.com>2026-05-22 17:52:21 -0400
commitede9c92ba6155be37571743df7172aec76dd3c4b (patch)
treefc2d486ae476c25220d065bbf00afbad5961386b /docs/guide
parent8f2e99d1b6e814fcf7b9142889b7f2dfab5dd94e (diff)
Update documentation for calling convention changes
Diffstat (limited to 'docs/guide')
-rw-r--r--docs/guide/types/attributes.md61
1 files changed, 61 insertions, 0 deletions
diff --git a/docs/guide/types/attributes.md b/docs/guide/types/attributes.md
index c8040e70..24bb9848 100644
--- a/docs/guide/types/attributes.md
+++ b/docs/guide/types/attributes.md
@@ -137,12 +137,73 @@ The following built-in calling conventions without dedicated keywords are availa
|`windows-syscall`|aarch64|Windows system call|
|`apple-syscall`|aarch64|macOS and iOS system calls|
|`go-stack`|x86, x86_64|Stack-based calling convention used by the Go compiler on 32-bit x86 or older compilers|
+|`pascal`|x86|Pascal stack-based convention with left-to-right parameter passing and callee stack cleanup|
|`register`|x86|Register-based calling convention with left-to-right parameter passing (used by default in Delphi)|
|`gcc-fastcall`|x86|The `fastcall` calling convention as implemented in GCC on non-Windows platforms|
|`clang-fastcall`|x86|The `fastcall` calling convention as implemented in Clang on non-Windows platforms|
|`gcc-thiscall`|x86|The `thiscall` calling convention as implemented in GCC on non-Windows platforms|
|`clang-thiscall`|x86|The `thiscall` calling convention as implemented in Clang on non-Windows platforms|
+???+ Warning "Linux x86 / x86_64 default convention rename"
+ Prior to version 5.4, the default Linux convention on x86/x86_64 was named `cdecl` (and the stdcall variant was `stdcall`). It is now `sysv` (and `sysv-stdcall`) to deconflict with the Windows behavior of `cdecl`/`stdcall`. Both names continue to be registered on the architecture, so `__convention("cdecl")` will still resolve to the Windows version of `cdecl` even on Linux. If you have scripts that match calling conventions by string name, update them to recognize `sysv` and `sysv-stdcall`.
+
+## Custom Parameter and Return Value Locations
+
+Calling conventions describe the default placement of parameters and return values, but many real-world ABIs have functions whose locations diverge from those defaults (for example, hand-tuned assembly, custom register conventions, or high-level language features). You can override the default location for individual parameters with the `@` syntax or for a function's return value with the `__location("...")` attribute. The argument is a string in Binary Ninja's value-location syntax (described below).
+
+### Examples
+
+``` C
+/* Parameter locations: place this parameter in a specific register or stack slot */
+int foo(int reg_param @ rdi, int stack_param @ 0x10);
+
+/* Return-value location: return through rsi instead of the default rax */
+int bar() __location("rsi");
+
+/* A 16-byte value returned with the high half in rdx and the low half in rax;
+ components are written left-to-right from high to low */
+struct pair get_pair() __location("rdx:rax");
+
+/* A parameter value in two registers. Complex locations for parameters are quoted. */
+struct void set_pair(struct pair value @ "rdx:rax");
+
+/* A return value spanning two registers with explicit field offsets */
+struct mixed get_mixed() __location("[0x0: rax, 0x8: xmm0]");
+
+/* An indirect return through a caller-supplied pointer; the leading * marks the
+ location as a pointer to the storage, and "-> *rax" says the same pointer is
+ returned in rax */
+struct big get_big() __location("*rdi -> *rax");
+```
+
+### Value Location Syntax
+
+The string that makes up a location describes one or more storage components (the locations holding the bytes of a single value). The grammar is:
+
+* **Register component:** the register name, e.g., `rax`, `xmm0`, `r1`.
+* **Stack component:** an integer offset into the caller's stack frame (decimal or `0x`-prefixed hex), e.g., `0x10`, `-4`.
+* **Component size suffix:** append `.b`, `.w`, `.d`, `.q`, `.t`, or `.o` for 1/2/4/8/10/16-byte sizes, or `.<n>` for an explicit byte count, e.g., `eax.d`, `r0.q`, `rax.b`. Without a suffix, the natural register width is used (for stack components, sizes are inferred from the type).
+* **Multi-component (concatenated):** components separated by `:`, written **high-to-low**, e.g., `rdx:rax` puts the low half in `rax` and the high half in `rdx`. This form requires that components are contiguous.
+* **Multi-component with offsets:** when components are not contiguous, list them inside `[ ... ]` as `offset: component`, e.g., `[0x0: rax, 0x8: xmm0]`. Offsets are byte offsets within the value being passed/returned.
+* **Indirect:** prefix the entire location with `*` to indicate the location holds a pointer to the value rather than the value itself, e.g., `*rdi`.
+* **Returned-pointer hint:** for indirect returns where the same pointer is also returned in a register, append `-> *<reg>`, e.g., `*rdi -> *rax`.
+
+### Pass By Value and By Reference
+
+For composite types (structures, arrays) the calling convention decides whether to pass the value packed into registers, on the stack, or indirectly through a pointer. When that default is wrong for a particular declaration (most commonly in C++ where non-trivial type rules are applied that cannot always be determined at the binary level) you can override it with `__by_value` or `__by_ref`:
+
+``` C
+/* Force this argument to be passed by value (in registers or on the stack)
+ even when the convention would normally pass it indirectly */
+void takes_value(struct value_type __by_value arg);
+
+/* Force this argument to be passed by reference (as a pointer) even when the
+ convention would normally pass it by value */
+void takes_object(struct object_type __by_ref arg);
+```
+
+`__by_value` and `__by_ref` apply per-parameter and affect only the location chosen for the parameter (the parameter's type in the signature is unchanged). If you need to override the *exact* register or stack slot, use the `@` syntax or `__location()` attribute described above instead (it implies a custom location and overrides any by-value/by-ref decision).
+
## System Call Functions for Type Libraries
[Type Libraries](typelibraries.md) can annotate system calls by adding functions with the special `__syscall()` attribute, specifying names and arguments for each syscall number. This attribute has no effect outside of [Type Libraries](typelibraries.md) and [Platform Types](platformtypes.md).