1 /*
2 * HT Editor
3 * analy_java.cc
4 *
5 * Copyright (C) 1999-2002 Sebastian Biallas (sb@biallas.net)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <string.h>
22
23 #include "analy_register.h"
24 #include "analy_java.h"
25 #include "htdebug.h"
26 #include "javadis.h"
27 #include "strtools.h"
28 #include "snprintf.h"
29
init(Analyser * A,java_token_func token_func,void * context)30 void AnalyJavaDisassembler::init(Analyser *A, java_token_func token_func, void *context)
31 {
32 disasm = new javadis(token_func, context);
33 AnalyDisassembler::init(A);
34 }
35
36 /*
37 *
38 */
getObjectID() const39 ObjectID AnalyJavaDisassembler::getObjectID() const
40 {
41 return ATOM_ANALY_JAVA;
42 }
43
44 /*
45 *
46 */
47
branchAddr(OPCODE * opcode,branch_enum_t branchtype,bool examine)48 Address *AnalyJavaDisassembler::branchAddr(OPCODE *opcode, branch_enum_t branchtype, bool examine)
49 {
50 javadis_insn *o = (javadis_insn*)opcode;
51 switch (o->op[0].type) {
52 case JAVA_OPTYPE_LABEL:
53 return new AddressFlat32(o->op[0].label);
54 }
55 return new InvalidAddress();
56 }
57
read4(Analyser * a,Address & addr,byte * b)58 static uint32 read4(Analyser *a, Address &addr, byte *b)
59 {
60 if (a->bufPtr(&addr, b, 4) != 4) throw 1;
61 addr.add(4);
62 return (b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3];
63 }
64
examineOpcode(OPCODE * opcode)65 void AnalyJavaDisassembler::examineOpcode(OPCODE *opcode)
66 {
67 javadis_insn *o = (javadis_insn*)opcode;
68 const char *opcode_str = o->name;
69 if (strcmp("lookupswitch", opcode_str) == 0) {
70 uint32 ofs = o->addr;
71 AddressFlat32 c(ofs);
72 Location *loc = analy->getFunctionByAddress(&c);
73 if (loc) {
74 AddressFlat32 *func = (AddressFlat32 *)loc->addr;
75 uint32 f = func->addr;
76 ofs = ofs+1 - f;
77 while (ofs % 4) {
78 AddressFlat32 iofs(f+ofs);
79 analy->data->setIntAddressType(&iofs, dst_ibyte, 1);
80 ofs++;
81 }
82 AddressFlat32 iofs(f + ofs);
83 byte buf[4];
84 try {
85 analy->data->setIntAddressType(&iofs, dst_idword, 4);
86 uint32 default_ofs = read4(analy, iofs, buf);
87 analy->data->setIntAddressType(&iofs, dst_idword, 4);
88 uint32 n = read4(analy, iofs, buf);
89
90 for (uint32 i=0; i < n; i++) {
91 char buffer[100];
92 analy->data->setIntAddressType(&iofs, dst_idword, 4);
93 uint32 value = read4(analy, iofs, buf);
94 analy->data->setIntAddressType(&iofs, dst_idword, 4);
95 uint32 rel_ofs = read4(analy, iofs, buf);
96 AddressFlat32 a(o->addr + rel_ofs);
97 if (!analy->getLocationByAddress(&a)) analy->addComment(&a, 0, "");
98 ht_snprintf(buffer, sizeof buffer, "lookupswitch value: %d", value);
99 analy->addComment(&a, 0, buffer);
100 analy->addAddressSymbol(&a, "lookup", label_loc, loc);
101 analy->pushAddress(&a, func);
102 analy->addXRef(&a, &c, xrefijump);
103 }
104 AddressFlat32 a(o->addr + default_ofs);
105 analy->addComment(&a, 0, "");
106 analy->addComment(&a, 0, "lookupswitch default");
107 analy->addAddressSymbol(&a, "lookup", label_loc, loc);
108 analy->pushAddress(&a, func);
109 analy->addXRef(&a, &c, xrefijump);
110 } catch (...) {
111 return;
112 }
113 }
114 } else if (strcmp("tableswitch", opcode_str) == 0) {
115 uint32 ofs = o->addr;
116 AddressFlat32 c(ofs);
117 Location *loc = analy->getFunctionByAddress(&c);
118 if (loc) {
119 AddressFlat32 *func = (AddressFlat32 *)loc->addr;
120 uint32 f = func->addr;
121 ofs = ofs+1 - f;
122 while (ofs % 4) {
123 AddressFlat32 iofs(f+ofs);
124 analy->data->setIntAddressType(&iofs, dst_ibyte, 1);
125 ofs++;
126 }
127 AddressFlat32 iofs(f + ofs);
128 byte buf[4];
129 try {
130 analy->data->setIntAddressType(&iofs, dst_idword, 4);
131 uint32 default_ofs = read4(analy, iofs, buf);
132 analy->data->setIntAddressType(&iofs, dst_idword, 4);
133 sint32 low = read4(analy, iofs, buf);
134 analy->data->setIntAddressType(&iofs, dst_idword, 4);
135 sint32 high = read4(analy, iofs, buf);
136
137 for (sint32 i=low; i <= high; i++) {
138 char buffer[100];
139 analy->data->setIntAddressType(&iofs, dst_idword, 4);
140 uint32 rel_ofs = read4(analy, iofs, buf);
141 AddressFlat32 a(o->addr + rel_ofs);
142 if (!analy->getLocationByAddress(&a)) analy->addComment(&a, 0, "");
143 ht_snprintf(buffer, sizeof buffer, "tableswitch value: %d", i);
144 analy->addComment(&a, 0, buffer);
145 analy->addAddressSymbol(&a, "table", label_loc, loc);
146 analy->pushAddress(&a, func);
147 analy->addXRef(&a, &c, xrefijump);
148 }
149 AddressFlat32 a(o->addr + default_ofs);
150 analy->addComment(&a, 0, "");
151 analy->addComment(&a, 0, "tableswitch default");
152 analy->addAddressSymbol(&a, "table", label_loc, loc);
153 analy->pushAddress(&a, func);
154 analy->addXRef(&a, &c, xrefijump);
155 } catch (...) {
156 return;
157 }
158 }
159 }
160 }
161
162 /*
163 *
164 */
isBranch(OPCODE * opcode)165 branch_enum_t AnalyJavaDisassembler::isBranch(OPCODE *opcode)
166 {
167 javadis_insn *o = (javadis_insn*)opcode;
168 const char *opcode_str = o->name;
169 if ((opcode_str[0]=='i') && (opcode_str[1]=='f')) {
170 return br_jXX;
171 } else if ((strcmp("tableswitch", opcode_str)==0)
172 || (strcmp("lookupswitch", opcode_str)==0)) {
173 examineOpcode(opcode);
174 return br_jump;
175 } else if (ht_strncmp("ret", opcode_str, 3)==0
176 || ht_strncmp("ret", opcode_str+1, 3)==0
177 || ht_strncmp("athrow", opcode_str, 6)==0) {
178 return br_return;
179 } else if (ht_strncmp("goto", opcode_str, 4)==0) {
180 return br_jump;
181 } else if (ht_strncmp("jsr", opcode_str, 3)==0) {
182 return br_call;
183 } else return br_nobranch;
184 }
185