void GenRelocateCodeAndBranch(void
*
buffer
, AssemblyCodeChunk
*
origin, AssemblyCodeChunk
*
relocated) {
CodeBuffer
*
code_buffer
=
new CodeBuffer(
64
);
ThumbTurboAssembler thumb_turbo_assembler_(
0
, code_buffer);
TurboAssembler arm_turbo_assembler_(
0
, code_buffer);
Assembler
*
curr_assembler_
=
NULL;
AssemblyCodeChunk origin_chunk;
origin_chunk.init_region_range(origin
-
>raw_instruction_start(), origin
-
>raw_instruction_size());
bool
entry_is_thumb
=
origin
-
>raw_instruction_start()
%
2
;
if
(entry_is_thumb) {
origin
-
>re_init_region_range(origin
-
>raw_instruction_start()
-
THUMB_ADDRESS_FLAG, origin
-
>raw_instruction_size());
}
LiteMutableArray relo_map(
8
);
relocate_remain:
addr32_t execute_state_changed_pc
=
0
;
bool
is_thumb
=
origin_chunk.raw_instruction_start()
%
2
;
if
(is_thumb) {
curr_assembler_
=
&thumb_turbo_assembler_;
buffer
=
(void
*
)((addr_t)
buffer
-
THUMB_ADDRESS_FLAG);
addr32_t origin_code_start_aligned
=
origin_chunk.raw_instruction_start()
-
THUMB_ADDRESS_FLAG;
/
/
remove thumb address flag
origin_chunk.re_init_region_range(origin_code_start_aligned, origin_chunk.raw_instruction_size());
gen_thumb_relocate_code(&relo_map, &thumb_turbo_assembler_,
buffer
, &origin_chunk, relocated,
&execute_state_changed_pc);
if
(thumb_turbo_assembler_.GetExecuteState()
=
=
ARMExecuteState) {
/
/
relocate interrupt as execute state changed
if
(execute_state_changed_pc < origin_chunk.raw_instruction_start()
+
origin_chunk.raw_instruction_size()) {
/
/
re
-
init the origin
int
relocate_remain_size
=
origin_chunk.raw_instruction_start()
+
origin_chunk.raw_instruction_size()
-
execute_state_changed_pc;
/
/
current execute state
is
ARMExecuteState, so
not
need `
+
THUMB_ADDRESS_FLAG`
origin_chunk.re_init_region_range(execute_state_changed_pc, relocate_remain_size);
/
/
update
buffer
buffer
=
(void
*
)((addr_t)
buffer
+
(execute_state_changed_pc
-
origin_code_start_aligned));
/
/
add nop to align ARM
if
(thumb_turbo_assembler_.pc_offset()
%
4
)
thumb_turbo_assembler_.t1_nop();
goto relocate_remain;
}
}
}
else
{
curr_assembler_
=
&arm_turbo_assembler_;
gen_arm_relocate_code(&relo_map, &arm_turbo_assembler_,
buffer
, &origin_chunk, relocated,
&execute_state_changed_pc);
if
(arm_turbo_assembler_.GetExecuteState()
=
=
ThumbExecuteState) {
/
/
relocate interrupt as execute state changed
if
(execute_state_changed_pc < origin_chunk.raw_instruction_start()
+
origin_chunk.raw_instruction_size()) {
/
/
re
-
init the origin
int
relocate_remain_size
=
origin_chunk.raw_instruction_start()
+
origin_chunk.raw_instruction_size()
-
execute_state_changed_pc;
/
/
current execute state
is
ThumbExecuteState, add THUMB_ADDRESS_FLAG
origin_chunk.re_init_region_range(execute_state_changed_pc
+
THUMB_ADDRESS_FLAG, relocate_remain_size);
/
/
update
buffer
buffer
=
(void
*
)((addr_t)
buffer
+
(execute_state_changed_pc
-
origin_chunk.raw_instruction_start()));
goto relocate_remain;
}
}
}
/
/
TODO:
/
/
if
last instr
is
unlink branch, skip
/
/
dkl 调回插桩点之后继续执行
addr32_t rest_instr_addr
=
origin_chunk.raw_instruction_start()
+
origin_chunk.raw_instruction_size();
if
(curr_assembler_
=
=
&thumb_turbo_assembler_) {
/
/
Branch to the rest of instructions
thumb_ AlignThumbNop();
thumb_ t2_ldr(pc, MemOperand(pc,
0
));
/
/
Get the real branch address
thumb_ EmitAddress(rest_instr_addr
+
THUMB_ADDRESS_FLAG);
}
else
{
/
/
Branch to the rest of instructions
CodeGen codegen(&arm_turbo_assembler_);
/
/
Get the real branch address
codegen.LiteralLdrBranch(rest_instr_addr);
}
/
/
Realize
all
the Pseudo
-
Label
-
Data
thumb_turbo_assembler_.RelocBind();
/
/
Realize
all
the Pseudo
-
Label
-
Data
/
/
dkl 在这里会修正之前lable link的ldr指令,
arm_turbo_assembler_.RelocBind();
/
/
Generate executable code
{
/
/
assembler without specific memory address
AssemblyCodeChunk
*
cchunk;
cchunk
=
MemoryArena::AllocateCodeChunk(code_buffer
-
>getSize());
if
(cchunk
=
=
nullptr)
return
;
thumb_turbo_assembler_.SetRealizedAddress(cchunk
-
>address);
arm_turbo_assembler_.SetRealizedAddress(cchunk
-
>address);
/
/
fixup the instr branch into trampoline(has been modified)
reloc_label_fixup(origin, &relo_map, &thumb_turbo_assembler_, &arm_turbo_assembler_);
AssemblyCodeChunk
*
code
=
NULL;
code
=
AssemblyCodeBuilder::FinalizeFromTurboAssembler(curr_assembler_);
relocated
-
>re_init_region_range(code
-
>raw_instruction_start(), code
-
>raw_instruction_size());
delete code;
}
/
/
thumb
if
(entry_is_thumb) {
/
/
add thumb address flag
relocated
-
>re_init_region_range(relocated
-
>raw_instruction_start()
+
THUMB_ADDRESS_FLAG,
relocated
-
>raw_instruction_size());
}
/
/
clean
{
thumb_turbo_assembler_.ClearCodeBuffer();
arm_turbo_assembler_.ClearCodeBuffer();
delete code_buffer;
}
}