Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Z
Zipr Toolchain
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Open Source Software
Zipr Toolchain
Commits
271ae947
Commit
271ae947
authored
5 years ago
by
Jason Hiser
Browse files
Options
Downloads
Patches
Plain Diff
added vldr patching support
parent
9e6286e1
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
unpin_arm32.cpp
+89
-2
89 additions, 2 deletions
unpin_arm32.cpp
with
89 additions
and
2 deletions
unpin_arm32.cpp
+
89
−
2
View file @
271ae947
...
...
@@ -119,6 +119,7 @@ void UnpinArm32_t::HandlePcrelReloc(Instruction_t* from_insn, Relocation_t* relo
// so far, only handling ldr and ldrb
const
auto
is_ldr_type
=
mnemonic
.
substr
(
0
,
3
)
==
"ldr"
;
// ldr, ldrb, ldreq, ldrbeq, etc.
const
auto
is_vldr_type
=
mnemonic
.
substr
(
0
,
4
)
==
"vldr"
;
// vldr <double>, vldr <single>
const
auto
is_add_type
=
mnemonic
.
substr
(
0
,
3
)
==
"add"
;
// add, addne, etc.
const
auto
is_addne_type
=
mnemonic
==
"addne"
;
// exactly addne
const
auto
is_addls_type
=
mnemonic
==
"addls"
;
// exactly addls
...
...
@@ -137,7 +138,93 @@ void UnpinArm32_t::HandlePcrelReloc(Instruction_t* from_insn, Relocation_t* relo
assert
(
tmp_reg
<
15
);
// sanity check 4 bits
if
(
is_ldr_type
&&
!
is_rd_pc
)
if
(
is_vldr_type
)
{
/*
* We need to patch an vldr[b][cond] fp_reg, [pc + constant]
* to be at a new location.
*
* The plan :
* FA: b<cond> L0
* FT:
* ..
* L0 str rd, [sp,#-fc]
* L1 ldr rd, [L6]
* L2 add rd, pc, rd
* L3 vldr rd, [rd, <imm>] # orig insn
* L4 ldr rd, [sp,#-fc]
* L5: b FT
* L6: .word <constant>
*/
const
auto
tramp_size
=
6
*
4
+
4
;
// 6 insns, 4 bytes each, plus one word of read-only data
const
auto
tramp_range
=
ms
.
getFreeRange
(
tramp_size
);
const
auto
tramp_start
=
tramp_range
.
getStart
();
// don't be too fancy, just reserve 16 bytes.
ms
.
splitFreeRange
({
tramp_start
,
tramp_start
+
tramp_size
});
// and give the bytes some names
const
auto
FA
=
from_insn_location
;
const
auto
FT
=
from_insn_location
+
4
;
const
auto
L0
=
tramp_start
;
const
auto
L1
=
L0
+
4
;
const
auto
L2
=
L1
+
4
;
const
auto
L3
=
L2
+
4
;
const
auto
L4
=
L3
+
4
;
const
auto
L5
=
L4
+
4
;
const
auto
L6
=
L5
+
4
;
// Create a branch to put over the original ldr
// and set the conditional bits equal to
// the original instruction conditional bits
auto
my_branch_bytes
=
branch_bytes
;
my_branch_bytes
[
3
]
&=
0x0f
;
// clear always condition bits
my_branch_bytes
[
3
]
|=
(
insn_bytes
[
3
]
&
0xf0
);
// add the vldr cond bits.
ms
.
plopBytes
(
FA
,
my_branch_bytes
.
c_str
(),
4
);
// and make it point at L0
zo
->
applyPatch
(
FA
,
L0
);
// spill tmp_reg at L0, e50d00fc
auto
spill_insn
=
string
(
"
\xfc\x00\x0d\xe5
"
,
4
);
spill_insn
[
1
]
|=
(
tmp_reg
<<
4
);
ms
.
plopBytes
(
L0
,
spill_insn
.
c_str
(),
4
);
// ldr dest_reg, [pc+k] (where pc+8+k == L6)
auto
ldr_imm_insn
=
string
(
"
\x0c\x00\x9f\xe5
"
,
4
);
ldr_imm_insn
[
1
]
|=
(
tmp_reg
<<
4
);
// set this instruction's dest reg to the ldr's dest reg.
ms
.
plopBytes
(
L1
,
ldr_imm_insn
.
c_str
(),
4
);
// put down add tmp_reg,pc, temp_reg
auto
new_add_word
=
string
(
"
\x00\x00\x8f\xe0
"
,
4
);
// e08f0000 add r0, pc, r0
new_add_word
[
1
]
|=
(
tmp_reg
<<
4
);
new_add_word
[
0
]
|=
(
tmp_reg
<<
0
);
ms
.
plopBytes
(
L2
,
new_add_word
.
c_str
(),
4
);
// put down orig vldr insn, with 1) cond field removed, and 2) Rn set to -> tmp_reg
auto
vldr_insn_bytes
=
from_insn
->
getDataBits
();
vldr_insn_bytes
[
2
]
&=
0xf0
;
// remove Rn bits.
vldr_insn_bytes
[
2
]
|=
(
tmp_reg
<<
0
);
// set Rn to tmp-reg
ms
.
plopBytes
(
L3
,
vldr_insn_bytes
.
c_str
(),
4
);
// put down L5, restore of scratch reg r0
auto
restore_insn
=
string
(
"
\xfc\x00\x1d\xe5
"
,
4
);
restore_insn
[
1
]
|=
(
tmp_reg
<<
4
);
// set Rd field
ms
.
plopBytes
(
L4
,
restore_insn
.
c_str
(),
4
);
// put an uncond branch the end of the trampoline
// and make it jump at FT
ms
.
plopBytes
(
L5
,
branch_bytes
.
c_str
(),
4
);
zo
->
applyPatch
(
L5
,
FT
);
// put the calculated pc-rel offset at L3
const
auto
new_offset
=
int32_t
(
orig_insn_addr
-
L2
);
ms
.
plopBytes
(
L6
,
reinterpret_cast
<
const
char
*>
(
&
new_offset
),
4
);
// endianness of host must match target
// should be few enough of these to always print
cout
<<
"Had to trampoline "
<<
disasm
->
getDisassembly
()
<<
" @"
<<
FA
<<
" to "
<<
hex
<<
L0
<<
"-"
<<
L0
+
tramp_size
-
1
<<
endl
;
}
else
if
(
is_ldr_type
&&
!
is_rd_pc
)
{
/*
* We need to patch an ldr[b][cond] reg, [pc + constant]
...
...
@@ -257,7 +344,7 @@ void UnpinArm32_t::HandlePcrelReloc(Instruction_t* from_insn, Relocation_t* relo
// and make it point at L0
zo
->
applyPatch
(
FA
,
L0
);
// spill reg at L0, e50d00fc
// spill
tmp_
reg at L0, e50d00fc
auto
spill_insn
=
string
(
"
\xfc\x00\x0d\xe5
"
,
4
);
spill_insn
[
1
]
|=
(
tmp_reg
<<
4
);
ms
.
plopBytes
(
L0
,
spill_insn
.
c_str
(),
4
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment