From 188b69652c282db26e0beb167da353ff95029e48 Mon Sep 17 00:00:00 2001
From: caheckman <48068198+caheckman@users.noreply.github.com>
Date: Tue, 1 Sep 2020 10:24:59 -0400
Subject: [PATCH] PrototypeModel documentation
---
.../src/main/doc/decompileplugin.xml | 196 +++++++++++++++++-
1 file changed, 193 insertions(+), 3 deletions(-)
diff --git a/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml b/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml
index 0af41c4ab4..38b30de7c5 100644
--- a/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml
+++ b/Ghidra/Features/Decompiler/src/main/doc/decompileplugin.xml
@@ -1049,6 +1049,69 @@
+
+ Prototype Model
+
+ Functions in high-level languages manipulate symbols like parameters and return values that
+ are implicitly stored in a way that doesn't collide with other functions and variables. To
+ actually map these symbols to physical registers and memory locations, compilers establish a
+ calling convention for the function.
+ Loosely, this is a set of memory resources, whether it is registers or stack locations,
+ and a procedure for sequentially assigning resources to parameters based on their properties.
+ A prototype model is the formal object in Ghidra that represents
+ a calling convention and holds its specific rules and resource details.
+
+
+ Prototype models are architecture specific, and depending on the compiler, a single Program may make
+ use of multiple models. Subsequently, each distinct model has a name like __stdcall or
+ __thiscall. The decompiler makes use of the prototype model, as assigned to the function by the user or
+ discovered in some other way, when performing its analysis of parameters.
+
+
+ A prototype model is typically used as a whole and is assigned by name to individual functions. But some of
+ the sub-concepts of the model may be relevant to reverse engineers.
+
+
+ Incoming and Outgoing Storage Locations
+
+ A formal input parameter is always assigned a specific memory location to hold its value coming into the function.
+ The storage location can be a register, a stack location, or other memory location. The storage
+ location may be reused later by other variables in the function; only the incoming value stored there is guaranteed
+ to be that of input parameter.
+
+
+ If the parameter
+ is stored on the stack, the storage location is viewed as a constant offset in the stack
+ space, where the offset is relative to the incoming value of stack pointer
+ (See the discussion in ).
+
+
+ The return value for the function, similarly, is stored at a single memory location. It
+ is guaranteed to be at that location only at points where the function is exited. There may be multiple exit
+ points, but they all share the same return value storage location.
+
+
+
+ Unaffected
+
+ Prototype models can specify a set of unaffectedmemory locations,
+ whose value must be preserved across the function. I.e. each location
+ must hold the same value at a function's exit that it held coming into the function.
+ These encompass a calling convention's saved registers, where a calling function
+ can store values it doesn't want to change unexpectedly, but also may include other registers that are
+ known not to change, like the stack pointer.
+ The decompiler uses the information to determine which locations can be safely propagated across
+ a sub-function.
+
+
+
+ Killed by Call
+
+ In constrast to unaffected memory locations, a prototype model may specify
+ killed by call locations that are guaranteed not
+ to be used to hold a value across the function.
+
+
@@ -1726,10 +1789,14 @@
For annotations that specifically label a function's formal parameters or return value,
the Signature Source-Type also affects how they're treated by the decompiler.
If the Source-Type is set to anything other than DEFAULT, there is a forced
- one-to-one correspondence between variables annotations and actual parameters in the decompiler's
+ one-to-one correspondence between variables annotation and actual parameters in the decompiler's
view of the function. This is stronger than just forcing the data-type; the existence (or not) of
- the variable itself is forced by the annotation in this case. A Source-Type other than
- DEFAULT is set typically if debug symbols for the function are read in during
+ the variable itself is forced by the annotation in this case. If the Source-Type is forcing and
+ there are no parameter annotations, a void prototype is forced on the function.
+
+
+ A forcing Source-Type, with a value other than
+ DEFAULT, is set typically if debug symbols for the function are read in during
Program import (IMPORTED), or if the user manually edits the function prototype
directly (USER_DEFINED).
@@ -1866,6 +1933,129 @@
+
+ Function Prototypes
+
+ Every formal Function in Ghidra is associated with a set of variable annotations and other properties that
+ make up the function prototype. Due to the nature of reverse engineering,
+ the function prototype may only include partial information and may be built up over time. Individual
+ elements include:
+
+
+
+
+ Input Parameters
+
+
+ Each formal input to the function can have a Variable Annotation that describes its name, data-type,
+ and storage location, at the moment control-flow enters the function. If the annotations exist, they are shown
+ in the Listing Window as part of the Function header, and they usually correspond directly with symbols in the
+ function declaration produced by the decompiler.
+
+
+
+
+ Return Value
+
+
+ The value returned by a function can have a special Variable Annotation that describes its data-type
+ and storage location, at the moment control-flow exits the function. If it exists, the annotation is shown
+ in the Listing Window as part of the Function header with the name <RETURN>, and it usually
+ corresponds directly with the return value in the function declaration produced by
+ the decompiler.
+
+
+
+
+ Calling Convention
+
+
+ The calling convention used by the function can be specified as part of the function prototype. The convention
+ is specified by name, referring to the formal Variable Arguments
+
+
+ Functions have a boolean property called variable argments, which can be turned on
+ if the function is capable of being passed a variable number of inputs. This property informs the decompiler that
+ the function may take additional parameters beyond any with an explicit variable annotation.
+ This affects decompilation of any function which calls the variable arguments function, allowing
+ the decompiler to discover unlisted parameters at a given call site.
+
+
+
+
+ No Return
+
+
+ A function can be marked explicitly as not returning, meaning that once
+ a call is made to the function, execution will never return to the caller. The decompiler uses this to
+ compute the correct control-flow in any calling functions.
+
+
+
+
+ In-Line
+
+
+ If the boolean property in-line is turned on for a particular function,
+ it directs the decompiler to inline the effects of the function into the decompilation of any of its calling functions.
+ The function will no longer appear as a direct subfunction call in the decompilation, but all of its data-flow
+ will be incorporated into the calling function.
+
+
+ This is useful for bookkeeping functions, where its important for the decompiler to
+ see its effects on the calling function. Functions that set up the stack frame for a caller or
+ functions that look up or dispatch a switch destination are typical examples that should be marked in-line.
+
+
+
+
+ Call-fixup
+
+
+ This property is similar in spirit to marking a function as in-line.
+ A call-fixup directs the decompiler to replace any call to the function with a specific
+ chunk of raw p-code. The decompilation of any calling function no longer shows the subfunction call, but the chunk
+ of p-code incorporates the subfunction's effects.
+
+
+ Call-fixups are more flexible than just inlining a function. The call-fixup chunk can be tailored to incorporate all of,
+ just a part of, or something different to the behavior of the function.
+
+
+ Call-fixups are specified by name. The name and associated p-code chunk are typically defined in the
+ compiler specification for the Program.
+
+
+
+
+
+
+
+ Discovering Parameters
+
+ Any parameter annotations in the function prototype are all forcing (as a unit) if the
+ Signature Source-Type is set to anything other than
+ DEFAULT. See the more complete discussion in .
+
+
+ If the function prototype is not forced, the decompiler will attempt to discover the parameters
+ and return value using the calling convention. The prototype model underlying the calling convention
+ dictates which storage locations can be considered as parameters and their formal ordering.
+
+
+
+