Concept language with mix of assembly and C headers
0

Configure Feed

Select the types of activity you want to include in your feed.

Rust 97.3%
Other 2.7%
26 2 0

Clone this repository

https://tangled.org/solune.tngl.sh/retlang https://tangled.org/did:plc:rpl5glmp2iyn225p3aptiugp
git@tangled.org:solune.tngl.sh/retlang git@tangled.org:did:plc:rpl5glmp2iyn225p3aptiugp

For self-hosted knots, clone URLs may differ based on your setup.



README.md

Return Oriented Programming Language#

Language inspired by ROP concept with mix of assembly syntax and C headers.

It supports linking with external C libraries by either specifying the library name or providing library path to CLI.

Due to simplistic nature of the language, support for imports and external gadgets is not planned.

Currently address space size is limited by constant defined at compiled time.

Targets#

  • Any target that is supported by C
  • WASM (needs testing)

Usage#

1. Compile retc#

git clone https://github.com/isofinly/RetLang.git
cd RetLang/backend
cargo build --release

2. Place retc to your $PATH and then you can use it to compile your ROP programs.#

$ retc -h
RET-lang toolchain

Usage: retc <COMMAND>

Commands:
  lex        [aliases: lx]
  compile    [aliases: c]
  parse      [aliases: p]
  transpile  [aliases: t]
  help       Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

3. Create simple program#

external: <stdio.h>

gadget main:
    printf("%s", "Goodbye!")
ret

stack: [main]

4. Compilation#

4.1 Direct compilation#

$ retc c program.ret

or specify output file

$ retc c program.ret -o program

or link with library

$ retc c program.ret -l z

Inspecting the binary:

$ otool -L .build/main
.build/main:
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)

4.2 Compilation with external C compiler#

$ retc t program.ret .build/custom.c

then run your compiler

$ tcc -Wall -O3 .build/custom.c -o .build/main

5. Debugging IR#

You can view lexer, parser outputs by using the lex or parse commands.

Grammar#

header_name = identifier , { "." , identifier } ;

external = "external" , ":" ,
                 ( "<" , header_name , ">"
                 | '"' , header_name , '"' ) ;

program = { gadget_def } , stack_init ;

(* Gadgets are the fundamental building blocks *)
gadget_def = "gadget" , identifier , ":" , gadget_body ;

gadget_body = { instruction } , return_stmt ;

(* Instructions can only manipulate data, not control flow *)
instruction = assignment
            | call
            | stack_op
            | arithmetic
            | memory_op
            | conditional_mod
            ;

assignment = identifier , "=" , expression ;

stack_op = "push" , expression
         | "pop" , identifier
         | "peek" , identifier , "[" , expression "]"  (* peek at stack offset *)
         | "stack_swap" , expression , expression      (* swap stack positions *)
         ;

arithmetic = identifier , arith_op , "=" , expression , arith_op , expression ;
arith_op = "+" | "-" | "*" | "/" | "%" | "&" | "|" | "^" | "<<" | ">>" ;

memory_op = "store" , expression , expression  (* store value at address *)
          | "load" , identifier , expression   (* load from address *)
          ;

conditional_mod = "if" , condition , "then" , identifier , "=" , expression ;

condition = expression , comp_op , expression ;
comp_op = "==" | "!=" | "<" | "<=" | ">" | ">=" ;

(* every gadget MUST end with a return that pops next address *)
return_stmt = "ret" , [ expression ] ;  (* optional value to push before returning *)

expression = literal
           | identifier
           | memory_ref
           | stack_ref
           | binary_expr
           | unary_expr
           | call
           ;

memory_ref = "[" , expression , "]" ;
stack_ref = "stack" , "[" , expression , "]" ;

binary_expr = expression , ( "+" | "-" | "*" | "/" | "%" | "&" | "|" | "^" | "<<" | ">>" ) , expression ;

unary_expr = "!" , expression ;

call = identifier , "(" , [ expression , { "," , expression } ] , ")" ;

(* Determines entrypoint *)
stack_init = "stack" , ":" , "[" , { identifier } , "]" ;

literal = int_literal | string_literal ;
identifier = letter , { letter | digit | "_" } ;
int_literal = [ "-" ] , digit , { digit } ;
string_literal = '"' , { ? any character except " ? } , '"' ;

letter = "a" | ... | "z" | "A" | ... | "Z" ;
digit = "0" | ... | "9" ;

comment = "//" , { ? any char except newline ? } ;

License#

See LICENSE.