8000 Format readme · stackless-dev/stackman@75af637 · GitHub
[go: up one dir, main page]

Skip to content

Commit 75af637

Browse files
committed
Format readme
1 parent 7ce4a67 commit 75af637

File tree

1 file changed

+42
-4
lines changed

1 file changed

+42
-4
lines changed

README.md

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
[![build test and commit](https://github.com/kristjanvalur/stackman/actions/workflows/buildcommit.yml/badge.svg)](https://github.com/kristjanvalur/stackman/actions/workflows/buildcommit.yml)
22

33
# stackman
4+
45
Simple low-level stack manipulation API and implementation for common platforms
56

67
## Purpose
8+
79
This library aims to provide a basic API to perfom stack manipulation
810
on various platforms. Stack manipulation involves changing the machine stack
911
pointer while optionally saving and restoring the stack contents.
@@ -29,34 +31,48 @@ Additionally, it provides a set of pre-assembled libraries for the most common
2931
platforms so that no assembly steps are required by users.
3032

3133
## Features
34+
3235
- Simple api
36+
3337
- `stackman_switch()` and `stackman_call()` are the only functions.
3438
- The caller provides a callback and context pointer to customize behaviour.
35-
Simple implementation
39+
40+
- Simple implementation
41+
3642
- The code involving assembly is as simple as possible, allowing for
3743
straightforward implementation on most platforms.
3844
- Complex logic and branching is delegated to the C callback.
3945
- Custom platform assembly code must only do three things:
4046
1. Save and restore volatile registers and stack state on the stack
4147
2. Call the callback twice with the current stack pointer
4248
3. Set the stack pointer to the value returned by the first callback.
43-
- Assembly support
49+
50+
- Assembly support
51+
4452
The straightforward and application-agnostic switching allows the switching function to be implemented in full assembler. This removes
4553
the risk of inline-assembler doing any sort of unexpected things such
4654
as in-lining the function or otherwise change the assumptions that the
4755
function makes about its environment. This assembly code can be created by the in-line assembler in a controlled environment.
56+
4857
- No dependencies
58+
4959
The library merely provides stack switching. It consist only of a couple of functions with no dependencies.
60+
5061
- Stable
62+
5163
There is no need to add or modify functionality.
64+
5265
- Libraries provided.
66+
5367
The aim is to provide pre-assembled libraries for the most popular platforms. This relieves other tools that want to do stack
5468
manipulation from doing any sort of assembly or complex linkage. Just include the headers and link to the appropriate library.
5569

5670
## Supported platforms
71+
5772
The current code is distilled out of other work, with the aim of simplifying and
5873
standardizing the api. A number of ABI specifications is supported, meaning architecture and
5974
calling convention, plus archive format:
75+
6076
- win_x86 (32 bits)
6177
- win_x64
6278
- win_ARM64 (experimental)
@@ -65,7 +81,8 @@ calling convention, plus archive format:
6581
- AAPCS (32 bit arm)
6682
- AAPCS64 (64 bit arm)
6783

68-
Supported toolchains:
84+
### Supported toolchains:
85+
6986
- Gnu C
7087
- clang
7188
- Microsoft Visual Studio
@@ -74,16 +91,21 @@ Other platforms can be easily adapted from both existing implementations for oth
7491
projects as well as from example code provided.
7592

7693
## API
94+
7795
There are two functions that make up the stackman library: `stakman_switch()` and `stackman_call()` who
7896
both take a `stackman_cb_t` callback:
97+
7998
```C
8099
typedef void *(*stackman_cb_t)(
81100
void *context, int opcode, void *stack_pointer);
82101
void *stackman_switch(stackman_cb_t callback, void *context);
83102
void *stackman_call(stackman_cb_t callback, void *context, void *stack);
84103
```
104+
85105
### stackman_switch()
106+
86107
This is the main _stack manipulation_ API. When called, it will call `callback` function twice:
108+
87109
1. First it calls it with the current opcode `STACKMAN_OP_SAVE`, passing the current `stack_pointer` to
88110
the callback. This gives the callback the opportunity to _save_ the stack data somewhere. The callback
89111
can then return a **different** stack pointer.
@@ -98,14 +120,17 @@ Depending on how the callback function is implemented, this API can be used for
98120
saving a copy of the stack, perform a stack switch, query the stack pointer, and so on.
99121
100122
### stackman_call()
123+
101124
This is a helper function to call a callback function, optionally providing it with a different stack to
102125
use.
126+
103127
1. It saves the current CPU stack pointer. If `stack` is non-zero, it will replace the stackpointer
104128
with that value.
105129
2. It calls the callback function with the opcode `STACKMAN_OP_CALL`.
106130
3. It replaces the stack pointer with the previously saved value and returns the return value from the callback.
107131
108132
This function is useful for at least three things:
133+
109134
- To move the call chain into a custom stack area, some heap-allocated block, for example.
110135
- To query the current stack pointer
111136
- To enforce an actual function call with stack pointer information.
@@ -114,34 +139,42 @@ The last feature is useful to bypass any in-lining that a compiler may do, when
114139
a proper function call with stack, for example, when setting up a new stack entry point.
115140
116141
## Usage
142+
117143
- Include `stackman.h` for a decleration of the `stackman_switch()` function
118144
and the definition of various platform specific macros. See the documentation
119145
in the header file for the various macros.
120146
- Implement switching semantics via the callback and call `stackman_switch()` from your
121147
program as appropriate. See tests/test.c for examples.
122148
123-
There are two basic ways to add the library to your project:
149+
There are two basic ways to add the library to your project: Using a static library or inlining the code.
150+
124151
### static library (preferred)
152+
125153
- You link with the `libstackman.a` or `stackman.lib` libraries provided for your platform.
126154
127155
### inlined code
156+
128157
- You inlude `stackman_impl.h` in one of your .c source files to provide inline assembly.
129158
- You include `stackman_impl.h` in an assembly (.S) file in your project to include assembly code.
130159
- (windows) You include `stackman_s.asm` in an assemby (.asm) file in your project.
131160
In the case of inlined code, it can be specified to prefer in-line assembly and static linkage
132161
over separate assembly language source.
133162
134163
## Development
164+
135165
### Adding new platforms
166+
136167
1. Modify `platform.h` to identif the platform environment. Define an ABI name and
137168
include custom header files.
138169
2. Use the `switch_template.h` to help build a `switch_ABI.h` file for your ABI.
139170
3. Provide an assembler version, `switch_ABI.S` by compiling the `gen_asm.c` file for your platform.
140171
4. Provide cross-compilation tools for linux if possible, by modifying the `Makefile`
141172
142173
### Cross-compilation
174+
143175
Linux on x86-64 can be used to cross compile for x86 and ARM targets. This is most useful to generate assembly code, e.g. when compiling
144176
stackman/platform/gen_asm.c
177+
145178
- x86 requires the -m32 flag to compilers and linkers.
146179
- arm32 requires to use the arm-linux-gnueabi-* tools, including cc and linker
147180
- aarch64 requires the aarch64-linux-gnu-* tools.
@@ -151,23 +184,27 @@ The x86 tools require the **gcc-multilib** and **g++-multilib** packages to be i
151184
platforms may need to be done independently.
152185
153186
#### Cross compiling for x86 (32 bit) on Linux
187+
154188
- install __gcc-multilib__ and __g++-multilib__
155189
- *compile* **gen_asm.c** using `gcc -m32`
156190
- *make* using `make PLATFORMFLAGS=-m32 test`
157191
158192
#### Cross compiling for ARM (32 bit) on Linux
193+
159194
- install __gcc-arm-linux-gnueabi__ and __g++-arm-linux-gnueabi__
160195
- install __qemu-user__ for hardware emulation
161196
- *compile* **gen_asm.c** using `arm-linux-gnueabi-gcc`
162197
- *make* using `make PLATFORM_PREFIX=arm-linux-gnueabi- EMULATOR=qemu-arm test`
163198
164199
#### Cross compiling for Arm64 on Linux
200+
165201
- install **gcc-aarch64-linux-gnu** and **g++-aarch64-linux-gnu**
166202
- install __qemu-user__ for hardware emulation
167203
- *compile* using `aarch64-linux-gnu-gcc`
168204
- *make* using `make PLATFORM_PREFIX=aarch64-linux-gnu- EMULATOR=qemu-aarch64 test`
169205
170206
## A note about Intel CET
207+
171208
Intel's *Control-Flow Enforcement Technology* is incompatible with stack switching
172209
because it employs a secondary *Shadow Stack*, that the user-mode program cannot
173210
modify. Unexpected return flow after a stack switch would cause the processor
@@ -179,6 +216,7 @@ code may be run in such a protected environment.
179216
See https://software.intel.com/content/www/us/en/develop/articles/technical-look-control-flow-enforcement-technology.html for more information
180217
181218
## History
219+
182220
This works was originally inspired by *Stackless Python* by [Christian Tismer](https://github.com/ctismer), where the original switching code was
183221
developed.
184222

0 commit comments

Comments
 (0)
0