ASLR in action

This commit is contained in:
nora 2024-11-29 22:50:26 +01:00
parent 96f2dcf8af
commit 741b1000b3
2 changed files with 49 additions and 10 deletions

View file

@ -105,6 +105,7 @@ function lex(input) {
case ",": case ",":
case ";": case ";":
case "+": case "+":
case "-":
case "=": { case "=": {
tokens.push({ tokens.push({
kind: head, kind: head,
@ -362,6 +363,9 @@ function parse(tokens) {
const params = []; const params = [];
while (tok.peek()?.kind !== ")") { while (tok.peek()?.kind !== ")") {
if (params.length > 0) {
tok.expect(",", "function parameter separator");
}
const type = parseType(tok, "function parameter"); const type = parseType(tok, "function parameter");
const name = tok.next("function name"); const name = tok.next("function name");
if (name.kind !== "ident") { if (name.kind !== "ident") {
@ -382,8 +386,9 @@ function parse(tokens) {
return { return {
kind: "function", kind: "function",
ret,
name, name,
params,
ret,
body, body,
}; };
} }
@ -481,6 +486,8 @@ function lower(ast) {
const REG_SI = RM_SI; const REG_SI = RM_SI;
const REG_DI = RM_DI; const REG_DI = RM_DI;
const PARAM_CALLCONV_REGISTERS = [REG_DI, REG_SI, REG_D, REG_C];
const REG_IGNORED = 0; const REG_IGNORED = 0;
function modRm(mod, reg, rm) { function modRm(mod, reg, rm) {
assert(mod <= 0b11); assert(mod <= 0b11);
@ -564,6 +571,15 @@ function lower(ast) {
]); ]);
} }
subRegs(reg1, reg2) {
// REX.W + 03 /r | ADD r64, r/m64 ; Add r/m64 to r64
this.#append([
rex(REX.W_64_BIT_OPERAND_SIZE, 0, 0, 0),
0x2b,
modRm(MOD_REG, reg1, reg2),
]);
}
movRegToStackOffset(offset, reg) { movRegToStackOffset(offset, reg) {
// mov [rsp+{offset}], reg // mov [rsp+{offset}], reg
// 89 /r, MOV r/m64, r64 // 89 /r, MOV r/m64, r64
@ -656,6 +672,7 @@ function lower(ast) {
} }
function codegenExpr(ctx, expr) { function codegenExpr(ctx, expr) {
assert(!Number.isNaN(ctx.offset));
const { ib, variables } = ctx; const { ib, variables } = ctx;
switch (expr.kind) { switch (expr.kind) {
case "call": { case "call": {
@ -683,7 +700,7 @@ function lower(ast) {
.reverse() .reverse()
.find((v) => v.name === expr.string); .find((v) => v.name === expr.string);
assert(offset); assert(offset);
ib.movStackOffsetToReg(offset.stackOffset, REG_A); ib.movStackOffsetToReg(offset.stackOffset + ctx.offset, REG_A);
break; break;
} }
case "+": { case "+": {
@ -691,12 +708,21 @@ function lower(ast) {
// evaluate the RHS, then restore the LHS and perform the operation. // evaluate the RHS, then restore the LHS and perform the operation.
codegenExpr(ctx, expr.lhs); codegenExpr(ctx, expr.lhs);
ib.pushReg64(REG_A); // push rax ib.pushReg64(REG_A); // push rax
codegenExpr(ctx, expr.rhs); codegenExpr({ ...ctx, offset: ctx.offset + 8 }, expr.rhs);
ib.popReg64(REG_C); // pop rcx ib.popReg64(REG_C); // pop rcx
ib.addRegs(REG_A, REG_C); ib.addRegs(REG_A, REG_C);
break; break;
} }
case "-": {
codegenExpr(ctx, expr.rhs);
ib.pushReg64(REG_A); // push rax
codegenExpr({ ...ctx, offset: ctx.offset + 8 }, expr.lhs);
ib.popReg64(REG_C); // pop rcx
ib.subRegs(REG_A, REG_C);
break;
}
default: { default: {
throw new Error(`unsupported expr: ${expr.kind}`); throw new Error(`unsupported expr: ${expr.kind}`);
} }
@ -707,15 +733,28 @@ function lower(ast) {
const ib = new InstBuilder(); const ib = new InstBuilder();
const variables = []; const variables = [];
assert(func.params.length <= 4);
func.params.forEach((param, i) => {
assert(param.type.kind === "int");
const offset = ib.reserveStack(4);
ib.movRegToStackOffset(offset, PARAM_CALLCONV_REGISTERS[i]);
variables.push({
name: param.name,
stackOffset: offset,
});
});
for (const stmt of func.body) { for (const stmt of func.body) {
const ctx = { ib, variables, offset: 0 };
switch (stmt.kind) { switch (stmt.kind) {
case "expr": { case "expr": {
codegenExpr({ ib, variables }, stmt.expr); codegenExpr(ctx, stmt.expr);
break; break;
} }
case "return": { case "return": {
if (stmt.rhs) { if (stmt.rhs) {
codegenExpr({ ib, variables }, stmt.rhs); codegenExpr(ctx, stmt.rhs);
} }
ib.finish(); ib.finish();
ib.ret(); ib.ret();
@ -724,7 +763,7 @@ function lower(ast) {
case "declaration": { case "declaration": {
assert(stmt.type === "int"); assert(stmt.type === "int");
if (stmt.init) { if (stmt.init) {
codegenExpr({ ib, variables }, stmt.init); codegenExpr(ctx, stmt.init);
} }
const slot = ib.reserveStack(4); const slot = ib.reserveStack(4);
variables.push({ variables.push({
@ -1163,7 +1202,7 @@ function assert(condition) {
function assertDefined(...values) { function assertDefined(...values) {
values.forEach((value, i) => { values.forEach((value, i) => {
if (value === null || value === undefined) { if (value === null || value === undefined) {
throw new Error(`assertion failed, argument ${i} undefined or null`); throw new Error(`assertion failed, argument ${i} undefined or nu ll`);
} }
}); });
} }

View file

@ -1,10 +1,10 @@
// #include<elf.h> // #include<elf.h>
int main(int argc) int main(int argc, int argv)
{ {
int x = 100; int x = 100;
int x = 200; thisismyfakeconstantbecauseidonthaveconstant(x - 1);
return x; return argv;
} }
int thisismyfakeconstantbecauseidonthaveconstant(int x) int thisismyfakeconstantbecauseidonthaveconstant(int x)