Skip to content

Commit a2beedc

Browse files
authored
i#5771: On AArch64 optionally mangle MRS to make CTR_EL0.DIC seem zero. (#7578)
This is a work-around rather than a proper fix for issue #5771. It may also facilitate experimentation by users. When "-fake_ctr_dic" is specified the MRS instruction is mangled by adding a following AND (immediate) instruction that clears the corresponding bit. Most programs will then execute the IC IVAU instruction that DynamoRIO currently relies on for detecting a code modification. (See, for example, LLVM's implementation of __clear_cache.) Issue: #5771
1 parent 0a9748a commit a2beedc

File tree

7 files changed

+92
-0
lines changed

7 files changed

+92
-0
lines changed

core/arch/aarchxx/mangle.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,6 +2999,25 @@ float_pc_update(dcontext_t *dcontext)
29992999
}
30003000

30013001
#ifdef AARCH64
3002+
void
3003+
mangle_ctr_read(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr)
3004+
{
3005+
if (instr_get_opcode(instr) == OP_mrs && instr_num_srcs(instr) == 1 &&
3006+
opnd_is_reg(instr_get_src(instr, 0)) &&
3007+
opnd_get_reg(instr_get_src(instr, 0)) == DR_REG_CTR_EL0 &&
3008+
instr_num_dsts(instr) == 1 && opnd_is_reg(instr_get_dst(instr, 0))) {
3009+
// Insert an AND (immediate) instruction after the MRS so that the
3010+
// app thinks the bit is clear. This will (one hopes) make the app
3011+
// execute the OP_ic_ivau instruction that DynamoRIO currently relies
3012+
// on for detecting code modifications.
3013+
const int CTR_EL0_DIC_BIT = 29;
3014+
reg_t reg = opnd_get_reg(instr_get_dst(instr, 0));
3015+
POST(ilist, instr,
3016+
INSTR_CREATE_and(dcontext, opnd_create_reg(reg), opnd_create_reg(reg),
3017+
OPND_CREATE_INT64(~(1UL << CTR_EL0_DIC_BIT))));
3018+
}
3019+
}
3020+
30023021
instr_t *
30033022
mangle_icache_op(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
30043023
instr_t *next_instr, app_pc pc)

core/arch/arch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,8 @@ mangle_reads_thread_register(dcontext_t *dcontext, instrlist_t *ilist, instr_t *
763763
#endif /* ARM */
764764

765765
#ifdef AARCH64
766+
void
767+
mangle_ctr_read(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr);
766768
instr_t *
767769
mangle_icache_op(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
768770
instr_t *next_instr, app_pc pc);

core/arch/mangle_shared.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,12 @@ d_r_mangle(dcontext_t *dcontext, instrlist_t *ilist, uint *flags DR_PARAM_INOUT,
19501950
}
19511951
#endif
19521952

1953+
#ifdef AARCH64
1954+
/* XXX i#5771: This may no longer be required when the issue is fixed. */
1955+
if (INTERNAL_OPTION(fake_ctr_dic))
1956+
mangle_ctr_read(dcontext, ilist, instr);
1957+
#endif
1958+
19531959
#ifdef AARCH64
19541960
if (instr_is_icache_op(instr) && instr_is_app(instr)) {
19551961
next_instr = mangle_icache_op(dcontext, ilist, instr, next_instr,

core/optionsx.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,12 @@ OPTION_DEFAULT_INTERNAL(bool, unsafe_build_ldstex, false,
633633
"replace blocks using exclusive load/store with a "
634634
"macro-instruction (unsafe)")
635635
#endif
636+
#ifdef AARCH64
637+
/* XXX i#5771: This option may no longer be required when the issue is fixed. */
638+
OPTION_DEFAULT_INTERNAL(bool, fake_ctr_dic, false,
639+
"mangle read of CTR_EL0 so app believes DIC bit is "
640+
"clear, which can help with apps that modify code")
641+
#endif
636642
#if defined(AARCHXX) || defined(RISCV64)
637643
/* TODO i#1698: ARM is still missing the abilty to convert the following:
638644
* + ldrexd..strexd.

suite/tests/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2368,6 +2368,12 @@ if (NOT ANDROID) # XXX i#1874: failing on Android
23682368
tobuild(common.segfault common/segfault.c)
23692369
endif ()
23702370

2371+
if (AARCH64)
2372+
tobuild(common.fake_ctr_dic common/fake_ctr_dic.c)
2373+
torunonly(common.fake_ctr_dic common.fake_ctr_dic common/fake_ctr_dic.c
2374+
"-fake_ctr_dic" "")
2375+
endif ()
2376+
23712377
# PR 217255: these 4 removed to shorten the regression suite since not
23722378
# adding much value in terms of testing corner cases
23732379
#tobuild(common.hello common/hello.c)

suite/tests/common/fake_ctr_dic.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* **********************************************************
2+
* Copyright (c) 2025 Arm Limited. All rights reserved.
3+
* **********************************************************/
4+
5+
/*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* * Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of Arm Limited nor the names of its contributors may be
17+
* used to endorse or promote products derived from this software without
18+
* specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23+
* ARE DISCLAIMED. IN NO EVENT SHALL ARM LIMITED OR CONTRIBUTORS BE LIABLE
24+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30+
* DAMAGE.
31+
*/
32+
33+
/* Check that CTR_EL0.DIC appears to be zero, which it should if
34+
* DynamoRIO was run with -fake_ctr_dic. See i#5771.
35+
*/
36+
37+
#include "tools.h"
38+
39+
int
40+
main()
41+
{
42+
const int CTR_EL0_DIC_BIT = 29;
43+
unsigned long ctr;
44+
asm volatile("mrs %[ctr], ctr_el0" : [ctr] "=r"(ctr));
45+
if (TEST(ctr, 1U << CTR_EL0_DIC_BIT)) {
46+
print("CTR_EL0 = %lx\n", ctr);
47+
return 1;
48+
} else {
49+
print("PASS\n");
50+
return 0;
51+
}
52+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
PASS

0 commit comments

Comments
 (0)