9 int analyse_jumps (struct code
*c
, const uint8
*code
, uint32 size
, uint32 address
)
11 struct location
*base
;
12 uint32 i
, numopc
= size
>> 2;
14 if (size
& 0x03 || address
& 0x03) {
15 error (__FILE__
": size/address is not multiple of 4");
19 base
= (struct location
*) xmalloc (numopc
* sizeof (struct location
));
20 memset (base
, 0, numopc
* sizeof (struct location
));
25 for (i
= 0; i
< numopc
; i
++) {
27 base
[i
].opc
= code
[i
<< 2];
28 base
[i
].opc
|= code
[(i
<< 2) + 1] << 8;
29 base
[i
].opc
|= code
[(i
<< 2) + 2] << 16;
30 base
[i
].opc
|= code
[(i
<< 2) + 3] << 24;
31 base
[i
].itype
= allegrex_insn_type (base
[i
].opc
);
32 base
[i
].address
= address
+ (i
<< 2);
34 switch (base
[i
].itype
) {
45 base
[i
].jtype
= JTYPE_BRANCH
;
58 base
[i
].jtype
= JTYPE_BRANCHLIKELY
;
63 base
[i
].jtype
= JTYPE_BRANCHANDLINK
;
67 base
[i
].jtype
= JTYPE_BRANCHANDLINKLIKELY
;
71 base
[i
].jtype
= JTYPE_JUMP
;
75 base
[i
].jtype
= JTYPE_JUMPANDLINK
;
79 base
[i
].jtype
= JTYPE_JUMPANDLINKREGISTER
;
83 base
[i
].jtype
= JTYPE_JUMPREGISTER
;
87 base
[i
].jtype
= JTYPE_NONE
;
91 switch (base
[i
].jtype
) {
93 case JTYPE_BRANCHANDLINK
:
94 case JTYPE_BRANCHANDLINKLIKELY
:
95 case JTYPE_BRANCHLIKELY
:
96 tgt
= base
[i
].opc
& 0xFFFF;
102 if (base
[i
].jtype
== JTYPE_BRANCHANDLINK
||
103 base
[i
].jtype
== JTYPE_BRANCHANDLINKLIKELY
) {
104 LLIST_ADD (c
->pool
, base
[tgt
].callrefs
, &base
[i
]);
106 LLIST_ADD (c
->pool
, base
[tgt
].jumprefs
, &base
[i
]);
109 error (__FILE__
": branch outside file\n%s", allegrex_disassemble (base
[i
].opc
, base
[i
].address
));
111 base
[i
].target_addr
= (tgt
<< 2) + address
;
114 case JTYPE_JUMPANDLINK
:
115 base
[i
].target_addr
= (base
[i
].opc
& 0x3FFFFFF) << 2;;
116 base
[i
].target_addr
|= ((base
[i
].address
) & 0xF0000000);
117 tgt
= (base
[i
].target_addr
- address
) >> 2;
119 llist ref
= llist_alloc (c
->pool
);
120 ref
->value
= &base
[i
];
121 base
[i
].target
= &base
[tgt
];
122 if (base
[i
].jtype
== JTYPE_JUMPANDLINK
) {
123 ref
->next
= base
[tgt
].callrefs
;
124 base
[tgt
].callrefs
= ref
;
126 ref
->next
= base
[tgt
].jumprefs
;
127 base
[tgt
].jumprefs
= ref
;
130 error (__FILE__
": jump outside file\n%s", allegrex_disassemble (base
[i
].opc
, base
[i
].address
));
134 base
[i
].target_addr
= 0;
140 if (base
[i
].callrefs
) {
141 LLIST_ADD (c
->pool
, c
->subroutines
, &base
[i
]);
149 int analyse_relocs (struct code
*c
)
155 int analyse_registers (struct code
*c
)
161 struct code
* analyse_code (struct prx
*p
)
164 c
= (struct code
*) xmalloc (sizeof (struct code
));
166 c
->pool
= llist_create ();
167 c
->subroutines
= NULL
;
169 if (!analyse_jumps (c
, p
->programs
->data
,
170 p
->modinfo
->expvaddr
- 4, p
->programs
->vaddr
)) {
175 if (!analyse_relocs (c
)) {
184 void free_code (struct code
*c
)
190 llist_destroy (c
->pool
);
195 void print_code (struct code
*c
)
199 for (i
= 0; i
< c
->numopc
; i
++) {
200 if (c
->base
[i
].callrefs
|| c
->base
[i
].jumprefs
) {
204 if (c
->base
[i
].callrefs
) {
206 report ("; Called from: ");
207 for (l
= c
->base
[i
].callrefs
; l
; l
= l
->next
) {
208 struct location
*loc
= (struct location
*) l
->value
;
209 report ("0x%08X ", loc
->address
);
213 if (c
->base
[i
].jumprefs
) {
215 report ("; Jumped from: ");
216 for (l
= c
->base
[i
].jumprefs
; l
; l
= l
->next
) {
217 struct location
*loc
= (struct location
*) l
->value
;
218 report ("0x%08X ", loc
->address
);
222 report ("%s", allegrex_disassemble (c
->base
[i
].opc
, c
->base
[i
].address
));