1 /*
2  *	HT Editor
3  *	analy.h
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 #ifndef analy_h
22 #define analy_h
23 
24 #include "asm.h"
25 #include "data.h"
26 #include "code_analy.h"
27 #include "data_analy.h"
28 #include "stddata.h"
29 
30 extern int num_ops_parsed;
31 
32 class Analyser;
33 
34 #define ADDRESS_STRING_FORMAT_COMPACT            0
35 #define ADDRESS_STRING_FORMAT_LEADING_WHITESPACE 1
36 #define ADDRESS_STRING_FORMAT_LEADING_ZEROS      2
37 #define ADDRESS_STRING_FORMAT_RESERVED           3
38 
39 #define ADDRESS_STRING_FORMAT_HEX_CAPS		    4
40 #define ADDRESS_STRING_FORMAT_ADD_0X		    8
41 #define ADDRESS_STRING_FORMAT_ADD_H		   16
42 
43 class Address: public Object {
44 public:
Address()45 				Address() {};
Address(BuildCtorArg & a)46 				Address(BuildCtorArg&a): Object(a) {};
47 	virtual	bool		add(int offset) = 0;
48 	virtual	int		byteSize() = 0;
49 	virtual Address	*	clone() const = 0;
50 	virtual	int		compareDelinear(Address *to);
51 	virtual	bool 		difference(int &result, Address *to) = 0;
52 	virtual	void 		getFromArray(const byte *array) = 0;
53 	virtual	void 		getFromCPUAddress(CPU_ADDR *ca) = 0;
54 	virtual	bool		getFromUInt64(uint64 u) = 0;
55 	virtual	bool 		isValid();
56 	virtual	int		parseString(const char *s, int length, Analyser *a) = 0;
57 	virtual	void		putIntoArray(byte *array) const = 0;
58 	virtual	void		putIntoCPUAddress(CPU_ADDR *ca) const = 0;
59 	virtual	bool		putIntoUInt64(uint64 &u) const = 0;
60 	virtual	int		stringify(char *s, int max_length, int format) const = 0;
61 	virtual	int		stringSize() const = 0;
62 	virtual	int		toString(char *buf, int buflen) const;
63 };
64 
65 class InvalidAddress: public Address {
66 public:
InvalidAddress()67 				InvalidAddress() {};
InvalidAddress(BuildCtorArg & a)68 				InvalidAddress(BuildCtorArg&a): Address(a) {};
69 	virtual	bool		add(int offset);
70 	virtual	int		byteSize();
71 	virtual	int		compareTo(const Object *obj) const;
72 	virtual	bool		difference(int &result, Address *to);
73 	virtual	InvalidAddress *clone() const;
74 	virtual	void 		getFromArray(const byte *array);
75 	virtual	void		getFromCPUAddress(CPU_ADDR *ca);
76 	virtual	bool		getFromUInt64(uint64 u);
77 	virtual	bool		isValid();
78 	virtual	ObjectID	getObjectID() const;
79 	virtual	int		parseString(const char *s, int length, Analyser *a);
80 	virtual	void 		putIntoArray(byte *array) const;
81 	virtual	void 		putIntoCPUAddress(CPU_ADDR *ca) const;
82 	virtual	bool		putIntoUInt64(uint64 &u) const;
83 	virtual	int		stringify(char *s, int max_length, int format) const;
84 	virtual	int		stringSize() const;
85 };
86 
87 /*
88  *	This address type will be used by most analysers, so we define it here.
89  */
90 class AddressFlat32: public Address {
91 public:
92 	uint32 addr;
AddressFlat32(BuildCtorArg & a)93 				AddressFlat32(BuildCtorArg&a): Address(a) {};
addr(a)94 				AddressFlat32(uint32 a=0): addr(a) {};
95 	virtual	bool		add(int offset);
96 	virtual	int		byteSize();
97 	virtual	AddressFlat32 *	clone() const;
98 	virtual	int		compareTo(const Object *obj) const;
99 	virtual	int		compareDelinear(Address *to);
100 	virtual	void		getFromArray(const byte *array);
101 	virtual	void		getFromCPUAddress(CPU_ADDR *ca);
102 	virtual	bool		getFromUInt64(uint64 u);
103 	virtual	bool		difference(int &result, Address *to);
104 	virtual	void		load(ObjectStream &s);
105 	virtual	ObjectID	getObjectID() const;
106 	virtual	int		parseString(const char *s, int length, Analyser *a);
107 	virtual	void		putIntoArray(byte *array) const;
108 	virtual	void		putIntoCPUAddress(CPU_ADDR *ca) const;
109 	virtual	bool		putIntoUInt64(uint64 &u) const;
110 	virtual	void		store(ObjectStream &s) const;
111 	virtual	int		stringify(char *s, int max_length, int format) const;
112 	virtual	int		stringSize() const;
113 };
114 
115 class AddressFlat64: public Address {
116 public:
117 	uint64 addr;
AddressFlat64(BuildCtorArg & a)118 				AddressFlat64(BuildCtorArg&a): Address(a) {};
addr(a)119 				AddressFlat64(uint64 a=0): addr(a) {};
120 	virtual	bool		add(int offset);
121 	virtual	int		byteSize();
122 	virtual	int		compareTo(const Object *obj) const;
123 	virtual	int		compareDelinear(Address *to);
124 	virtual	void		getFromArray(const byte *array);
125 	virtual	void		getFromCPUAddress(CPU_ADDR *ca);
126 	virtual	bool		getFromUInt64(uint64 u);
127 	virtual	bool		difference(int &result, Address *to);
128 	virtual	AddressFlat64 *	clone() const;
129 	virtual	void		load(ObjectStream &s);
130 	virtual	ObjectID	getObjectID() const;
131 	virtual	int		parseString(const char *s, int length, Analyser *a);
132 	virtual	void		putIntoArray(byte *array) const;
133 	virtual	void		putIntoCPUAddress(CPU_ADDR *ca) const;
134 	virtual	bool		putIntoUInt64(uint64 &u) const;
135 	virtual	void		store(ObjectStream &s) const;
136 	virtual	int		stringify(char *s, int max_length, int format) const;
137 	virtual	int		stringSize() const;
138 };
139 
140 #define ANALY_SEGMENT_CAP_WRITE 1
141 #define ANALY_SEGMENT_CAP_INITIALIZED 2
142 // other caps can be defined locally
143 
144 class Segment: public Object {
145 	Address *start, *end;
146 	char *name;
147 	int caps;
148 
149 					Segment(const char *n, Address *s, Address *e, int c, int address_size);
150 	virtual	bool			containsAddress(Address *addr) = 0;
151 	virtual	String &		getName(String &res);
152 	virtual	int			getAddressSize();
153 	virtual	int			getCapability(int cap);
154 };
155 
156 /*
157  *	these are the different possibilities of a branch
158  *	to support further processors other types can be added
159  */
160 enum branch_enum_t {
161 			br_nobranch,					// straight exec. flow
162 			br_jump,
163 			br_return,
164 			br_call,
165 			br_jXX
166 };
167 
168 /*
169  *   internal opcodes are interchanged in this format
170  */
171 #define OPCODE dis_insn
172 
173 /*
174  *
175  */
176 class AnalyDisassembler: public Object {
177 public:
178 	Analyser		*analy;
179 	Disassembler		*disasm;
180 					AnalyDisassembler();
AnalyDisassembler(BuildCtorArg & a)181 					AnalyDisassembler(BuildCtorArg &a): Object(a) {};
182 
183 		void			init(Analyser *A);
184 
185 	virtual	Address *		branchAddr(OPCODE *opcode, branch_enum_t branchtype, bool examine) = 0;
186 	virtual	void			examineOpcode(OPCODE *opcode) = 0;
187 	virtual	void			initDisasm();
188 	virtual	branch_enum_t		isBranch(OPCODE *opcode) = 0;
189 };
190 
191 /***************************************************************************/
192 
193 enum xref_enum_t {
194 	xrefread,
195 	xrefwrite,
196 	xrefoffset,
197 	xrefjump,
198 	xrefcall,
199 	xrefijump,
200 	xreficall
201 };
202 
203 class AddrXRef: public Object {
204 public:
205 	Address		*addr;
206 	xref_enum_t	type;
207 				AddrXRef(Address *a, xref_enum_t aType = xrefread);
AddrXRef(BuildCtorArg & a)208 				AddrXRef(BuildCtorArg&a): Object(a) {};
209 	virtual			~AddrXRef();
210 	virtual	void		load(ObjectStream &s);
211 	virtual	ObjectID	getObjectID() const;
212 	virtual	void		store(ObjectStream &s) const;
213 	virtual int		compareTo(const Object *) const;
214 };
215 
216 class CommentList: public Array {
217 public:
218 				CommentList();
219 	void			appendPreComment(const char *s);
220 	void			appendPreComment(int special);
221 	void			appendPostComment(const char *s);
222 	void			appendPostComment(int special);
223 	const char *		getName(uint i);
224 };
225 
226 struct Symbol;
227 
228 struct Location {
229 	// the address
230 	Address		*addr;
231 	// this is a tree structure (key is addr)
232 	Location	*left, *right;
233 	// attached label
234 	Symbol		*label;
235 	// attached xrefs
236 	Container	*xrefs;
237 	// attached comments
238 	CommentList	*comments;
239 	// for data types
240 	taddr_type	type;
241 	// the function the address belongs to (if applicable)
242 	Location	*thisfunc;
243 	// some flags
244 	int		flags;
245 };
246 
247 /*
248  * taddr.flags:
249  */
250 #define AF_DELETED 1
251 #define AF_FUNCTION_SET 2
252 #define AF_FUNCTION_END 4
253 
254 enum tsectype {
255 	scvalid,
256 	scread,
257 	scwrite,
258 	screadwrite,
259 	sccode,
260 	scinitialized
261 };
262 
263 enum taccesstype {
264 	acread,
265 	acwrite,
266 	acoffset
267 };
268 
269 struct taccess	{
270 	bool		indexed;
271 	int		size;
272 	taccesstype 	type;
273 };
274 
275 enum labeltype {
276 	label_unknown = 0,
277 	label_func,
278 	label_loc,
279 	label_data
280 };
281 
282 struct Symbol {
283 	labeltype	type;
284 	Location *	location;
285 	char *		name;
286 	Symbol		*left, *right;
287 };
288 
289 class AddressQueueItem: public Object {
290 public:
291 	Address	*addr;
292 	Address	*func;
AddressQueueItem(BuildCtorArg & a)293 				AddressQueueItem(BuildCtorArg&a): Object(a) {};
294 				AddressQueueItem(Address *Addr, Address *Func);
295 				~AddressQueueItem();
296 	virtual	void		load(ObjectStream &s);
297 	virtual	ObjectID	getObjectID() const;
298 	virtual	void		store(ObjectStream &s) const;
299 };
300 
301 class CodeAnalyser;
302 class DataAnalyser;
303 
304 class Analyser: public Object	{
305 public:
306 	Address *		addr;
307 	Address *		invalid_addr;
308 	Queue *			addr_queue;
309 	int			ops_parsed;							// for continuing
310 	bool			active;
311 	Address			*next_explored, *first_explored, *last_explored;
312 	bool			next_address_is_invalid;
313 	Area *			explored;
314 	Area *			initialized;
315 	Location *		locations;
316 	CodeAnalyser *		code;
317 	DataAnalyser *		data;
318 	AnalyDisassembler *	analy_disasm;
319 	Disassembler *		disasm;
320 	Symbol *		symbols;
321 	int			location_threshold, symbol_threshold;
322 	int			cur_addr_ops, cur_label_ops;                 // for threshold
323 	int			max_opcode_length;
324 	Location		*cur_func;
325 	mutable bool		dirty;
326 
327 	int			symbol_count;
328 	int			location_count;
329 
Analyser()330 				Analyser() {};
Analyser(BuildCtorArg & a)331 				Analyser(BuildCtorArg&a): Object(a) {};
332 
333 		void		init();
334 	virtual	void		load(ObjectStream &s);
335 	virtual	void		done();
336 
337 		bool		addAddressSymbol(Address *Addr, const char *Prefix, labeltype type, Location *infunc=NULL);
338 		void	 	addComment(Address *Addr, int line, const char *c);
339 		bool		addSymbol(Address *Addr, const char *label, labeltype type, Location *infunc=NULL);
340 	virtual	FileOfs		addressToFileofs(Address *Addr) = 0;
341 		bool		addXRef(Address *from, Address *to, xref_enum_t action);
342 		void	 	assignComment(Address *Addr, int line, const char *c);
343 		bool		assignSymbol(Address *Addr, const char *label, labeltype type, Location *infunc=NULL);
344 		void		assignXRef(Address *from, Address *to, xref_enum_t action);
345 	virtual	void		beginAnalysis();
346 	virtual	uint		bufPtr(Address *Addr, byte *buf, int size) = 0;
347 		bool	  	continueAnalysis();
348 		void		continueAnalysisAt(Address *Addr);
349 	virtual	Address* createAddress() = 0;
350 		void		dataAccess(Address *Addr, taccess access);
351 		void		deleteLocation(Address *Addr);
352 		void		deleteSymbol(Address *Addr);
353 		bool		deleteXRef(Address *from, Address *to);
354 		void		disableSymbol(Symbol *label);
355 		void		doBranch(branch_enum_t branch, OPCODE *opcode, int len);
356 		void		engageCodeanalyser();
357 		Location *	enumLocations(Address *Addr);
358 		Location *	enumLocationsReverse(Address *Addr);
359 		Symbol *	enumSymbolsByName(const char *at);
360 		Symbol *	enumSymbolsByNameReverse(const char *at);
361 		Symbol *	enumSymbols(Symbol *sym);
362 		Symbol *	enumSymbolsReverse(Symbol *sym);
363 	virtual	taddr_typetype	examineData(Address *Addr);
364 		void		finish();
365 		void		freeLocation(Location *loc);
366 		void		freeLocations(Location *locs);
367 		void		freeComments(Location *loc);
368 		void		freeSymbol(Symbol *sym);
369 		void		freeSymbols(Symbol *syms);
370 		Location *	getLocationByAddress(Address *Addr);
371 		Location *	getLocationContextByAddress(Address *Addr);
372 		int		getLocationCount() const;
373 		Location *	getFunctionByAddress(Address *Addr);
374 		Location *	getPreviousSymbolByAddress(Address *Addr);
375 	virtual	const char *	getSegmentNameByAddress(Address *Addr);
376 		Symbol *	getSymbolByAddress(Address *Addr);
377 		Symbol *	getSymbolByName(const char *label);
378 		const char *	getSymbolNameByLocation(Location *loc);
379 		int		getSymbolCount() const;
380 		bool		gotoAddress(Address *Addr, Address *func);
381 	virtual	void 		initCodeAnalyser();
382 	virtual	void		initDataAnalyser();
383 	virtual	void		initUnasm() = 0;
384 	virtual bool 	isAddressFixedUp(Address *Addr, int offset);
385 	virtual	void		log(const char *s);                // stub
386 	virtual	CPU_ADDR 	mapAddr(Address *Addr);      // stub
387 		Location *	newLocation(Address *Addr);
388 		Location *	newLocation(Location *&locs, Address *Addr);
389 		Symbol *	newSymbol(const char *label, Location *loc, labeltype type, Location *infunc);
390 		Symbol *	newSymbol(Symbol *&syms, const char *label, Location *loc, labeltype type);
391 	virtual	Address *	nextValid(Address *Addr) = 0;
392 		void		optimizeLocationTree();
393 		void		optimizeSymbolTree();
394 		bool		popAddress(Address **Addr, Address **func);
395 		void		pushAddress(Address *Addr, Address *func);
396 	virtual	int		queryConfig(int mode);				// stub
397 		void		setActive(bool mode);
398 		void		setLocationFunction(Location *a, Location *func);
399 		void		setLocationTreeOptimizeThreshold(int threshold);
400 		void		setDisasm(Disassembler *d);
401 		void		setSymbolTreeOptimizeThreshold(int threshold);
402 	virtual	void		store(ObjectStream &s) const;
403 	virtual	bool		validAddress(Address *addr, tsectype action) = 0;
404 		bool		validCodeAddress(Address *addr);
405 		bool		validReadAddress(Address *addr);
406 		bool		validWriteAddress(Address *addr);
407 
408 //  interface only (there's no internal use)
409 		int	mode;
410 
411 	virtual	Assembler *	createAssembler();
412 	virtual	Address *	fileofsToAddress(FileOfs fileofs);
413 		CommentList *	getComments(Address *Addr);
414 		const char *	getDisasmStr(Address *Addr, int &length);
415 		const char *	getDisasmStrFormatted(Address *Addr);
416 		int		getDisplayMode();
417 	virtual	String &	getName(String &res);
418 	virtual	const char *	getType();
419 		Container *	getXRefs(Address *Addr);
420 		bool		isDirty();
421 		void		makeDirty();
422 		void		setDisplayMode(int enable, int disable);
423 		void		toggleDisplayMode(int toggle);
424 };
425 
426 /* display modes */
427 #define ANALY_SHOW_ADDRESS 1
428 #define ANALY_SHOW_COMMENTS 2
429 #define ANALY_SHOW_LABELS 4
430 #define ANALY_SHOW_XREFS 8
431 #define ANALY_SHOW_BYTES 16
432 #define ANALY_EDIT_BYTES 32
433 #define ANALY_TRANSLATE_SYMBOLS 64
434 #define ANALY_COLLAPSE_XREFS 128
435 
436 /* queryConfig() constants */
437 #define Q_DO_ANALYSIS 1
438 #define Q_ENGAGE_CODE_ANALYSER 2
439 #define Q_ENGAGE_DATA_ANALYSER 3
440 
441 /* interesting constants */
442 #define INVALID_FILE_OFS ((FileOfs)-1)
443 
444 /* analyser system constants */
445 #define MAX_OPS_PER_CONTINUE 10
446 
447 extern int global_analyser_address_string_format;
448 
449 #endif
450