aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-14 16:15:55 +1300
committerAndrew Chambers <[email protected]>2021-10-14 16:15:55 +1300
commit2f68de5f5c53fa0c373a74aa6b4043996855d281 (patch)
tree60efacbd76e501d0d2c98c7f018a1a40acedf9a9 /main.c
parent1de295e1499d2fa5fc4bfa80b5edc6d3dbed7350 (diff)
Work on reloc types.
Diffstat (limited to 'main.c')
-rw-r--r--main.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/main.c b/main.c
index 7828a39..5de9def 100644
--- a/main.c
+++ b/main.c
@@ -463,7 +463,7 @@ static void assemblerrm(const Instr *instr, VarBytes prefix, VarBytes opcode) {
regarg = instr->arg1->kind;
assemblemem(memarg, isreg64(regarg), prefix, opcode, regbits(regarg));
} else {
- rexw = isreg64(instr->arg2->kind);
+ rexw = isreg64(instr->arg1->kind) || isreg64(instr->arg2->kind);
reg1 = regbits(instr->arg1->kind);
reg2 = regbits(instr->arg2->kind);
rex = rexbyte(rexw, reg1 & (1 << 3), 0, reg2 & (1 << 3));
@@ -560,13 +560,28 @@ static void assemblemov(const Instr *mov) {
static void assemblemovextend(const Instr *mov, VarBytes opcode) {
VarBytes prefix;
+ uint8_t rexw, rex, reg, rm;
if (mov->variant == 0 || mov->variant == 5)
prefix = 0x66;
else
prefix = -1;
- assemblerrm(mov, prefix, opcode);
+ if (mov->arg1->kind == ASM_MEMARG) {
+ rexw = isreg64(mov->arg2->kind);
+ reg = regbits(mov->arg2->kind);
+ assemblemem(&mov->arg1->memarg, rexw, prefix, opcode, reg);
+ } else if (mov->arg2->kind == ASM_MEMARG) {
+ rexw = isreg64(mov->arg1->kind);
+ reg = regbits(mov->arg1->kind);
+ assemblemem(&mov->arg2->memarg, rexw, prefix, opcode, reg);
+ } else {
+ rexw = isreg64(mov->arg1->kind) || isreg64(mov->arg2->kind);
+ reg = regbits(mov->arg2->kind);
+ rm = regbits(mov->arg1->kind);
+ rex = rexbyte(rexw, reg & (1 << 3), 0, rm & (1 << 3));
+ assemblemodregrm(rex, prefix, opcode, 0x03, reg, rm);
+ }
}
static void assembledivmulneg(const Instr *instr, uint8_t reg) {
@@ -776,7 +791,7 @@ static void assemble(void) {
assemblereloc(v->dirint.value.l, v->dirint.value.c, 4, R_X86_64_32);
break;
case ASM_DIR_QUAD:
- assemblereloc(v->dirquad.value.l, v->dirquad.value.c, 8, R_X86_64_32);
+ assemblereloc(v->dirquad.value.l, v->dirquad.value.c, 8, R_X86_64_64);
break;
case ASM_LABEL:
sym = getsym(v->label.name);
@@ -1101,23 +1116,20 @@ static void fillsymtab(void) {
}
}
-static void resolvereloc(Relocation *reloc) {
+static int resolvereloc(Relocation *reloc) {
Symbol *sym;
uint8_t *rdata;
int64_t addend, value;
sym = reloc->sym;
+ if (sym->section != reloc->section)
+ return 0;
+
switch (reloc->type) {
- case R_X86_64_32: {
- rdata = &reloc->section->data[reloc->offset];
- value = sym->offset - reloc->offset + reloc->addend;
- rdata[0] = ((uint32_t)value & 0xff);
- rdata[1] = ((uint32_t)value & 0xff00) >> 8;
- rdata[2] = ((uint32_t)value & 0xff0000) >> 16;
- rdata[3] = ((uint32_t)value & 0xff000000) >> 24;
- break;
- }
+ case R_X86_64_32:
+ case R_X86_64_64:
+ return 0;
case R_X86_64_PC32: {
rdata = &reloc->section->data[reloc->offset];
value = sym->offset - reloc->offset + reloc->addend;
@@ -1125,10 +1137,11 @@ static void resolvereloc(Relocation *reloc) {
rdata[1] = ((uint32_t)value & 0xff00) >> 8;
rdata[2] = ((uint32_t)value & 0xff0000) >> 16;
rdata[3] = ((uint32_t)value & 0xff000000) >> 24;
- break;
+ return 1;
}
default:
unreachable();
+ return 0;
}
}
@@ -1150,6 +1163,7 @@ static void appendreloc(Relocation *reloc) {
switch (reloc->type) {
case R_X86_64_PC32:
case R_X86_64_32:
+ case R_X86_64_64:
elfrel.r_info = ELF64_R_INFO(sym->idx, reloc->type);
elfrel.r_offset = reloc->offset;
elfrel.r_addend = reloc->addend;
@@ -1166,10 +1180,8 @@ static void handlerelocs(void) {
size_t i;
for (i = 0; i < nrelocs; i++) {
reloc = &relocs[i];
- if (reloc->sym->section == reloc->section) {
- resolvereloc(reloc);
+ if (resolvereloc(reloc))
continue;
- }
appendreloc(reloc);
}
}