Skip to content

Commit

Permalink
Merge branch 'feature/apple-macho'
Browse files Browse the repository at this point in the history
  • Loading branch information
tyfkda committed Jun 29, 2024
2 parents 6c6d0b4 + 3903601 commit 1792b04
Show file tree
Hide file tree
Showing 27 changed files with 1,059 additions and 330 deletions.
10 changes: 10 additions & 0 deletions include/mach-o/arm64/reloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

// MachoArm64RelocationType
#define ARM64_RELOC_UNSIGNED 0
#define ARM64_RELOC_BRANCH26 2
#define ARM64_RELOC_PAGE21 3
#define ARM64_RELOC_PAGEOFF12 4
#define ARM64_RELOC_GOT_LOAD_PAGE21 5
#define ARM64_RELOC_GOT_LOAD_PAGEOFF12 6
#define ARM64_RELOC_ADDEND 10
82 changes: 82 additions & 0 deletions include/mach-o/loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#pragma once

#include <stdint.h>

struct mach_header_64 {
uint32_t magic;
int32_t cputype;
int32_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
};

#define MH_MAGIC_64 0xfeedfacf

#define MH_OBJECT 0x1
#define MH_EXECUTE 0x2

#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000

struct load_command {
uint32_t cmd;
uint32_t cmdsize;
};

#define LC_SYMTAB 0x2
#define LC_SEGMENT_64 0x19
#define LC_BUILD_VERSION 0x32

struct symtab_command {
uint32_t cmd;
uint32_t cmdsize;
uint32_t symoff;
uint32_t nsyms;
uint32_t stroff;
uint32_t strsize;
};

struct segment_command_64 { /* for 64-bit architectures */
uint32_t cmd;
uint32_t cmdsize;
char segname[16];
uint64_t vmaddr;
uint64_t vmsize;
uint64_t fileoff;
uint64_t filesize;
int32_t maxprot;
int32_t initprot;
uint32_t nsects;
uint32_t flags;
};

struct build_version_command {
uint32_t cmd;
uint32_t cmdsize;
uint32_t platform;
uint32_t minos;
uint32_t sdk;
uint32_t ntools;
};

#define PLATFORM_MACOS 1

struct section_64 { /* for 64-bit architectures */
char sectname[16];
char segname[16];
uint64_t addr;
uint64_t size;
uint32_t offset;
uint32_t align;
uint32_t reloff;
uint32_t nreloc;
uint32_t flags;
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
};

#define S_ATTR_PURE_INSTRUCTIONS 0x80000000
#define S_ATTR_SOME_INSTRUCTIONS 0x00000400
27 changes: 27 additions & 0 deletions include/mach-o/nlist.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <stdint.h>

#define N_STAB 0xe0
#define N_PEXT 0x10
#define N_TYPE 0x0e
#define N_EXT 0x01

#define N_UNDF 0x0
#define N_ABS 0x2
#define N_SECT 0xe
#define N_PBUD 0xc
#define N_INDR 0xa

struct nlist_64 {
union {
uint32_t n_strx;
} n_un;
uint8_t n_type;
uint8_t n_sect;
uint16_t n_desc;
uint64_t n_value;
};

#define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f)
#define SET_COMM_ALIGN(n_desc, align) (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8))
14 changes: 14 additions & 0 deletions include/mach-o/reloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <stdint.h>

struct relocation_info {
int32_t r_address;
uint32_t
r_symbolnum : 24,
r_pcrel : 1,
r_length : 2,
r_extern : 1,
r_type : 4;
};
#define R_ABS 0
13 changes: 13 additions & 0 deletions include/mach-o/x86_64/reloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

enum reloc_type_x86_64 {
X86_64_RELOC_UNSIGNED,
X86_64_RELOC_SIGNED,
X86_64_RELOC_BRANCH,
X86_64_RELOC_GOT_LOAD,
X86_64_RELOC_GOT,
X86_64_RELOC_SUBTRACTOR,
X86_64_RELOC_SIGNED_1,
X86_64_RELOC_SIGNED_2,
X86_64_RELOC_SIGNED_4,
};
19 changes: 19 additions & 0 deletions include/mach/machine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#define CPU_TYPE_ARM ((cpu_type_t)12)
#define CPU_TYPE_X86 ((cpu_type_t)7)

#define CPU_ARCH_MASK 0xff000000
#define CPU_ARCH_ABI64 0x01000000

#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64)

#define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3)

#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)

#define CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t)0)

