1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-14 16:31:42 +03:00
mold/macho/input-sections.cc

105 lines
3.0 KiB
C++
Raw Normal View History

2021-10-04 08:15:26 +03:00
#include "mold.h"
2021-10-05 10:00:45 +03:00
#include <algorithm>
2021-10-04 08:15:26 +03:00
namespace mold::macho {
2021-10-05 10:00:45 +03:00
std::ostream &operator<<(std::ostream &out, const InputSection &sec) {
2021-10-08 10:55:33 +03:00
out << sec.file << "(" << sec.hdr.get_segname() << ","
<< sec.hdr.get_sectname() << ")";
2021-10-05 10:00:45 +03:00
return out;
}
2021-10-04 08:15:26 +03:00
InputSection::InputSection(Context &ctx, ObjectFile &file, const MachSection &hdr)
: file(file), hdr(hdr) {
contents = file.mf->get_contents().substr(hdr.offset, hdr.size);
2021-10-05 10:00:45 +03:00
subsections.push_back({*this, 0, (u32)contents.size(), (u32)hdr.addr});
}
Subsection *InputSection::find_subsection(Context &ctx, u32 addr) {
auto it = std::upper_bound(subsections.begin(), subsections.end(), addr,
[&](u32 addr, const Subsection &subsec) {
return addr < subsec.input_addr;
});
if (it == subsections.begin())
2021-10-05 13:12:03 +03:00
return nullptr;
2021-10-05 10:00:45 +03:00
return &*(it - 1);
}
2021-10-11 15:56:18 +03:00
static Relocation read_reloc(Context &ctx, ObjectFile &file,
const MachSection &hdr, MachRel r) {
u8 *buf = (u8 *)file.mf->data + hdr.offset;
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)
return {r.offset, (bool)r.is_pcrel, addend, file.syms[r.idx], nullptr};
u32 addr;
if (r.is_pcrel) {
if (r.p2size != 2)
Fatal(ctx) << file << ": invalid PC-relative reloc: " << r.offset;
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) << file << ": bad relocation: " << r.offset;
return {r.offset, (bool)r.is_pcrel, addr - target->input_addr, nullptr, target};
}
2021-10-05 10:00:45 +03:00
void InputSection::parse_relocations(Context &ctx) {
2021-10-04 13:41:20 +03:00
rels.reserve(hdr.nreloc);
2021-10-06 07:43:39 +03:00
// Parse mach-o relocations to fill `rels` vector
2021-10-04 13:41:20 +03:00
MachRel *rel = (MachRel *)(file.mf->data + hdr.reloff);
2021-10-10 11:52:49 +03:00
for (i64 i = 0; i < hdr.nreloc; i++)
2021-10-11 15:56:18 +03:00
rels.push_back(read_reloc(ctx, file, hdr, rel[i]));
2021-10-05 14:02:41 +03:00
2021-10-06 07:43:39 +03:00
// Sort `rels` vector
2021-10-05 14:02:41 +03:00
sort(rels, [](const Relocation &a, const Relocation &b) {
return a.offset < b.offset;
});
2021-10-06 07:43:39 +03:00
// Assign each subsection a group of relocations
i64 i = 0;
for (Subsection &subsec : subsections) {
subsec.rel_offset = i;
while (i < rels.size() &&
rels[i].offset < subsec.input_offset + subsec.input_size)
i++;
subsec.nrels = i - subsec.rel_offset;
}
}
void Subsection::apply_reloc(Context &ctx, u8 *buf) {
for (const Relocation &rel : std::span(isec.rels).subspan(rel_offset, nrels)) {
u32 *loc = (u32 *)(buf + rel.offset);
if (rel.sym) {
*loc = rel.sym->get_addr(ctx) + rel.addend;
2021-10-06 07:43:39 +03:00
} else {
2021-10-06 08:33:01 +03:00
*loc = rel.subsec->isec.osec->hdr.addr + rel.subsec->output_offset +
rel.addend;
2021-10-06 07:43:39 +03:00
}
if (rel.is_pcrel)
*loc = *loc - isec.osec->hdr.addr - output_offset - rel.offset - 4;
}
2021-10-04 08:15:26 +03:00
}
} // namespace mold::macho