mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-02 10:16:21 +00:00
0a14411bc1
* Add -O flag to ragg2 as an alias for -o a.out or -o <file> (without extension) * Add rabin2 -M (get main) for Java Class files * Add emit_trace (code tracer) for r_egg. useful to debug - ragg2 -a trace hello.r - Add emit->jmp() function pointer and emit->retvar - many fixes in function calls and definitions - Added support for 'break;' 'break();' and 'goto();' - Added .ret variable as an alias for eax, rax or r0
210 lines
5.0 KiB
Plaintext
210 lines
5.0 KiB
Plaintext
r_egg
|
|
===== --pancake
|
|
|
|
This is a rewrite of rarc2, a relocatable code compiler for radare.
|
|
|
|
Syntax of the language
|
|
======================
|
|
The code of r_egg is compiled as in a flow. It is a one-pass compiler;
|
|
this means that you have to define the proper stackframe size at the
|
|
beginning of the function, and you have to define the functions in
|
|
order to avoid getting compilation errors.
|
|
|
|
The compiler generates assembly code for x86-{32,64} and arm. But it aims
|
|
to support more platforms. This code is the compiled with r_asm and
|
|
injected into a tiny binary with r_bin.
|
|
|
|
You may like to use r_egg to create standalone binaries, position-
|
|
independent raw eggs to be injected on running processes or to patch
|
|
on-disk binaries.
|
|
|
|
The generated code is not yet optimized, but it's safe to be executed
|
|
at any place in the code.
|
|
|
|
Preprocessor
|
|
------------
|
|
There's no standard preprocessor integrated with it. But if you feel
|
|
the need to use one you may use cpp or spp*.
|
|
|
|
* hg clone http://hg.youterm.com/spp
|
|
|
|
Aliases
|
|
-------
|
|
Sometimes you just need to replace at compile time a single entity on
|
|
multiple places. Aliases are translated into 'equ' statements in assembly
|
|
language. This is just an assembler-level keyword redefinition.
|
|
|
|
AF_INET@alias(2);
|
|
printf@alias(0x8053940);
|
|
|
|
Includes
|
|
--------
|
|
Use cat(1) or the preprocessor to concatenate multiple files to be compiled.
|
|
It's not a task of a compiler to look for external sources, so it's a
|
|
delegated task right now.. but we will probably add native support for
|
|
spp (merge into)
|
|
|
|
TODO: this is not yet implemented
|
|
|
|
INCDIR@alias("/usr/include/ragg2");
|
|
sys-osx.r@include(INCDIR);
|
|
|
|
Hashbang
|
|
--------
|
|
eggs can use a hashbang to make them executable.
|
|
|
|
$ head -n1 hello.r
|
|
#!/usr/bin/ragg2 -X
|
|
$ ./hello.r
|
|
Hello World!
|
|
|
|
Main
|
|
----
|
|
The execution of the code is done as in a flow. The first function to be
|
|
defined will be the first one to be executed. If you want to run main()
|
|
just do like this:
|
|
|
|
#!/usr/bin/ragg2 -X
|
|
main();
|
|
...
|
|
main@global(128,64) {
|
|
...
|
|
|
|
Function definition
|
|
-------------------
|
|
You may like to split up your code into several code blocks. Those blocks
|
|
are bound to a label followed by root brackets '{ ... }'
|
|
|
|
Function signatures
|
|
-------------------
|
|
name@type(stackframesize,staticframesize) { body }
|
|
|
|
name : name of the function to define
|
|
type : see function types below
|
|
stackframesize : get space from stack to store local variables
|
|
staticframesize : get space from stack to store static variables (strings)
|
|
body : code of the function
|
|
|
|
Function types
|
|
--------------
|
|
alias ; Used to create aliases
|
|
data ; the body of the block is defined in .data
|
|
inline ; the function body is inlined when called
|
|
global ; make the symbol global
|
|
fastcall ; function that is called using the fast calling convention
|
|
syscall ; define syscall calling convention signature
|
|
|
|
Syscalls
|
|
--------
|
|
r_egg offers a syntax sugar for defining syscalls. The syntax is like this:
|
|
|
|
exit@syscall(1);
|
|
@syscall() {
|
|
: mov eax, `.arg`
|
|
: int 0x80
|
|
}
|
|
main@global() {
|
|
exit (0);
|
|
}
|
|
|
|
Libraries
|
|
---------
|
|
At the moment there is no support for linking r_egg programs to system
|
|
libraries. but if you inject the code into a program (disk/memory) you
|
|
can define the address of each function using the @alias syntax.
|
|
|
|
Core library
|
|
------------
|
|
There's a work-in-progress libc-like library written completely in r_egg
|
|
|
|
Variables
|
|
---------
|
|
.arg
|
|
.arg0
|
|
.arg1
|
|
.arg2
|
|
.var0
|
|
.var2
|
|
.fix
|
|
.ret ; eax for x86, r0 for arm
|
|
.bp
|
|
.pc
|
|
.sp
|
|
|
|
Arrays
|
|
------
|
|
Supported as raw pointers. TODO: enhace this feature
|
|
|
|
Tracing
|
|
-------
|
|
Sometimes r_egg programs will break or just not work as expected. Use the
|
|
'trace' architecture to get a arch-backend call trace:
|
|
|
|
$ ragg2 -a trace -s yourprogram.r
|
|
|
|
Pointers
|
|
--------
|
|
TODO: Theorically '*' is used to get contents of a memory pointer.
|
|
|
|
Virtual registers
|
|
-----------------
|
|
TODO: a0, a1, a2, a3, sp, fp, bp, pc
|
|
|
|
Return values
|
|
-------------
|
|
The return value is stored in the a0 register, this register is set when
|
|
calling a function or when typing a variable name without assignment.
|
|
|
|
$ cat test.r
|
|
add@global(4) {
|
|
.var0 = .arg0 + .arg1;
|
|
.var0;
|
|
}
|
|
main@global() {
|
|
add (3,4);
|
|
}
|
|
|
|
$ ragg2 -F -o test test.r
|
|
$ ./test
|
|
$ echo $?
|
|
7
|
|
|
|
Traps
|
|
-----
|
|
Each architecture have a different instruction to break the execution of
|
|
the program. REgg language captures calls to 'break()' to run the emit_trap
|
|
callback of the selected arch. The
|
|
|
|
break(); --> compiles into 'int3' on x86
|
|
break; --> compiles into 'int3' on x86
|
|
|
|
Inline assembly
|
|
---------------
|
|
Lines prefixed with ':' char are just inlined in the output assembly.
|
|
|
|
: jmp 0x8048400
|
|
: .byte 33,44
|
|
|
|
Labels
|
|
------
|
|
You can define labels using the ':' keyword like this:
|
|
|
|
:label_name:
|
|
/* loop forever */
|
|
goto(label_name)
|
|
|
|
Control flow
|
|
------------
|
|
goto (addr) -- branch execution
|
|
while (cond)
|
|
if (cond)
|
|
break () -- executes a trap instruction
|
|
|
|
Comments
|
|
--------
|
|
Supported syntax for comments are:
|
|
|
|
/* multiline comment */'
|
|
// single line comment
|
|
# single line comment
|