1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-10 19:26:38 +03:00

[Mach-O] wip

This commit is contained in:
Rui Ueyama 2021-11-06 14:56:51 +09:00
parent a4bdd81966
commit d88b4c1e86
2 changed files with 41 additions and 30 deletions

View File

@ -39,22 +39,40 @@ Subsection *InputSection::find_subsection(Context &ctx, u32 addr) {
return it[-1].get(); return it[-1].get();
} }
static i64 read_addend(u8 *buf, MachRel r) {
i64 addend = 0;
switch (r.type) {
case X86_64_RELOC_SIGNED_1:
addend = 1;
break;
case X86_64_RELOC_SIGNED_2:
addend = 2;
break;
case X86_64_RELOC_SIGNED_4:
addend = 4;
break;
}
switch (r.p2size) {
case 0:
return buf[r.offset] + addend;
case 1:
return *(i16 *)(buf + r.offset) + addend;
case 2:
return *(i32 *)(buf + r.offset) + addend;
case 3:
return *(i64 *)(buf + r.offset) + addend;
}
unreachable();
}
static Relocation read_reloc(Context &ctx, ObjectFile &file, static Relocation read_reloc(Context &ctx, ObjectFile &file,
const MachSection &hdr, MachRel r) { const MachSection &hdr, MachRel r) {
u8 *buf = (u8 *)file.mf->data + hdr.offset; u8 *buf = (u8 *)file.mf->data + hdr.offset;
Relocation rel{r.offset, (u8)r.type, (u8)r.p2size}; Relocation rel{r.offset, (u8)r.type, (u8)r.p2size, (bool)r.is_pcrel};
i64 addend = read_addend(buf, r);
i64 addend;
if (r.p2size == 0)
addend = *(i8 *)(buf + r.offset);
else if (r.p2size == 1)
addend = *(i16 *)(buf + r.offset);
else if (r.p2size == 2)
addend = *(i32 *)(buf + r.offset);
else if (r.p2size == 3)
addend = *(i64 *)(buf + r.offset);
else
unreachable();
if (r.is_extern) { if (r.is_extern) {
rel.addend = addend; rel.addend = addend;
@ -137,29 +155,21 @@ void Subsection::apply_reloc(Context &ctx, u8 *buf) {
#define S (rel.sym ? rel.sym->get_addr(ctx) : rel.subsec->get_addr(ctx)) #define S (rel.sym ? rel.sym->get_addr(ctx) : rel.subsec->get_addr(ctx))
#define A rel.addend #define A rel.addend
#define P (get_addr(ctx) + rel.offset) #define P (rel.is_pcrel ? get_addr(ctx) + rel.offset + 4 : 0)
#define G rel.sym->get_got_addr(ctx) #define G rel.sym->get_got_addr(ctx)
switch (rel.type) { switch (rel.type) {
case X86_64_RELOC_UNSIGNED: case X86_64_RELOC_UNSIGNED:
write(S + A); case X86_64_RELOC_SIGNED:
case X86_64_RELOC_BRANCH:
case X86_64_RELOC_SIGNED_1:
case X86_64_RELOC_SIGNED_2:
case X86_64_RELOC_SIGNED_4:
write(S + A - P);
break; break;
case X86_64_RELOC_GOT_LOAD: case X86_64_RELOC_GOT_LOAD:
case X86_64_RELOC_GOT: case X86_64_RELOC_GOT:
write(G + A - P - 4); write(G + A - P);
break;
case X86_64_RELOC_SIGNED:
case X86_64_RELOC_BRANCH:
write(S + A - P - 4);
break;
case X86_64_RELOC_SIGNED_1:
write(S + A - P - 3);
break;
case X86_64_RELOC_SIGNED_2:
write(S + A - P - 2);
break;
case X86_64_RELOC_SIGNED_4:
write(S + A - P);
break; break;
default: default:
Fatal(ctx) << isec << ": unknown reloc: " << (int)rel.type; Fatal(ctx) << isec << ": unknown reloc: " << (int)rel.type;

View File

@ -29,8 +29,9 @@ struct Symbol;
struct Relocation { struct Relocation {
u32 offset = 0; u32 offset = 0;
u16 type = -1; u8 type = -1;
u8 p2size = 0; u8 p2size = 0;
bool is_pcrel = false;
i64 addend = 0; i64 addend = 0;
Symbol *sym = nullptr; Symbol *sym = nullptr;
Subsection *subsec = nullptr; Subsection *subsec = nullptr;