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:
parent
c89448d17c
commit
0cb34615d9
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user