1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-21 09:57:18 +03:00

[Mach-O] wip

This commit is contained in:
Rui Ueyama 2021-10-10 17:52:49 +09:00
parent 96b07d875d
commit d176ed8fbb
3 changed files with 57 additions and 42 deletions

View File

@ -27,46 +27,13 @@ Subsection *InputSection::find_subsection(Context &ctx, u32 addr) {
return &*(it - 1);
}
static i64 read_addend(u8 *buf, u32 offset, u32 p2size) {
switch (p2size) {
case 0: return *(i8 *)(buf + offset);
case 1: return *(i16 *)(buf + offset);
case 2: return *(i32 *)(buf + offset);
case 3: return *(i64 *)(buf + offset);
}
unreachable();
}
void InputSection::parse_relocations(Context &ctx) {
rels.reserve(hdr.nreloc);
// Parse mach-o relocations to fill `rels` vector
MachRel *rel = (MachRel *)(file.mf->data + hdr.reloff);
for (i64 i = 0; i < hdr.nreloc; i++) {
MachRel &r = rel[i];
i64 addend = read_addend((u8 *)contents.data(), r.offset, r.p2size);
if (r.is_extern) {
rels.push_back({r.offset, (bool)r.is_pcrel, addend, file.syms[r.idx],
nullptr});
} else {
u32 addr;
if (r.is_pcrel) {
if (r.p2size != 2)
Fatal(ctx) << *this << ": invalid PC-relative reloc: " << i;
addr = hdr.addr + r.offset + 4 + addend;
} else {
addr = addend;
}
Subsection *target = file.sections[r.idx - 1]->find_subsection(ctx, addr);
if (!target)
Fatal(ctx) << *this << ": bad relocation: " << i;
rels.push_back({r.offset, (bool)r.is_pcrel, addr - target->input_addr,
nullptr, target});
}
}
for (i64 i = 0; i < hdr.nreloc; i++)
rels.push_back(file.read_reloc(ctx, hdr, rel[i]));
// Sort `rels` vector
sort(rels, [](const Relocation &a, const Relocation &b) {

View File

@ -45,6 +45,8 @@ public:
void parse_compact_unwind(Context &ctx, MachSection &hdr);
void resolve_symbols(Context &ctx);
Relocation read_reloc(Context &ctx, const MachSection &hdr, MachRel r);
MappedFile<Context> *mf;
std::vector<std::unique_ptr<InputSection>> sections;
std::vector<Symbol *> syms;

View File

@ -79,18 +79,33 @@ void ObjectFile::parse_compact_unwind(Context &ctx, MachSection &hdr) {
// Read comapct unwind entries
for (i64 i = 0; i < num_entries; i++) {
CompactUnwindEntry &src = ((CompactUnwindEntry *)contents.data())[i];
unwind_entries.push_back({{}, src.code_len, src.compact_unwind_info, {}, {}});
CompactUnwindEntry &ent = ((CompactUnwindEntry *)contents.data())[i];
unwind_entries.push_back({{}, ent.code_len, ent.compact_unwind_info, {}, {}});
}
// Read relocations
std::vector<MachRel> mach_rels((MachRel *)(mf->data + hdr.reloff),
(MachRel *)(mf->data + hdr.reloff) + hdr.nreloc);
MachRel *mach_rels = (MachRel *)(mf->data + hdr.reloff);
for (i64 i = 0; i < hdr.nreloc; i++) {
MachRel &r = mach_rels[i];
i64 idx = r.offset / sizeof(CompactUnwindEntry);
i64 offset = r.offset % sizeof(CompactUnwindEntry);
sort(mach_rels, [](const MachRel &a, const MachRel &b) {
return a.offset < b.offset;
});
// if (idx >= unwind_entries.size())
// Fatal(ctx) << *this << ": relocation offset too large: " << i;
UnwindEntry &ent = unwind_entries[idx];
if (offset == offsetof(CompactUnwindEntry, code_start)) {
}
if (offset == offsetof(CompactUnwindEntry, personality)) {
}
if (offset == offsetof(CompactUnwindEntry, lsda)) {
}
// Fatal(ctx) << *this << ": unsupported relocation: " << i;
}
}
void ObjectFile::resolve_symbols(Context &ctx) {
@ -113,4 +128,35 @@ void ObjectFile::resolve_symbols(Context &ctx) {
}
}
static i64 read_addend(u8 *buf, MachRel r) {
switch (r.p2size) {
case 0: return *(i8 *)(buf + r.offset);
case 1: return *(i16 *)(buf + r.offset);
case 2: return *(i32 *)(buf + r.offset);
case 3: return *(i64 *)(buf + r.offset);
}
unreachable();
}
Relocation ObjectFile::read_reloc(Context &ctx, const MachSection &hdr, MachRel r) {
i64 addend = read_addend((u8 *)mf->get_contents().data() + hdr.offset, r);
if (r.is_extern)
return {r.offset, (bool)r.is_pcrel, addend, syms[r.idx], nullptr};
u32 addr;
if (r.is_pcrel) {
if (r.p2size != 2)
Fatal(ctx) << *this << ": invalid PC-relative reloc: " << r.offset;
addr = hdr.addr + r.offset + 4 + addend;
} else {
addr = addend;
}
Subsection *target = sections[r.idx - 1]->find_subsection(ctx, addr);
if (!target)
Fatal(ctx) << *this << ": bad relocation: " << r.offset;
return {r.offset, (bool)r.is_pcrel, addr - target->input_addr, nullptr, target};
}
} // namespace mold::macho