-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathinstr.c
112 lines (94 loc) · 2.98 KB
/
instr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
instr.c
Copyright (C) 2015 Juha Aaltonen
This file is part of standalone gdb stub for Raspberry Pi 2B.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Stuff needed for finding out where to place traps in single stepping
*/
#include <stdint.h>
#include "instr.h"
#include "rpi2.h"
#include "ARM_decode_table.h"
#include "log.h"
// handle thumb instructions
instr_next_addr_t next_address_thumb(unsigned int address)
{
instr_next_addr_t retval;
unsigned int instr; // both half-words if 32-bit
unsigned short *tptr; // thumb instruction pointer
// not supported yet
// either one or two 16-bit integers
retval = set_undef_addr();
tptr = (unsigned short *) address;
instr = (*tptr++) << 16;
instr |= *tptr;
// call THUMB decoding
// TODO: add Thumb support
return retval;
}
// handle ARM instructions
instr_next_addr_t next_address_arm(unsigned int address)
{
instr_next_addr_t retval;
unsigned int instr;
retval = set_undef_addr();
instr = *((unsigned int *) address);
retval = ARM_decoder_dispatch(instr);
// if execution is linear, address = 0xffffffff is returned
// here we get the true address
if ((retval.flag & INSTR_ADDR_ARM) && (retval.address == 0xffffffff))
{
// get next address for linear execution
// PABT leaves PC to point at the instruction that caused PABT,
// in our case BKPT. We have to skip that to reach the address
// after the BKPT (BKPT is replaced with the restored instruction).
retval.address = rpi2_reg_context.reg.r15 + 4;
}
else if ((retval.flag & INSTR_ADDR_THUMB) && (retval.address == 0xffffffff))
{
// get next address for linear execution
// PABT leaves PC to point at the instruction that caused PABT,
// in our case BKPT. We have to skip that to reach the address
// after the BKPT (BKPT is replaced with the restored instruction).
retval.address = rpi2_reg_context.reg.r15 + 2;
}
return retval;
}
// finds out the branch info about the instruction at address
instr_next_addr_t next_address(unsigned int address)
{
instr_next_addr_t retval;
retval = set_undef_addr();
// if 'J'-bit is set, not supported
if (!(rpi2_reg_context.reg.cpsr & (1 << 24)))
{
// ARM or Thumb? (bit 5 = 'T'-bit)
if (rpi2_reg_context.reg.cpsr & (1 << 5))
{
// check 16-bit alignment of the address
if (!(address & 1))
{
retval = next_address_thumb(address);
}
}
else
{
// check 32-bit alignment of the address
if (!(address & 3))
{
retval = next_address_arm(address);
}
}
}
return retval;
}