aboutsummaryrefslogtreecommitdiffstats
path: root/target-arm
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2010-03-24 06:38:41 -0700
committerVladimir Chtchetkine <vchtchetkine@google.com>2010-03-24 06:38:41 -0700
commitca52b2260ba9f9bac07092c3d8260ed523de1fe1 (patch)
tree1528222cddf73be24cc4fd5f48878ee525074fae /target-arm
parent01e9608cb62901d13b330f851a260a2082e81a06 (diff)
downloadexternal_qemu-ca52b2260ba9f9bac07092c3d8260ed523de1fe1.zip
external_qemu-ca52b2260ba9f9bac07092c3d8260ed523de1fe1.tar.gz
external_qemu-ca52b2260ba9f9bac07092c3d8260ed523de1fe1.tar.bz2
Make return address table independent from process context.
Use physical addresses (instead of emulated ones) for registered return addresses. This way addresses will be independent from process context, as even if virtual addresses may overlap, the physical ones will not. Change-Id: If5be5174286be0a456c47c48812d7cc9bf19bc1f
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/memcheck_arm_helpers.h26
-rw-r--r--target-arm/translate.c6
2 files changed, 19 insertions, 13 deletions
diff --git a/target-arm/memcheck_arm_helpers.h b/target-arm/memcheck_arm_helpers.h
index a05668a..d13b89d 100644
--- a/target-arm/memcheck_arm_helpers.h
+++ b/target-arm/memcheck_arm_helpers.h
@@ -83,6 +83,7 @@ is_arm_bl_or_blx(uint32_t insn)
/* Checks if given THUMB instruction is BL, or BLX.
* Param:
* insn - THUMB instruction to check.
+ * pc - Emulated PC address for the instruction.
* ret_off - If insn is BL, or BLX, upon return ret_off contains
* instruction's byte size. If instruction is not BL, or BLX, content of
* this parameter is undefined on return.
@@ -90,7 +91,7 @@ is_arm_bl_or_blx(uint32_t insn)
* boolean: 1 if THUMB instruction is BL/BLX, or 0 if it's not.
*/
static inline int
-is_thumb_bl_or_blx(uint16_t insn, target_ulong* ret_off)
+is_thumb_bl_or_blx(uint16_t insn, target_ulong pc, target_ulong* ret_off)
{
/* THUMB BLX(register): 0100 0111 1xxx xxxx
* THUMB BL(1-stimmediate): 1111 0xxx xxxx xxxx
@@ -100,8 +101,12 @@ is_thumb_bl_or_blx(uint16_t insn, target_ulong* ret_off)
*ret_off = 2;
return 1;
} else if ((insn & 0xF800) == 0xF000) { // THUMB BL(X)(imm)
- *ret_off = 4;
- return 1;
+ // This is a 32-bit THUMB. Get the second half of the instuction.
+ insn = lduw_code(pc + 2);
+ if ((insn & 0xC000) == 0xC000) {
+ *ret_off = 4;
+ return 1;
+ }
}
return 0;
}
@@ -110,6 +115,9 @@ is_thumb_bl_or_blx(uint16_t insn, target_ulong* ret_off)
* NOTE: If return address has been registered as new in this routine, this will
* cause invalidation of all existing TBs that contain translated code for that
* address.
+ * NOTE: Before storing PC address in the array, we convert it from emulated
+ * address to a physical address. This way we deal with emulated addresses
+ * overlapping for different processes.
* Param:
* env - CPU state environment.
* addr - Return address to register.
@@ -125,11 +133,9 @@ register_ret_address(CPUState* env, target_ulong addr)
if ((0x90000000 <= addr && addr <= 0xBFFFFFFF)) {
/* Address belongs to a module that always loads at this fixed address.
* So, we can keep this address in the global array. */
- ret = addrarray_add(&ret_addresses, addr);
+ ret = addrarray_add(&ret_addresses, get_phys_addr_code(env, addr));
} else {
- /* TODO: Figure out how to move "floating" part to the process
- * descriptor. */
- ret = addrarray_add(&ret_addresses, addr);
+ ret = addrarray_add(&ret_addresses, get_phys_addr_code(env, addr));
}
assert(ret != 0);
@@ -164,12 +170,12 @@ register_ret_address(CPUState* env, target_ulong addr)
* or 0 if it's not.
*/
static inline int
-is_ret_address(target_ulong addr)
+is_ret_address(CPUState* env, target_ulong addr)
{
if ((0x90000000 <= addr && addr <= 0xBFFFFFFF)) {
- return addrarray_check(&ret_addresses, addr);
+ return addrarray_check(&ret_addresses, get_phys_addr_code(env, addr));
} else {
- return addrarray_check(&ret_addresses, addr);
+ return addrarray_check(&ret_addresses, get_phys_addr_code(env, addr));
}
}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 6c8ebde..ca04700 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5813,7 +5813,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
#ifdef CONFIG_MEMCHECK
if (watch_call_stack(s)) {
- if (is_ret_address(s->pc)) {
+ if (is_ret_address(env, s->pc)) {
set_on_ret(s->pc);
}
if (is_arm_bl_or_blx(insn)) {
@@ -8197,10 +8197,10 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
#ifdef CONFIG_MEMCHECK
if (watch_call_stack(s)) {
target_ulong ret_off;
- if (is_ret_address(s->pc)) {
+ if (is_ret_address(env, s->pc)) {
set_on_ret(s->pc);
}
- if (is_thumb_bl_or_blx(insn, &ret_off)) {
+ if (is_thumb_bl_or_blx(insn, s->pc, &ret_off)) {
set_on_call(s->pc, s->pc + ret_off);
if (!s->search_pc) {
register_ret_address(env, s->pc + ret_off);