Skip to content

Commit

Permalink
Add timer-based metering for x86
Browse files Browse the repository at this point in the history
  • Loading branch information
zyedidia committed Nov 14, 2024
1 parent e2f3117 commit 2181a7d
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 42 deletions.
6 changes: 6 additions & 0 deletions lfi-leg/amd64/amd64.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void amd64_storespass(struct op*);
void amd64_declpass(struct op*);
void amd64_tlspass(struct op*);
void amd64_syscallpass(struct op*);
void amd64_meterpass(struct op*);

void amd64_pextelim(struct op*);

Expand All @@ -32,6 +33,7 @@ static Pass passes[] = {
(Pass) { .fn = &amd64_storespass },
(Pass) { .fn = &amd64_branchpass },
(Pass) { .fn = &amd64_declpass, .disabled = true },
(Pass) { .fn = &amd64_meterpass, .disabled = true },
(Pass) { .fn = &amd64_tlspass },
(Pass) { .fn = &amd64_syscallpass },
};
Expand Down Expand Up @@ -77,6 +79,10 @@ amd64_rewrite(FILE* input, struct output* output)
passes[i].disabled = false;
else if (passes[i].fn == &amd64_declpass)
passes[i].disabled = true;
if (args.meter != METER_NONE && passes[i].fn == &amd64_meterpass)
passes[i].disabled = false;
else if (passes[i].fn == &amd64_meterpass)
passes[i].disabled = true;
if (args.allowtls && passes[i].fn == &amd64_tlspass)
passes[i].disabled = true;
else if (passes[i].fn == &amd64_tlspass)
Expand Down
34 changes: 17 additions & 17 deletions lfi-leg/amd64/decl.leg
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,33 @@
%}

