Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Z
Zipr Backend
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
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
Open Source Software
Zipr Backend
Commits
d1978e28
Commit
d1978e28
authored
6 years ago
by
Jason Hiser
Browse files
Options
Downloads
Patches
Plain Diff
added patching for shorter branches
parent
8212927e
No related branches found
No related tags found
1 merge request
!16
Arm port
Pipeline
#979
failed
6 years ago
Stage: clean
Stage: build
Stage: test
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/patcher_arm64.cpp
+69
-45
69 additions, 45 deletions
src/patcher_arm64.cpp
with
69 additions
and
45 deletions
src/patcher_arm64.cpp
+
69
−
45
View file @
d1978e28
...
...
@@ -72,10 +72,6 @@ void ZiprPatcherARM64_t::ApplyNopToPatch(RangeAddress_t addr)
void
ZiprPatcherARM64_t
::
ApplyPatch
(
RangeAddress_t
from_addr
,
RangeAddress_t
to_addr
)
{
// A Brandh unconditional, in binary is: op=000101 imm26=00 00000000 00000000 00000000
// it includes a 26-bit immediate, which is +/- 128MB, which should be a good enough "jump anywhere"
// for now.
//
const
auto
first_byte
=
(
uint8_t
)
memory_space
[
from_addr
+
3
];
const
auto
second_byte
=
(
uint8_t
)
memory_space
[
from_addr
+
2
];
const
auto
third_byte
=
(
uint8_t
)
memory_space
[
from_addr
+
1
];
...
...
@@ -90,49 +86,77 @@ void ZiprPatcherARM64_t::ApplyPatch(RangeAddress_t from_addr, RangeAddress_t to_
(((
uint32_t
)
third_byte
)
<<
8
)
|
(((
uint32_t
)
fourth_byte
)
<<
0
);
switch
(
opcode
)
// A Bracdh unconditional, in binary is: op=000101 imm26=00 00000000 00000000 00000000
// it includes a 26-bit immediate, which is +/- 128MB, which should be a good enough "jump anywhere"
// for now.
//
const
auto
is_uncond_branch
=
(
first_byte
>>
2
)
==
(
0x14
>>
2
);
// unconditional branch
const
auto
is_uncond_branch_and_link
=
(
first_byte
>>
2
)
==
(
0x97
>>
2
);
// uncond branch and link
// B.cond
// 01010100 imm19 0 cond
const
auto
is_branch_cond
=
first_byte
==
0x54
;
// conditional branch
// compare and branch
// sf 011 0101 imm19 Rt
// sf 011 0100 imm19 Rt
const
auto
is_compare_and_branch_nz
=
(
first_byte
&
0x7f
)
==
0x35
;
const
auto
is_compare_and_branch_z
=
(
first_byte
&
0x7f
)
==
0x34
;
const
auto
is_compare_and_branch
=
(
is_compare_and_branch_nz
||
is_compare_and_branch_z
);
// b5 011 0111 b40 imm14 Rt -- tbnz
// b5 011 0110 b40 imm14 Rt -- tbz
const
auto
is_test_and_branch_nz
=
(
first_byte
&
0x7f
)
==
0x37
;
const
auto
is_test_and_branch_z
=
(
first_byte
&
0x7f
)
==
0x36
;
const
auto
is_test_and_branch
=
is_test_and_branch_nz
||
is_test_and_branch_z
;
if
(
is_uncond_branch
||
is_uncond_branch_and_link
)
{
case
(
0x14
>>
2
)
:
// unconditional branch
case
(
0x97
>>
2
)
:
// uncond branch and link
{
const
auto
opBits
=
32U
-
26U
;
// 32 bits, imm26
// assert there's no overflow.
assert
((
uint64_t
)(
new_offset
<<
opBits
)
==
((
uint64_t
)
new_offset
)
<<
opBits
);
// or in opcode for first byte. set remaining bytes.
const
auto
trimmed_offset
=
new_offset
&
((
1
<<
26
)
-
1
);
const
auto
new_first_byte
=
(
trimmed_offset
>>
0
)
&
0xff
;
const
auto
new_second_byte
=
(
trimmed_offset
>>
8
)
&
0xff
;
const
auto
new_third_byte
=
(
trimmed_offset
>>
16
)
&
0xff
;
const
auto
new_fourth_byte
=
(
opcode
<<
2
)
|
((
trimmed_offset
>>
24
)
&
0xff
);
//cout<<"ARM64::Patching "<<hex<<from_addr+0<<" val="<<new_first_byte <<endl;
//cout<<"ARM64::Patching "<<hex<<from_addr+1<<" val="<<new_second_byte<<endl;
//cout<<"ARM64::Patching "<<hex<<from_addr+2<<" val="<<new_third_byte <<endl;
//cout<<"ARM64::Patching "<<hex<<from_addr+3<<" val="<<new_fourth_byte<<endl;
memory_space
[
from_addr
+
0
]
=
new_first_byte
;
memory_space
[
from_addr
+
1
]
=
new_second_byte
;
memory_space
[
from_addr
+
2
]
=
new_third_byte
;
memory_space
[
from_addr
+
3
]
=
new_fourth_byte
;
break
;
}
case
(
0x54
>>
2
)
:
// conditional branch
{
const
auto
opBits
=
32U
-
19
;
// 32 bits, imm19
const
auto
mask19
=
(
1
<<
19U
)
-
1
;
assert
(
first_byte
==
0x54
);
// need the last 2 0's for opcode here.
assert
((
uint64_t
)(
new_offset
<<
opBits
)
==
((
uint64_t
)
new_offset
)
<<
opBits
);
const
auto
full_word_clean
=
full_word
&
~
(
mask19
<<
5
);
const
auto
full_word_new_offset
=
full_word_clean
|
((
new_offset
&
mask19
)
<<
5
);
memory_space
[
from_addr
+
0
]
=
(
full_word_new_offset
>>
0
)
&
0xff
;
memory_space
[
from_addr
+
1
]
=
(
full_word_new_offset
>>
8
)
&
0xff
;
memory_space
[
from_addr
+
2
]
=
(
full_word_new_offset
>>
16
)
&
0xff
;
memory_space
[
from_addr
+
3
]
=
(
full_word_new_offset
>>
24
)
&
0xff
;
break
;
}
default
:
assert
(
0
);
const
auto
non_imm_bits
=
32U
-
26U
;
// 32 bits, imm26
// assert there's no overflow.
assert
((
uint64_t
)(
new_offset
<<
non_imm_bits
)
==
((
uint64_t
)
new_offset
)
<<
non_imm_bits
);
// or in opcode for first byte. set remaining bytes.
const
auto
trimmed_offset
=
new_offset
&
((
1
<<
26
)
-
1
);
const
auto
new_first_byte
=
(
trimmed_offset
>>
0
)
&
0xff
;
const
auto
new_second_byte
=
(
trimmed_offset
>>
8
)
&
0xff
;
const
auto
new_third_byte
=
(
trimmed_offset
>>
16
)
&
0xff
;
const
auto
new_fourth_byte
=
(
opcode
<<
2
)
|
((
trimmed_offset
>>
24
)
&
0xff
);
//cout<<"ARM64::Patching "<<hex<<from_addr+0<<" val="<<new_first_byte <<endl;
//cout<<"ARM64::Patching "<<hex<<from_addr+1<<" val="<<new_second_byte<<endl;
//cout<<"ARM64::Patching "<<hex<<from_addr+2<<" val="<<new_third_byte <<endl;
//cout<<"ARM64::Patching "<<hex<<from_addr+3<<" val="<<new_fourth_byte<<endl;
memory_space
[
from_addr
+
0
]
=
new_first_byte
;
memory_space
[
from_addr
+
1
]
=
new_second_byte
;
memory_space
[
from_addr
+
2
]
=
new_third_byte
;
memory_space
[
from_addr
+
3
]
=
new_fourth_byte
;
}
else
if
(
is_branch_cond
||
is_compare_and_branch
)
{
const
auto
non_mask_bits
=
32U
-
19
;
// 32 bits, imm19
const
auto
mask19
=
(
1
<<
19U
)
-
1
;
assert
((
uint64_t
)(
new_offset
<<
non_mask_bits
)
==
((
uint64_t
)
new_offset
)
<<
non_mask_bits
);
const
auto
full_word_clean
=
full_word
&
~
(
mask19
<<
5
);
const
auto
full_word_new_offset
=
full_word_clean
|
((
new_offset
&
mask19
)
<<
5
);
memory_space
[
from_addr
+
0
]
=
(
full_word_new_offset
>>
0
)
&
0xff
;
memory_space
[
from_addr
+
1
]
=
(
full_word_new_offset
>>
8
)
&
0xff
;
memory_space
[
from_addr
+
2
]
=
(
full_word_new_offset
>>
16
)
&
0xff
;
memory_space
[
from_addr
+
3
]
=
(
full_word_new_offset
>>
24
)
&
0xff
;
}
else
if
(
is_test_and_branch
)
{
const
auto
non_mask_bits
=
32U
-
14
;
// 32 bits, imm14
const
auto
mask14
=
(
1
<<
14U
)
-
1
;
assert
(
first_byte
==
0x54
);
// need the last 2 0's for opcode here.
assert
((
uint64_t
)(
new_offset
<<
non_mask_bits
)
==
((
uint64_t
)
new_offset
)
<<
non_mask_bits
);
const
auto
full_word_clean
=
full_word
&
~
(
mask14
<<
5
);
const
auto
full_word_new_offset
=
full_word_clean
|
((
new_offset
&
mask14
)
<<
5
);
memory_space
[
from_addr
+
0
]
=
(
full_word_new_offset
>>
0
)
&
0xff
;
memory_space
[
from_addr
+
1
]
=
(
full_word_new_offset
>>
8
)
&
0xff
;
memory_space
[
from_addr
+
2
]
=
(
full_word_new_offset
>>
16
)
&
0xff
;
memory_space
[
from_addr
+
3
]
=
(
full_word_new_offset
>>
24
)
&
0xff
;
}
else
assert
(
0
);
}
...
...
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