Skip to content

Commit

Permalink
update: macho format partly right(not work now)
Browse files Browse the repository at this point in the history
  • Loading branch information
park671 committed Nov 22, 2024
1 parent 1eab37e commit 0c85e76
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 125 deletions.
2 changes: 1 addition & 1 deletion file/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
static const char *FILE_TAG = "file";

// 将 value 对齐到 alignment 的倍数
int alignTo(int value, int alignment) {
uint64_t alignTo(uint64_t value, uint64_t alignment) {
int remainder = value % alignment;
if (remainder == 0) {
return value; // 已对齐
Expand Down
2 changes: 1 addition & 1 deletion file/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <stdio.h>
#include <stdint.h>

int alignTo(int value, int alignment);
uint64_t alignTo(uint64_t value, uint64_t alignment);

extern void openFile(const char *fileName);

Expand Down
10 changes: 9 additions & 1 deletion generator/arm64/macos_syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@
//

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

void initMachOProgramStart() {

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, X16, MACOS_SYS_EXIT, true);
binaryOpSvc(INST_SVC, 0x80);
}
10 changes: 10 additions & 0 deletions generator/arm64/macos_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
#ifndef PCC_MACOS_SYSCALL_H
#define PCC_MACOS_SYSCALL_H

enum MacOsArm64SysCallNumber {
MACOS_SYS_SYSCALL = 0,
MACOS_SYS_EXIT = 1,
MACOS_SYS_FORK = 2,
MACOS_SYS_READ = 3,
MACOS_SYS_WRITE = 4,
MACOS_SYS_OPEN = 5,
MACOS_SYS_CLOSE = 6
};

void initMachOProgramStart();

#endif //PCC_MACOS_SYSCALL_H
3 changes: 2 additions & 1 deletion generator/arm64/windows_syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ void initWindowsArm64ProgramStart() {
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
//move the "main" ret value to X1, set X0 with "invalid handle"
//NtTerminateProcess(null, returnValue);
binaryOp2(INST_MOV, 1, X1, X0, false);
binaryOp2(INST_MOV, 1, X0, INVALID_HANDLE_VALUE, true);
binaryOpSvc(INST_SVC, NtTerminateProcess);
Expand Down
140 changes: 84 additions & 56 deletions generator/assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "file.h"
#include "pe.h"
#include "macho.h"
#include "sys/syscall.h"

static const char *ASSEMBLER_TAG = "assembler";

Expand Down Expand Up @@ -158,84 +159,111 @@ void generatePeArm64(Mir *mir,
}

void generateMachoArm64(Mir *mir,
int sharedLibrary,
const char *outputFileName) {
int sharedLibrary,
const char *outputFileName) {
if (outputFileName == nullptr) {
outputFileName = "output.macho";
}
openFile(outputFileName);

int currentOffset = 0;
const uint64_t ram_alignment = 16384;
const uint64_t file_alignment = 4;

int loadCommandCount = 0;
int sectionCount = 1; // Initial section count (__TEXT segment)
uint64_t currentFileAddr = 0;
uint64_t currentVmAddr = 0;

initMachOProgramStart();

// Generate ARM64 target code
int textSectionSize = generateArm64Target(mir);
currentOffset += sizeof(struct mach_header_64);
generateArm64Target(mir);
relocateBinary(0);
InstBuffer *instBuffer = getEmittedInstBuffer();

// Calculate offsets and counts
loadCommandCount += 2; // One LC_SEGMENT_64 and one LC_SYMTAB
currentOffset += loadCommandCount * sizeof(struct segment_command_64);
int textSectionOffset = currentOffset;
currentOffset += textSectionSize;
int stringTableOffset = currentOffset;
/**
* mach-o header
* [
* segment64: page0
* segment64: __TEXT
* segment64: lc_main
* ]
*/
currentFileAddr += sizeof(mach_header_64);//header
currentFileAddr += sizeof(segment_command_64);//__PAGE0
currentFileAddr += sizeof(segment_command_64);//__TEXT
currentFileAddr += sizeof(entry_point_command);//LC_MAIN
currentFileAddr += sizeof(section_64);//__text section

// Set program entry point
uint64_t programEntry = 0x100000000 + textSectionOffset;
uint64_t codeFileAddr = alignTo(currentFileAddr, file_alignment);

// Relocate binary
relocateBinary(0);
InstBuffer *instBuffer = getEmittedInstBuffer();
uint64_t loadCommandSize = 0;
loadCommandSize += sizeof(segment_command_64);//__PAGE0
loadCommandSize += sizeof(segment_command_64);//__TEXT
loadCommandSize += sizeof(entry_point_command);//LC_MAIN
//lc_segment64: page0
const uint64_t page0Size = 0x100000000;
uint64_t pageZeroSize = alignTo(page0Size, ram_alignment);
segment_command_64 *pageZeroLc = createSegmentCommand64("__PAGEZERO",
currentVmAddr,
pageZeroSize,
0,
0,
VM_PROT_NONE,
VM_PROT_NONE,
0,
0);
loadCommandCount++;
currentVmAddr += pageZeroSize;
currentVmAddr = alignTo(currentVmAddr, ram_alignment);

//lc_segment64: text
uint64_t textVmSize = alignTo(codeFileAddr + instBuffer->size, ram_alignment);
const char *TEXT_SEGMENT_NAME = "__TEXT";
segment_command_64 *textLc = createSegmentCommand64(TEXT_SEGMENT_NAME,
currentVmAddr,
textVmSize,
0,
textVmSize,
VM_PROT_EXECUTE | VM_PROT_READ,
VM_PROT_EXECUTE | VM_PROT_READ,
1,
0);
loadCommandCount++;
currentVmAddr += textVmSize;
currentVmAddr = alignTo(currentVmAddr, ram_alignment);

//lc_main
entry_point_command *mainLc = createEntryPointCommand(codeFileAddr, 0);
loadCommandCount++;

//section64:text
uint64_t codeVmAddr = page0Size + codeFileAddr;
section_64 *textSection = createSection64("__text",
TEXT_SEGMENT_NAME,
codeVmAddr,
instBuffer->size,
codeFileAddr,
file_alignment,
0,
0,
S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS);

// Create Mach-O header
struct mach_header_64 *machHeader = createMachHeader64(
mach_header_64 *machHeader = createMachHeader64(
CPU_TYPE_ARM64,
CPU_SUBTYPE_ARM64_ALL,
MH_EXECUTE,
loadCommandCount,
loadCommandCount * sizeof(struct segment_command_64),
loadCommandSize,
MH_NOUNDEFS | MH_PIE);

// Create __TEXT segment
struct segment_command_64 *textSegment = createSegmentCommand64(
"__TEXT",
0x100000000,
0x1000,
textSectionOffset,
textSectionSize,
VM_PROT_READ | VM_PROT_EXECUTE,
VM_PROT_READ | VM_PROT_EXECUTE,
1,
0);

// Create __text section
struct section_64 *textSection = createSection64(
"__text",
"__TEXT",
0x100000000 + textSectionOffset,
textSectionSize,
textSectionOffset,
4,
0,
0,
S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS);

// Create symbol table command
struct symtab_command *symtabCommand = createSymtabCommand(
stringTableOffset, // Offset of string table
0, // Number of symbols
stringTableOffset, // Offset of string table
0); // Size of string table

writeFileB(machHeader, sizeof(struct mach_header_64));
writeFileB(textSegment, sizeof(struct segment_command_64));
writeFileB(textSection, sizeof(struct section_64));
writeFileB(machHeader, sizeof(mach_header_64));
writeFileB(pageZeroLc, sizeof(segment_command_64));
writeFileB(textLc, sizeof(segment_command_64));
writeFileB(mainLc, sizeof(entry_point_command));
writeFileB(textSection, sizeof(section_64));
writeEmptyAlignment(file_alignment);
writeFileB(instBuffer->result, instBuffer->size);
const char *stringTable = "\0";
writeFileB(stringTable, 1);

logd(ASSEMBLER_TAG, "mach-o arm64 generation finish.");
}

Expand Down
77 changes: 49 additions & 28 deletions wrapper/macho.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@
//

#include "macho.h"
#include "logger.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static const char *MACHO_TAG = "macho";

mach_header_64 *createMachHeader64(uint32_t cputype,
uint32_t cpusubtype,
uint32_t filetype,
uint32_t ncmds,
uint32_t sizeofcmds,
uint32_t flags) {
uint32_t cpusubtype,
uint32_t filetype,
uint32_t ncmds,
uint32_t sizeofcmds,
uint32_t flags) {
// 分配内存
mach_header_64 *header = (mach_header_64 *)malloc(sizeof(mach_header_64));
mach_header_64 *header = (mach_header_64 *) malloc(sizeof(mach_header_64));

// 检查分配是否成功
if (header == NULL) {
Expand All @@ -37,16 +40,16 @@ mach_header_64 *createMachHeader64(uint32_t cputype,
}

segment_command_64 *createSegmentCommand64(const char *segname,
uint64_t vmaddr,
uint64_t vmsize,
uint64_t fileoff,
uint64_t filesize,
uint32_t maxprot,
uint32_t initprot,
uint32_t nsects,
uint32_t flags) {
uint64_t vmaddr,
uint64_t vmsize,
uint64_t fileoff,
uint64_t filesize,
uint32_t maxprot,
uint32_t initprot,
uint32_t nsects,
uint32_t flags) {
// 分配内存
segment_command_64 *segment = (segment_command_64 *)malloc(sizeof(segment_command_64));
segment_command_64 *segment = (segment_command_64 *) malloc(sizeof(segment_command_64));

// 检查分配是否成功
if (segment == NULL) {
Expand All @@ -71,11 +74,11 @@ segment_command_64 *createSegmentCommand64(const char *segname,
}

symtab_command *createSymtabCommand(uint32_t symoff,
uint32_t nsyms,
uint32_t stroff,
uint32_t strsize) {
uint32_t nsyms,
uint32_t stroff,
uint32_t strsize) {
// 分配内存
symtab_command *symtab = (symtab_command *)malloc(sizeof(symtab_command));
symtab_command *symtab = (symtab_command *) malloc(sizeof(symtab_command));

// 检查分配是否成功
if (symtab == NULL) {
Expand All @@ -95,16 +98,16 @@ symtab_command *createSymtabCommand(uint32_t symoff,
}

section_64 *createSection64(const char *sectname,
const char *segname,
uint64_t addr,
uint64_t size,
uint32_t offset,
uint32_t align,
uint32_t reloff,
uint32_t nreloc,
uint32_t flags) {
const char *segname,
uint64_t addr,
uint64_t size,
uint32_t offset,
uint32_t align,
uint32_t reloff,
uint32_t nreloc,
uint32_t flags) {
// 分配内存
section_64 *section = (section_64 *)malloc(sizeof(section_64));
section_64 *section = (section_64 *) malloc(sizeof(section_64));

// 检查分配是否成功
if (section == NULL) {
Expand All @@ -129,3 +132,21 @@ section_64 *createSection64(const char *sectname,
return section; // 返回已填充的区块指针
}

entry_point_command *createEntryPointCommand(uint64_t entryoff, uint64_t stacksize) {
// 分配内存
entry_point_command *entryPointCmd = (entry_point_command *) malloc(sizeof(entry_point_command));

// 检查分配是否成功
if (entryPointCmd == nullptr) {
loge(MACHO_TAG, "Error: Memory allocation failed\n");
return nullptr;
}

// 填充 entry_point_command 的字段
entryPointCmd->cmd = LC_MAIN; // 设置命令类型为 LC_MAIN
entryPointCmd->cmdsize = sizeof(entry_point_command); // 命令大小为 24 字节
entryPointCmd->entryoff = entryoff; // 程序入口偏移(从 __TEXT 段的起始位置计算)
entryPointCmd->stacksize = stacksize; // 初始栈大小(如果为 0,则使用默认值)

return entryPointCmd; // 返回已填充的 entry_point_command 指针
}
Loading

0 comments on commit 0c85e76

Please sign in to comment.