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-11-07 18:59:17 +09:00
parent c89448d17c
commit 0cb34615d9
2 changed files with 48 additions and 5 deletions

View File

@ -277,13 +277,14 @@ class RebaseEncoder {
public: public:
RebaseEncoder(); RebaseEncoder();
void add(i64 seg_idx, i64 offset); void add(i64 seg_idx, i64 offset);
void flush();
void finish(); void finish();
std::vector<u8> buf; std::vector<u8> buf;
private: private:
i64 last_seg = -1; i64 cur_seg = -1;
i64 last_off = 0; i64 cur_off = 0;
i64 times = 0; i64 times = 0;
}; };

View File

@ -422,12 +422,54 @@ RebaseEncoder::RebaseEncoder() {
void RebaseEncoder::add(i64 seg_idx, i64 offset) { void RebaseEncoder::add(i64 seg_idx, i64 offset) {
assert(seg_idx < 16); assert(seg_idx < 16);
buf.push_back(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | seg_idx);
encode_uleb(buf, offset); // Accumulate consecutive base relocations
buf.push_back(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1); if (seg_idx == cur_seg && offset == cur_off) {
cur_off += 8;
times++;
return;
}
// Flush the accumulated base relocations
flush();
// Advance the cursor
if (seg_idx != cur_seg) {
buf.push_back(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | seg_idx);
encode_uleb(buf, offset);
} else {
i64 dist = offset - cur_off;
assert(dist >= 0);
if (dist % 8 == 0 && dist < 128) {
buf.push_back(REBASE_OPCODE_ADD_ADDR_IMM_SCALED | (dist >> 3));
} else {
buf.push_back(REBASE_OPCODE_ADD_ADDR_ULEB);
encode_uleb(buf, dist);
}
}
cur_seg = seg_idx;
cur_off = offset + 8;
times = 1;
}
void RebaseEncoder::flush() {
if (times == 0)
return;
if (times < 16) {
buf.push_back(REBASE_OPCODE_DO_REBASE_IMM_TIMES | times);
} else {
buf.push_back(REBASE_OPCODE_DO_REBASE_ULEB_TIMES);
encode_uleb(buf, times);
}
times = 0;
} }
void RebaseEncoder::finish() { void RebaseEncoder::finish() {
flush();
buf.push_back(REBASE_OPCODE_DONE); buf.push_back(REBASE_OPCODE_DONE);
} }