ShiftInsn = (
(s:ShiftQ SEP r:REG COMMA x:REG) {
(s:ShiftQ SEP '%cl' - COMMA x1:REG COMMA x2:REG) {
mkdirective(".bundle_lock");
mkinsn("andq $0x3f, %s", r.val);
mkinsn("%s %s, %s", s.val, r.val, x.val);
mkinsn("andb $0x3f, %%cl");
mkinsn("%s %%cl, %s, %s", s.val, x1.val, x2.val);
mkdirective(".bundle_unlock");
rfree(r); rfree(x);
rfree(x1); rfree(x2);
}
| (s:ShiftL SEP r:REG COMMA x:REG) {
| (s:ShiftL SEP '%cl' - COMMA x1:REG COMMA x2:REG) {
mkdirective(".bundle_lock");
mkinsn("andl $0x1f, %s", r.val);
mkinsn("%s %s, %s", s.val, r.val, x.val);
mkinsn("andb $0x1f, %%cl");
mkinsn("%s %%cl, %s, %s", s.val, x1.val, x2.val);
mkdirective(".bundle_unlock");
rfree(r); rfree(x);
rfree(x1); rfree(x2);
}
| (s:ShiftW SEP r:REG COMMA x:REG) {
| (s:ShiftW SEP '%cl' - COMMA x1:REG COMMA x2:REG) {
mkdirective(".bundle_lock");
mkinsn("andw $0xf, %s", r.val);
mkinsn("%s %s, %s", s.val, r.val, x.val);
mkinsn("andb $0xf, %%cl");
mkinsn("%s %%cl, %s, %s", s.val, x1.val, x2.val);
mkdirective(".bundle_unlock");
rfree(r); rfree(x);
rfree(x1); rfree(x2);
}
| (s:ShiftB SEP r:REG COMMA x:REG) {
| (s:ShiftB SEP '%cl' - COMMA x1:REG COMMA x2:REG) {
mkdirective(".bundle_lock");
mkinsn("andl $0x7, %s", r.val);
mkinsn("%s %s, %s", s.val, r.val, x.val);
mkinsn("andb $0x7, %%cl");
mkinsn("%s %%cl, %s, %s", s.val, x1.val, x2.val);
mkdirective(".bundle_unlock");
rfree(r); rfree(x);
rfree(x1); rfree(x2);
}
)

Expand All @@ -47,7 +47,7 @@ ShiftL = < Shift 'l' > { $$ = (Result) { .val = strndup(yytext, yyleng) } }
ShiftW = < Shift 'w' > { $$ = (Result) { .val = strndup(yytext, yyleng) } }
ShiftB = < Shift 'b' > { $$ = (Result) { .val = strndup(yytext, yyleng) } }

Shift = ('shr' | 'shl')
Shift = ('shrd' | 'shld')

%%

Expand Down
6 changes: 6 additions & 0 deletions lfi-leg/amd64/flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ amd64_getflags(enum flags compiler)
flags = xasprintf("%s -mllvm -align-labels=16", flags);
else if (args.cfi == CFI_BUNDLE32)
flags = xasprintf("%s -mllvm -align-labels=32", flags);
if (args.meter != METER_NONE)
flags = xasprintf("%s -mllvm --reserve-r12", flags);
break;
case FLAGS_GCC:
if (args.boxtype > BOX_BUNDLEJUMPS)
Expand All @@ -37,12 +39,16 @@ amd64_getflags(enum flags compiler)
flags = xasprintf("%s -falign-labels=32 -falign-functions=32", flags);
if (args.p2size == 0)
flags = xasprintf("%s -ffixed-r15", flags);
if (args.meter != METER_NONE)
flags = xasprintf("%s -ffixed-r12", flags);
break;
default:
assert(0);
}
if (!args.allowtls && compiler != FLAGS_POSTLINK) {
flags = xasprintf("%s -mno-tls-direct-seg-refs -mtls-dialect=gnu2", flags);
}
if (args.sysexternal)
flags = xasprintf("%s -ffixed-r13", flags);
return flags;
}
1 change: 1 addition & 0 deletions lfi-leg/amd64/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ leg_inputs = [
'decl.leg',
'pextelim.leg',
'tls.leg',
'meter.leg',
]

leg_addr_inputs = [
Expand Down
80 changes: 80 additions & 0 deletions lfi-leg/amd64/meter.leg
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
%{
#include "amd64/amd64.h"
#include "op.h"
#include "args.h"
#include "util.h"

#define YY_INPUT(ctx, buf, result, max_size) \
{ \
char yyc = ctx->op->text[ctx->idx]; \
ctx->idx += yyc != 0; \
result = yyc == 0 ? 0 : (*(buf) = yyc, 1); \
} \

static void
timermeter(bool indirect)
{
mkinsn("leaq 0(%%r12), %%r12");
}
%}

Top = IndBranch | Branch

IndBranch = b:INDBRANCH SEP '*' r:XREG {
timermeter(true);
mkinsn("%s *%s", b.val, r.val);
rfree(b); rfree(r);
}

Branch = b:DIRBRANCH SEP name:NAME {
mkdirective(".bundle_lock");
timermeter(false);
mkinsn("%s %s", b.val, name.val);
mkdirective(".bundle_unlock");
rfree(b); rfree(name);
}

INDBRANCH = < ('notrack'? ('jmp' 'q'?) | ('call' 'q'?)) > {
$$ = (Result) { .val = strndup(yytext, yyleng) };
}

DIRBRANCH = < (JCC | JMP) > {
$$ = (Result) { .val = strndup(yytext, yyleng) };
}

JMP = 'jmp' | 'call'

JCC = 'jo'
| 'jno'
| 'jc' | 'jb'
| 'jae' | 'jnb'
| 'je' | 'jz'
| 'jne' | 'jnz'
| 'jna' | 'jbe'
| 'ja' | 'jnbe'
| 'js'
| 'jns'
| 'jp' | 'jpe'
| 'jnp' | 'jpo'
| 'jl' | 'jnge'
| 'jge' | 'jnl'
| 'jle' | 'jng'
| 'jg' | 'jnle'

%%

void
amd64_meterpass(struct op* op)
{
if (!op->insn)
return;
yycontext ctx;
memset(&ctx, 0, sizeof(yycontext));
ctx.op = op;
oplocate(op);
if (yyparse(&ctx)) {
opremove(op);
opfree(op);
}
yyrelease(&ctx);
}
14 changes: 5 additions & 9 deletions lfi-leg/amd64/syscall.leg
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,11 @@
Top = Syscall | Retcall

Syscall = 'syscall' - {
if (!args.decl) {
mkdirective(".bundle_lock");
mkinsn("leaq 1024f(%%rip), %%r11");
mkinsn("jmpq *(%%r14)");
mklabel("1024");
mkdirective(".bundle_unlock");
} else {
mkinsn("syscall");
}
mkdirective(".bundle_lock");
mkinsn("leaq 1024f(%%rip), %%r11");
mkinsn("jmpq *(%%r14)");
mklabel("1024");
mkdirective(".bundle_unlock");
}

Retcall = 'libret' - {
Expand Down
10 changes: 5 additions & 5 deletions lfi-leg/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ enum boxtype {
};

enum meter {
METER_NONE,
METER_BRANCH,
METER_BRANCH_RESUME,
METER_FP,
METER_TIMER,
METER_NONE = 0,
METER_BRANCH = 1,
METER_BRANCH_RESUME = 2,
METER_FP = 3,
METER_TIMER = 4,
};

enum flags {
Expand Down
17 changes: 6 additions & 11 deletions lfi-leg/test/amd64/decl.s
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
shrq %rdi, %rax
shrdq %cl, %rdi, %rax
>>>
.bundle_align_mode 4
.bundle_lock
andq $0x3f, %rdi
shrq %rdi, %rax
andb $0x3f, %cl
shrdq %cl, %rdi, %rax
.bundle_unlock
------
shrl %edi, %eax
shrdl %cl, %edi, %eax
>>>
.bundle_align_mode 4
.bundle_lock
andl $0x1f, %edi
shrl %edi, %eax
andb $0x1f, %cl
shrdl %cl, %edi, %eax
.bundle_unlock
------
callq *(%rax)
Expand All @@ -25,8 +25,3 @@ cmpq %rax, %rax
callq *%r11
.bundle_unlock
.p2align 4
------
syscall
>>>
.bundle_align_mode 4
syscall
25 changes: 25 additions & 0 deletions lfi-leg/test/amd64/meter_timer.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
jmp foo
>>>
.bundle_align_mode 4
.bundle_lock
leaq 0(%r12), %r12
jmp foo
.bundle_unlock
------
jz foo
>>>
.bundle_align_mode 4
.bundle_lock
leaq 0(%r12), %r12
jz foo
.bundle_unlock
------
jmpq *%rax
>>>
.bundle_align_mode 4
.bundle_lock
andl $0xfffffff0, %eax
orq %r14, %rax
leaq 0(%r12), %r12
jmpq *%rax
.bundle_unlock
1 change: 1 addition & 0 deletions lfi-leg/test/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ tests = {
'amd64/syscall.s',
'amd64/variable.s',
'amd64/tls.s',
'amd64/meter_timer.s',
],
'riscv64': [
'riscv64/arith.s',
Expand Down

0 comments on commit 2181a7d

Please sign in to comment.