typedef int integer_t;
typedef integer_t cpu_type_t;
typedef integer_t cpu_subtype_t;
16 changes: 8 additions & 8 deletions src/as/arch/aarch64/asm_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ static unsigned char *asm_ldrstr(Inst *inst, Code *code) {
if (opr2->type == INDIRECT) {
assert(opr2->indirect.reg.size == REG64);
// assert(opr2->indirect.offset == NULL || opr2->indirect.offset->kind == EX_FIXNUM);
Expr *offset_expr = opr2->indirect.offset;
int64_t offset = offset_expr != NULL && offset_expr->kind == EX_FIXNUM ? offset_expr->fixnum : 0;
ExprWithFlag *offset_expr = &opr2->indirect.offset;
int64_t offset = offset_expr->expr != NULL && offset_expr->expr->kind == EX_FIXNUM ? offset_expr->expr->fixnum : 0;
assert(offset < (1 << (6 + 3)) && offset >= -(1 << (6 + 3)));
uint32_t base = opr2->indirect.reg.no;
uint32_t prepost = kPrePost[opr2->indirect.prepost];
Expand Down Expand Up @@ -316,8 +316,8 @@ static unsigned char *asm_ldpstp(Inst *inst, Code *code) {
uint32_t sz = opr1->reg.size == REG64 ? 1 : 0;
Operand *opr3 = &inst->opr[2];
assert(opr3->indirect.reg.size == REG64);
assert(opr3->indirect.offset == NULL || opr3->indirect.offset->kind == EX_FIXNUM);
int64_t offset = opr3->indirect.offset != NULL ? opr3->indirect.offset->fixnum : 0;
assert(opr3->indirect.offset.expr == NULL || opr3->indirect.offset.expr->kind == EX_FIXNUM);
int64_t offset = opr3->indirect.offset.expr != NULL ? opr3->indirect.offset.expr->fixnum : 0;
assert(offset < (1 << (6 + 3)) && offset >= -(1 << (6 + 3)));
uint32_t base = opr3->indirect.reg.no;
uint32_t prepost = kPrePost[opr3->indirect.prepost];
Expand Down Expand Up @@ -400,8 +400,8 @@ static unsigned char *asm_f_ldrstr(Inst *inst, Code *code) {
if (opr2->type == INDIRECT) {
assert(opr2->indirect.reg.size == REG64);
// assert(opr2->indirect.offset == NULL || opr2->indirect.offset->kind == EX_FIXNUM);
Expr *offset_expr = opr2->indirect.offset;
int64_t offset = offset_expr != NULL && offset_expr->kind == EX_FIXNUM ? offset_expr->fixnum : 0;
ExprWithFlag *offset_expr = &opr2->indirect.offset;
int64_t offset = offset_expr->expr != NULL && offset_expr->expr->kind == EX_FIXNUM ? offset_expr->expr->fixnum : 0;
assert(offset < (1 << (6 + 3)) && offset >= -(1 << (6 + 3)));
uint32_t base = opr2->indirect.reg.no;
uint32_t prepost = kPrePost[opr2->indirect.prepost];
Expand Down Expand Up @@ -456,8 +456,8 @@ static unsigned char *asm_f_ldpstp(Inst *inst, Code *code) {
uint32_t sz = opr1->reg.size == REG64 ? 1 : 0;
Operand *opr3 = &inst->opr[2];
assert(opr3->indirect.reg.size == REG64);
assert(opr3->indirect.offset->kind == EX_FIXNUM);
int64_t offset = opr3->indirect.offset->fixnum;
assert(opr3->indirect.offset.expr->kind == EX_FIXNUM);
int64_t offset = opr3->indirect.offset.expr->fixnum;
assert(offset < (1 << (6 + 3)) && offset >= -(1 << (6 + 3)));
uint32_t base = opr3->indirect.reg.no;
uint32_t prepost = kPrePost[opr3->indirect.prepost];
Expand Down
13 changes: 11 additions & 2 deletions src/as/arch/aarch64/inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,25 @@ enum OperandType {
FREG, // freg
};

#define LF_PAGE (1 << 0)
#define LF_PAGEOFF (1 << 1)
#define LF_GOT (1 << 2)

typedef struct {
Expr *expr;
int flag;
} ExprWithFlag;

typedef struct {
enum OperandType type;
union {
Reg reg;
int64_t immediate;
struct {
Expr *expr;
ExprWithFlag expr;
} direct;
struct {
Expr *offset;
ExprWithFlag offset;
Reg reg;
int prepost; // 0=none, 1=pre, 2=post
} indirect;
Expand Down
36 changes: 22 additions & 14 deletions src/as/arch/aarch64/ir_asm_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,12 @@ bool resolve_relative_address(Vector **section_irs, Table *label_table, Vector *
switch (inst->op) {
case ADD_I:
if (inst->opr[2].type == DIRECT) {
Value value = calc_expr(label_table, inst->opr[2].direct.expr);
ExprWithFlag *expr = &inst->opr[2].direct.expr;
Value value = calc_expr(label_table, expr->expr);
if (value.label != NULL) {
if (value.flag == LF_PAGEOFF) {
if (expr->flag == LF_PAGEOFF || expr->flag == (LF_GOT | LF_PAGEOFF)) {
UnresolvedInfo *info = malloc_or_die(sizeof(*info));
info->kind = UNRES_PCREL_LO;
info->kind = expr->flag == LF_PAGEOFF ? UNRES_PCREL_LO : UNRES_GOT_LO;
info->label = value.label;
info->src_section = sec;
info->offset = address - start_address;
Expand All @@ -99,16 +100,17 @@ bool resolve_relative_address(Vector **section_irs, Table *label_table, Vector *
break;
case LDR:
case STR:
if (inst->opr[1].type == INDIRECT && inst->opr[1].indirect.offset != NULL) {
Value value = calc_expr(label_table, inst->opr[1].indirect.offset);
if (inst->opr[1].type == INDIRECT && inst->opr[1].indirect.offset.expr != NULL) {
ExprWithFlag *offset = &inst->opr[1].indirect.offset;
Value value = calc_expr(label_table, offset->expr);
if (value.label != NULL) {
static const int table[][2] = {
{ LF_GOT, UNRES_GOT_HI },
{ LF_GOT | LF_PAGEOFF, UNRES_GOT_LO },
};
size_t i;
for (i = 0; i < ARRAY_SIZE(table); ++i) {
if (table[i][0] == value.flag)
if (table[i][0] == offset->flag)
break;
}
if (i >= ARRAY_SIZE(table)) {
Expand All @@ -127,16 +129,17 @@ bool resolve_relative_address(Vector **section_irs, Table *label_table, Vector *
break;
case ADRP:
if (inst->opr[1].type == DIRECT) {
Value value = calc_expr(label_table, inst->opr[1].direct.expr);
ExprWithFlag *expr = &inst->opr[1].direct.expr;
Value value = calc_expr(label_table, expr->expr);
if (value.label != NULL) {
static const int table[][2] = {
{ 0, UNRES_PCREL_HI },
{ LF_PAGE, UNRES_PCREL_HI },
{ LF_GOT, UNRES_GOT_HI },
{ LF_GOT | LF_PAGE, UNRES_GOT_HI },
};
size_t i;
for (i = 0; i < ARRAY_SIZE(table); ++i) {
if (table[i][0] == value.flag)
if (table[i][0] == expr->flag)
break;
}
if (i >= ARRAY_SIZE(table)) {
Expand All @@ -159,7 +162,7 @@ bool resolve_relative_address(Vector **section_irs, Table *label_table, Vector *
case BHI: case BLS: case BGE: case BLT:
case BGT: case BLE: case BAL: case BNV:
if (inst->opr[0].type == DIRECT) {
Value value = calc_expr(label_table, inst->opr[0].direct.expr);
Value value = calc_expr(label_table, inst->opr[0].direct.expr.expr);
if (value.label != NULL) {
LabelInfo *label_info = table_get(label_table, value.label);
if (label_info == NULL) {
Expand Down Expand Up @@ -198,7 +201,7 @@ bool resolve_relative_address(Vector **section_irs, Table *label_table, Vector *

case BL:
if (inst->opr[0].type == DIRECT) {
Value value = calc_expr(label_table, inst->opr[0].direct.expr);
Value value = calc_expr(label_table, inst->opr[0].direct.expr.expr);
if (value.label != NULL) {
UnresolvedInfo *info = malloc_or_die(sizeof(*info));
info->kind = UNRES_CALL;
Expand All @@ -220,14 +223,15 @@ bool resolve_relative_address(Vector **section_irs, Table *label_table, Vector *
case IR_EXPR_LONG:
case IR_EXPR_QUAD:
{
Value value = calc_expr(label_table, ir->expr);
Value value = calc_expr(label_table, ir->expr.expr);
assert(value.label != NULL);
UnresolvedInfo *info = malloc_or_die(sizeof(*info));
info->kind = UNRES_ABS64; // TODO:
info->label = value.label;
info->src_section = sec;
info->offset = address - start_address;
info->add = value.offset;
ir->expr.addend = value.offset;
vec_push(unresolved, info);
}
break;
Expand Down Expand Up @@ -268,9 +272,13 @@ void emit_irs(Vector **section_irs) {
case IR_EXPR_LONG:
case IR_EXPR_QUAD:
{
int64_t zero = 0;
#if XCC_TARGET_PLATFORM == XCC_PLATFORM_APPLE
int64_t value = ir->expr.addend;
#else
int64_t value = 0;
#endif
int size = 1 << (ir->kind - IR_EXPR_BYTE);
add_section_data(sec, &zero, size); // TODO: Target endian
add_section_data(sec, &value, size); // TODO: Target endian
}
break;
}
Expand Down
Loading

0 comments on commit 1792b04

Please sign in to comment.