Skip to content

Commit

Permalink
update: windows PE arm64 exit syscall now work!
Browse files Browse the repository at this point in the history
  • Loading branch information
park671 committed Nov 21, 2024
1 parent 2814dc4 commit e6f5e07
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 17 deletions.
12 changes: 0 additions & 12 deletions generator/arm64/assembler_arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1063,26 +1063,14 @@ void generateData(MirData *mirData) {
//todo
}

void initProgramStart() {
emitLabel("_start");
binaryOp2(INST_MOV, 1, X29, 0, true);
binaryOp2(INST_MOV, 1, X30, 0, true);
binaryOpBranch(INST_BL, UNUSED, "main");
//keep the "main" ret value in X0
binaryOp2(INST_MOV, 1, X8, SYS_EXIT, true);
binaryOpSvc(INST_SVC, 0);
}

int generateArm64Target(Mir *mir) {
logd(ARM64_TAG, "arm64 target generation...");
initProgramStart();
//.text
MirMethod *mirMethod = mir->mirMethod;
while (mirMethod != nullptr) {
generateText(mirMethod);
mirMethod = mirMethod->next;
}

//.data
if (mir->mirData != nullptr) {
generateSection(SECTION_DATA);
Expand Down
9 changes: 7 additions & 2 deletions generator/arm64/binary_arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ void binaryOpStoreLoad(Arm64Inst inst, uint32_t is64Bit, Operand reg1, Operand r
}


void movInteger(Operand reg, uint64_t imm) {
void movInteger(Operand reg, int64_t imm) {
uint64_t mark = 0xffff;//use for check imm size
int e;
if (!(imm & ~mark)) {
Expand All @@ -432,6 +432,11 @@ void movInteger(Operand reg, uint64_t imm) {
emitInst(0x52a00000 | reg | imm >> 11); // movz w(reg),#(imm >> 16),lsl #16
return;
}
if (imm == -1) {
emitInst(0x92800000);// movn x0 (~#0); ~#0 == 0xFFFF... = #-1
//fixme: this is a special case.
return;
}
loge(BIN_TAG, "big imm (>16bit) need .data impl");
}

Expand Down Expand Up @@ -644,7 +649,7 @@ void binaryOpNop(Arm64Inst inst) {
/**
*
* @param inst
* @param sysCallImm always "0" on linux aarch64
* @param sysCallImm ignore on linux, must be set on windows!
*/
void binaryOpSvc(Arm64Inst inst, uint32_t sysCallImm) {
if (inst != INST_SVC) {
Expand Down
2 changes: 1 addition & 1 deletion generator/arm64/binary_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include <stdint.h>

typedef uint32_t Operand;
typedef int64_t Operand;

typedef uint32_t Inst;

Expand Down
14 changes: 14 additions & 0 deletions generator/arm64/linux_syscall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Created by Park Yu on 2024/11/21.
//
#include "linux_syscall.h"

void initLinuxArm64ProgramStart() {
emitLabel("_start");
binaryOp2(INST_MOV, 1, X29, 0, true);
binaryOp2(INST_MOV, 1, X30, 0, true);
binaryOpBranch(INST_BL, UNUSED, "main");
//keep the "main" ret value in X0
binaryOp2(INST_MOV, 1, X8, SYS_EXIT, true);
binaryOpSvc(INST_SVC, 0);
}
6 changes: 5 additions & 1 deletion generator/arm64/linux_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
#ifndef PCC_LINUX_SYSCALL_H
#define PCC_LINUX_SYSCALL_H

enum SysCallNumber{
#include "binary_arm64.h"
#include "register_arm64.h"

enum LinuxArm64SysCallNumber{
SYS_READ = 63,
SYS_WRITE = 64,
SYS_OPEN = 56,
Expand Down Expand Up @@ -37,5 +40,6 @@ enum SysCallNumber{
// 根据需要添加其他系统调用
};

void initLinuxArm64ProgramStart();

#endif //PCC_LINUX_SYSCALL_H
15 changes: 15 additions & 0 deletions generator/arm64/windows_syscall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Created by Park Yu on 2024/11/21.
//
#include "windows_syscall.h"

void initWindowsArm64ProgramStart() {
emitLabel("_start");
binaryOp2(INST_MOV, 1, X29, 0, true);
binaryOp2(INST_MOV, 1, X30, 0, true);
binaryOpBranch(INST_BL, UNUSED, "main");
//keep the "main" ret value in X0
binaryOp2(INST_MOV, 1, X1, X0, false);
binaryOp2(INST_MOV, 1, X0, INVALID_HANDLE_VALUE, true);
binaryOpSvc(INST_SVC, NtTerminateProcess);
}
24 changes: 24 additions & 0 deletions generator/arm64/windows_syscall.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// Created by Park Yu on 2024/10/17.
//

#ifndef PCC_LINUX_WINDOWS_SYSCALL_H
#define PCC_LINUX_WINDOWS_SYSCALL_H

#include "binary_arm64.h"
#include "register_arm64.h"

enum WindowsArm64SysCallNumber {
NtWriteFile = 8,
NtTerminateProcess = 44,
NtTerminateThread = 83,
// 根据需要添加其他系统调用
};

//00 00 80 92

#define INVALID_HANDLE_VALUE -1

void initWindowsArm64ProgramStart();

#endif //PCC_LINUX_WINDOWS_SYSCALL_H
5 changes: 4 additions & 1 deletion generator/assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "logger.h"
#include "arm64/assembler_arm64.h"
#include "arm64/binary_arm64.h"
#include "arm64/linux_syscall.h"
#include "arm64/windows_syscall.h"
#include "elf.h"
#include "file.h"
#include "pe.h"
Expand All @@ -22,7 +24,7 @@ void generateElfArm64(Mir *mir,
int currentOffset = 0;
int programHeaderCount = 0;
int sectionHeaderCount = 1;//shstrtab

initLinuxArm64ProgramStart();
int sectionCount = generateArm64Target(mir);
currentOffset += sizeof(Elf64_Ehdr);
programHeaderCount += sectionCount;
Expand Down Expand Up @@ -107,6 +109,7 @@ void generatePeArm64(Mir *mir,

int currentOffset = 0;
// 1. 生成指令缓冲区
initWindowsArm64ProgramStart();
int sectionCount = generateArm64Target(mir); // 根据 mir 生成指令
relocateBinary(0);
InstBuffer *instBuffer = getEmittedInstBuffer(); // 获取生成的指令缓冲区
Expand Down

0 comments on commit e6f5e07

Please sign in to comment.