summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/unwarminder/SOURCES1
-rw-r--r--lib/unwarminder/backtrace.c10
-rw-r--r--lib/unwarminder/safe_read.S143
-rw-r--r--lib/unwarminder/safe_read.h33
4 files changed, 181 insertions, 6 deletions
diff --git a/lib/unwarminder/SOURCES b/lib/unwarminder/SOURCES
index 055e6d0ab3..b060e2908d 100644
--- a/lib/unwarminder/SOURCES
+++ b/lib/unwarminder/SOURCES
@@ -5,3 +5,4 @@ unwarm.c
5unwarminder.c 5unwarminder.c
6unwarmmem.c 6unwarmmem.c
7unwarm_thumb.c 7unwarm_thumb.c
8safe_read.S \ No newline at end of file
diff --git a/lib/unwarminder/backtrace.c b/lib/unwarminder/backtrace.c
index 4e1609137c..294b7f66f4 100644
--- a/lib/unwarminder/backtrace.c
+++ b/lib/unwarminder/backtrace.c
@@ -23,6 +23,7 @@
23 ***************************************************************************/ 23 ***************************************************************************/
24 24
25#include "backtrace.h" 25#include "backtrace.h"
26#include "safe_read.h"
26 27
27/*************************************************************************** 28/***************************************************************************
28 * Prototypes 29 * Prototypes
@@ -86,20 +87,17 @@ static Boolean CliReport(void *data, Int32 address)
86 87
87static Boolean CliReadW(const Int32 a, Int32 *v) 88static Boolean CliReadW(const Int32 a, Int32 *v)
88{ 89{
89 *v = *(Int32 *)a; 90 return safe_read32((uint32_t *)a, (uint32_t *)v);
90 return TRUE;
91} 91}
92 92
93static Boolean CliReadH(const Int32 a, Int16 *v) 93static Boolean CliReadH(const Int32 a, Int16 *v)
94{ 94{
95 *v = *(Int16 *)a; 95 return safe_read16((void *)a, (uint16_t *)v);
96 return TRUE;
97} 96}
98 97
99static Boolean CliReadB(const Int32 a, Int8 *v) 98static Boolean CliReadB(const Int32 a, Int8 *v)
100{ 99{
101 *v = *(Int8 *)a; 100 return safe_read8((void *)a, (uint8_t *)v);
102 return TRUE;
103} 101}
104 102
105Boolean CliInvalidateW(const Int32 a) 103Boolean CliInvalidateW(const Int32 a)
diff --git a/lib/unwarminder/safe_read.S b/lib/unwarminder/safe_read.S
new file mode 100644
index 0000000000..2e3fc78955
--- /dev/null
+++ b/lib/unwarminder/safe_read.S
@@ -0,0 +1,143 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22
23.data
24was_aborted:
25 .word 0
26
27.section .text.safe_read8
28.type safe_read8, %function
29.global safe_read8
30@ bool safe_read8(uint8_t *addr, uint8_t *value)
31safe_read8:
32 @ was_aborted = 0
33 ldr r2, =was_aborted
34 mov r3, #0
35 str r3, [r2]
36 @ r0=*addr
37safe_read8_faulty_addr:
38 ldrb r0, [r0]
39 @ if(was_aborted)
40 ldr r2, [r2]
41 cmp r2, #1
42 @ return false;
43 moveq r0, #0
44 bxeq lr
45 @ if(value != NULL)
46 cmp r1, #0
47 @ *value = r0
48 strneb r0, [r1]
49 @ return true;
50 mov r0, #1
51 bx lr
52.size safe_read8, . - safe_read8
53
54.section .text.safe_read16
55.type safe_read16, %function
56.global safe_read16
57@ bool safe_read16(uint16_t *addr, uint16_t *value)
58safe_read16:
59 @ was_aborted = 0
60 ldr r2, =was_aborted
61 mov r3, #0
62 str r3, [r2]
63 @ r0=*addr
64safe_read16_faulty_addr:
65 ldrh r0, [r0]
66 @ if(was_aborted)
67 ldr r2, [r2]
68 cmp r2, #1
69 @ return false;
70 moveq r0, #0
71 bxeq lr
72 @ if(value != NULL)
73 cmp r1, #0
74 @ *value = r0
75 strneh r0, [r1]
76 @ return true;
77 mov r0, #1
78 bx lr
79.size safe_read16, . - safe_read16
80
81.section .text.safe_read32
82.type safe_read32, %function
83.global safe_read32
84@ bool safe_read32(uint32_t *addr, uint32_t *value)
85safe_read32:
86 @ was_aborted = 0
87 ldr r2, =was_aborted
88 mov r3, #0
89 str r3, [r2]
90 @ r0=*addr
91safe_read32_faulty_addr:
92 ldr r0, [r0]
93 @ if(was_aborted)
94 ldr r2, [r2]
95 cmp r2, #1
96 @ return false;
97 moveq r0, #0
98 bxeq lr
99 @ if(value != NULL)
100 cmp r1, #0
101 @ *value = r0
102 strne r0, [r1]
103 @ return true;
104 mov r0, #1
105 bx lr
106.size safe_read32, . - safe_read32
107
108#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
109.section .text.data_abort_handler
110.type data_abort_handler, %function
111.global data_abort_handler
112data_abort_handler:
113 @ store minimal amount of registers
114 stmfd sp!, {r0-r1}
115 @ compute faulty address
116 sub r0, lr, #8
117 @ compare to safe_read8
118 ldr r1, =safe_read8_faulty_addr
119 cmp r0, r1
120 beq 1f
121 @ compare to safe_read16
122 ldr r1, =safe_read16_faulty_addr
123 cmp r0, r1
124 beq 1f
125 @ compare to safe_read32
126 ldr r1, =safe_read32_faulty_addr
127 cmp r0, r1
128 beq 1f
129 @ otherwise just normally to UIE
130 mov r0, r1
131 mov r1, #2
132 b UIE
1331:
134 @ set was_aborted
135 ldr r1, =was_aborted
136 mov r0, #1
137 str r0, [r1]
138 @ restore registers
139 ldmfd sp!, {r0-r1}
140 @ restore mode and jump back to the *next* instruction
141 subs pc, lr, #-4
142.size data_abort_handler, . - data_abort_handler
143#endif
diff --git a/lib/unwarminder/safe_read.h b/lib/unwarminder/safe_read.h
new file mode 100644
index 0000000000..0ad23e648d
--- /dev/null
+++ b/lib/unwarminder/safe_read.h
@@ -0,0 +1,33 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef __SAFE_READ__
22#define __SAFE_READ__
23
24#include "system.h"
25
26/* Try to read an X-bit unsigned integer. If the address is not readable,
27 * returns false. Otherwise returns true and store the result in *value
28 * if value is not NULL */
29bool safe_read8(uint8_t *addr, uint8_t *value);
30bool safe_read16(uint16_t *addr, uint16_t *value);
31bool safe_read32(uint32_t *addr, uint32_t *value);
32
33#endif /* __SAFE_READ__ */ \ No newline at end of file