Add '#define HAVE_PROCFS', move '#include "fopen-same.h" to end of file
[deliverable/binutils-gdb.git] / gdb / tdesc.c
CommitLineData
dd3b648e
RP
1/* This file has been modified by Data General Corporation, November 1989. */
2
3/*
4This file provides an abstract interface to "tdesc" information.
5 It is designed to be used in a uniform manner by several kinds
6 of debuggers:
7 (1) code in live debugged process (e.g., a traceback routine)
8 (2) a separate-process debugger debugging a live process
9 (3) a separate-process debugger debugging a memory dump
10
11 Dcontext model notes
12 * captures machine context
13 * partial: excludes memory
14 * frames
15 * kinds
16 * make one for starters, chain in reverse order to previous ones
17 * representation: pointer to opaque
18 * alloc/free protocol
19
20 Overall model
21 * access functions
22 * handle
23 * error handling
24*/
25
26
27
28typedef int dc_boolean_t; /* range 0 .. 1 */
29#define DC_FALSE 0
30#define DC_TRUE 1
31
32
33typedef int dc_tristate_t; /* range 0 .. 2 */
34#define DC_NO 0
35#define DC_YES 1
36#define DC_MAYBE 2
37
38
39/*
40 A word is 32 bits of information. In memory, a word is word-aligned.
41
42 A common and important use of dc_word_t is to represent values in the
43 target process, including (byte) addresses in the target process.
44 In this case, C arithmetic can be used to simulate machine address
45 arithmetic on the target. (Unsigned arithmetic is actually modulus
46 arithmetic.)
47*/
48typedef unsigned int dc_word_t;
49
50
51/* These bit operations number bits from 0 at the least significant end. */
52#define bit_test(word,bit) ((word) & (1 << (bit))) /* returns 0 or other */
53#define bit_value(word,bit) (((word) >> (bit)) & 1) /* returns 0 or 1 */
54#define bit_set(word,bit) ((word) |= (1 << (bit)))
55#define bit_clear(word,bit) ((word) &= ~(1 << (bit)))
56#define bit_assign(word, bit, bool) \
57 if (bool) bit_set(word, bit); else bit_clear(word, bit)
58
59
60/*----------------*/
61
62
63/* The exactness of locations may not be certainly known. */
64typedef dc_tristate_t dc_exactness_t;
65
66
67/*
68 The model includes five kinds of contexts. Because each context
69 has an associated region and frame, these describe region kinds
70 and frame kinds as well.
71 [more description needed]
72 Currently, only call contexts exist.
73*/
74
75typedef int dc_kind_t; /* range 0 .. 4 */
76#define DC_CALL_KIND 0
77#define DC_SAVE_KIND 1
78#define DC_EXCEPTION_KIND 2
79#define DC_PROTECTION_KIND 3
80#define DC_SPECIAL_KIND 4
81#define DC_NUM_KINDS 5
82
83#define DC_MIO_ENTRY_POINT (1<< 0)
84#define DC_MIO_PROLOGUE_END (1<< 1)
85#define DC_MIO_EPILOGUE_START (1<< 2)
86#define DC_MIO_IMPLICIT_PROLOGUE_END (1<<16)
87#define DC_MIO_LITERAL_ENTRY_POINT (1<<17)
88#define DC_MIO_LITERAL_EPILOGUE_START (1<<18)
89
90#define DC_MII_PRECEDING_TDESC_END (1<<0)
91#define DC_MII_FOLLOWING_TDESC_START (1<<1)
92
93typedef struct dc_debug_info {
94 unsigned int protocol; /* 1 for this structure */
95 dc_word_t tdesc_ptr;
96 unsigned int text_words_count;
97 dc_word_t text_words_ptr;
98 unsigned int data_words_count;
99 dc_word_t data_words_ptr;
100} dc_debug_info_t;
101
102
103typedef struct tdesc_hdr {
104 unsigned int map_protocol; /* 1 for this structure */
105 unsigned int end; /* address beyond end */
106} tdesc_hdr_t;
107
108
109typedef struct tdesc_chunk_hdr {
110 int zeroes : 8;
111 int info_length : 22;
112 int info_alignment : 2;
113 unsigned int info_protocol;
114 dc_word_t start_address;
115 dc_word_t end_address;
116} tdesc_chunk_hdr_t;
117
118
119typedef struct tdesc_chunk_info1 {
120 int variant : 8; /* 1 for this structure */
121 int register_save_mask : 17;
122 int pad1 : 1;
123 int return_address_info_discriminant : 1;
124 int frame_address_register : 5;
125 unsigned int frame_address_offset;
126 unsigned int return_address_info;
127 unsigned int register_save_offset;
128} tdesc_chunk_info1_t;
129
130
131typedef struct tdesc_chunk1 {
132 tdesc_chunk_hdr_t hdr;
133 tdesc_chunk_info1_t info;
134} tdesc_chunk1_t;
135
136
137typedef struct dc_mstate {
138 dc_word_t reg[32]; /* general registers */
139 dc_word_t xip;
140 dc_word_t nip;
141 dc_word_t fip;
142 dc_word_t fpsr;
143 dc_word_t fpcr;
144 dc_word_t psr;
145} dc_mstate_t;
146
147
148typedef struct dc_map_info_in {
149 dc_word_t flags;
150 dc_word_t preceding_tdesc_end;
151 dc_word_t following_tdesc_start;
152} dc_map_info_in_t;
153
154
155typedef struct dc_map_info_out {
156 dc_word_t flags;
157 dc_word_t entry_point;
158 dc_word_t prologue_end;
159 dc_word_t epilogue_start;
160} dc_map_info_out_t;
161
162
163#if 0
164
165 void error_fcn (env, continuable, message)
166 dc_word_t env; /* environment (arbitrary datum) */
167 dc_boolean_t continuable; /* whether error function may return */
168 char *message; /* string (no trailing newline) */
169
170 /* In the future, we probably want the error_fcn to be: */
171 void error_fcn (env, continuable, code, ...)
172 dc_word_t env; /* environment (arbitrary datum) */
173 dc_boolean_t continuable; /* whether error function may return */
174 int code; /* error code */
175 ... /* parameters to message associated
176 with the code */
177
178 void read_fcn (env, memory, length, buffer)
179 dc_word_t env; /* environment (arbitrary datum) */
180 dc_word_t memory; /* start address in image */
181 int length; /* in bytes */
182 char *buffer; /* start address of buffer */
183 /* There are no alignment assumptions for the read function. */
184
185 void write_fcn (env, memory, length, buffer)
186 dc_word_t env; /* environment (arbitrary datum) */
187 dc_word_t memory; /* start address in image */
188 int length; /* in bytes */
189 char *buffer; /* start address of buffer */
190 /* There are no alignment assumptions for the write function. */
191 /* The write function is optional. It must be provided if changes
192 to writable registers are to be made. */
193
194 void exec_fcn (env, mstate)
195 dc_word_t env; /* environment (arbitrary datum) */
196 dc_mstate_t *mstate; /* machine state (read-write) */
197 /* The execute function is optional. It would be used (in the future)
198 by the implementation of a procedurally specified tdesc mechanism. */
199
200#endif
201
202/*----------------*/
203
204
205#ifndef NULL
206#define NULL ((void *) 0)
207#endif
208
209extern char *malloc();
210extern char *calloc();
211extern void qsort();
212
213
214/*
215 At initialization, create a tdesc table from the tdesc info.
216 A tdesc table is simply a sorted array of tdesc elements.
217 A tdesc element is the last 6 words of the tdesc chunk.
218 We require that all tdesc chunks have info protocol 1.
219*/
220
221typedef struct tdesc_elem {
222 dc_word_t start_address;
223 dc_word_t end_address;
224 tdesc_chunk_info1_t info;
225} tdesc_elem_t;
226
227typedef tdesc_elem_t *tdesc_table_t;
228
229void dc_correct_cr_data();
230
231int dc_compare_tdesc_elems (elem1, elem2)
232 char *elem1, *elem2;
233{
234 dc_word_t s1, s2, e1, e2;
235 s1 = ((tdesc_elem_t *) elem1)->start_address;
236 s2 = ((tdesc_elem_t *) elem2)->start_address;
237 if (s1 < s2) return -1;
ea3c0839 238 if (s1 > s2) return 1;
dd3b648e
RP
239 e1 = ((tdesc_elem_t *) elem1)->end_address;
240 e2 = ((tdesc_elem_t *) elem2)->end_address;
241 if (e1 < e2) return -1;
ea3c0839 242 if (e1 > e2) return 1;
dd3b648e
RP
243 return 0;
244}
245
246
247typedef struct handle_info {
248 dc_word_t debug_info_ptr;
249 void (*error_fcn)();
250 dc_word_t error_env;
251 void (*read_fcn)();
252 dc_word_t read_env;
253 void (*write_fcn)(); /* NULL => absent */
254 dc_word_t write_env;
255 void (*exec_fcn)(); /* NULL => absent */
256 dc_word_t exec_env;
257 void (*map_fcn)(); /* NULL => absent */
258 dc_word_t map_env;
259 tdesc_table_t tdesc_table;
260 int tdesc_table_size;
261} handle_info_t;
262
263typedef handle_info_t *dc_handle_t;
264
265
266/*
267 Errors detected in this module are funnelled through dc_error or dc_warn,
268 as appropriate. Both routines call dc_exception, which invokes the error
269 handler supplied by the user.
270
271 Currently, dc_exception substitutes parameters into the message given
272 it and passes the resulting string to the user error handler.
273 In the future, dc_exception should simply pass an error code and
274 the parameters on to the user error handler.
275*/
276
277#include <varargs.h>
278extern int vsprintf();
279
280/* Exit status for exception-processing machinery failure */
281#define DC_EXCEPTION_FAILURE 250
282
283void dc_exception(continuable, args)
284 dc_boolean_t continuable;
285 va_list args;
286{
287 dc_handle_t handle;
288 char *format;
289 char buffer[1024];
290
291 handle = va_arg(args, dc_handle_t);
292 format = va_arg(args, char *);
293 (void) vsprintf(buffer, format, args);
294 (*(handle->error_fcn)) (handle->error_env, continuable, buffer);
295 if (!continuable)
296 exit(DC_EXCEPTION_FAILURE); /* User error handler should never return in this case. */
297}
298
299
300void dc_error(va_alist) /* (handle, format, args... ) */
301 va_dcl
302{
303 va_list args;
304
305 va_start(args);
306 dc_exception(DC_FALSE, args);
307 va_end(args);
308}
309
310
311void dc_warn(va_alist) /* (handle, format, args... ) */
312 va_dcl
313{
314 va_list args;
315
316 va_start(args);
317 dc_exception(DC_TRUE, args);
318 va_end(args);
319}
320
321
322
323#define MALLOC_FAILURE_MESSAGE "Heap space exhausted (malloc failed)."
324#define CALLOC_FAILURE_MESSAGE "Heap space exhausted (Calloc failed)."
325
326
327/* Commonize memory allocation call so failure diagnosis is easier */
328
329char* dc_malloc( handle, size )
330 dc_handle_t handle;
331 int size;
332{
333 char* space = malloc( size );
334 if (space == (char *)NULL)
335 dc_error( handle, MALLOC_FAILURE_MESSAGE );
336
337 return space;
338}
339
340
341/* Commonize memory allocation call so failure diagnosis is easier */
342
343char* dc_calloc( handle,nelem, size )
344 dc_handle_t handle;
345 int nelem;
346 int size;
347{
348 char* space = calloc( nelem, size );
349 if (space == (char *)NULL)
350 dc_error( handle, CALLOC_FAILURE_MESSAGE );
351
352 return space;
353}
354
355
356dc_word_t dc_read_word (handle, address)
357 dc_handle_t handle;
358 dc_word_t address;
359{
360 dc_word_t word;
361 (*(handle->read_fcn)) (handle->read_env, address,
362 sizeof(dc_word_t), (char *)(&(word)));
363 return word;
364}
365
366
367void dc_write_word (handle, address, value)
368 dc_handle_t handle;
369 dc_word_t address;
370 dc_word_t value;
371{
372 dc_word_t word;
373 word = value;
374 if (handle->write_fcn) {
375 (*(handle->write_fcn)) (handle->write_env, address,
376 sizeof(dc_word_t), (char *)(&(word)));
377 } else {
378 dc_error (handle, "Writing is disabled.");
379 }
380}
381
382
383void dc_write_masked_word (handle, address, mask, value)
384 dc_handle_t handle;
385 dc_word_t address;
386 dc_word_t mask;
387 dc_word_t value;
388{
389 dc_write_word (handle, address,
390 (value & mask) | (dc_read_word(handle, address) & ~mask));
391}
392
393
394dc_handle_t dc_initiate (debug_info_ptr,
395 error_fcn, error_env,
396 read_fcn, read_env,
397 write_fcn, write_env,
398 exec_fcn, exec_env,
399 map_fcn, map_env)
400 dc_word_t debug_info_ptr;
401 void (*error_fcn)();
402 dc_word_t error_env;
403 void (*read_fcn)();
404 dc_word_t read_env;
405 void (*write_fcn)(); /* NULL => absent */
406 dc_word_t write_env;
407 void (*exec_fcn)(); /* NULL => absent */
408 dc_word_t exec_env;
409 void (*map_fcn)(); /* NULL => absent */
410 dc_word_t map_env;
411 /* write_fcn may be given as NULL if no writing is required. */
412 /* exec_fcn may be given as NULL if no execution is required.
413 Currently, no execution is required. It would be if the
414 implementation needed to invoke procedures in the debugged process. */
415{
416 dc_handle_t handle;
417 unsigned int debug_info_protocol;
418 dc_debug_info_t debug_info;
419 unsigned int tdesc_map_protocol;
420 tdesc_hdr_t tdesc_hdr;
421 dc_word_t tdesc_info_start;
422 dc_word_t tdesc_info_end;
423 dc_word_t tdesc_info_length;
424
425 /* Set up handle enough for dc_error. */
426 handle = (dc_handle_t) malloc(sizeof(handle_info_t));
427 /* Cant use dc_malloc() as handle is being created ... */
428 /* if (handle == NULL) (*error_fcn)( error_env, MALLOC_FAILURE_MESSAGE ) */
429 handle->error_fcn = error_fcn;
430 handle->error_env = error_env;
431 handle->read_fcn = read_fcn;
432 handle->read_env = read_env;
433 handle->write_fcn = write_fcn;
434 handle->write_env = write_env;
435 handle->exec_fcn = exec_fcn;
436 handle->exec_env = exec_env;
437/****************************************************************/
438/* BUG 9/19/89 Found by hls. Map functions not initialized. */
439/****************************************************************/
440 handle->map_fcn = map_fcn;
441 handle->map_env = map_env;
442 handle->debug_info_ptr = debug_info_ptr;
443 handle->tdesc_table = (tdesc_table_t)NULL;
444
445 /* Find tdesc info. */
446 if (debug_info_ptr) {
447 (*read_fcn) (read_env, debug_info_ptr, sizeof(unsigned int),
448 (char *)(&debug_info_protocol));
449 if (debug_info_protocol != 1)
450 dc_error (handle, "Unrecognized debug info protocol: %d",
451 debug_info_protocol);
452 (*read_fcn) (read_env, debug_info_ptr, sizeof(dc_debug_info_t),
453 (char *)(&debug_info));
454 (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(unsigned int),
455 (char *)(&tdesc_map_protocol));
456 if (tdesc_map_protocol != 1)
457 dc_error (handle, "Unrecognized tdesc map protocol: %d",
458 tdesc_map_protocol);
459 (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(tdesc_hdr_t),
460 (char *)(&tdesc_hdr));
461 tdesc_info_start = debug_info.tdesc_ptr + sizeof(tdesc_hdr_t);
462 tdesc_info_end = tdesc_hdr.end;
463 tdesc_info_length = tdesc_info_end - tdesc_info_start;
464
465 /* Create tdesc table from tdesc info. */
466 {
467 /* Over-allocate in order to avoid second pass over tdesc info. */
468 tdesc_table_t tt = (tdesc_table_t) dc_malloc(handle, tdesc_info_length);
469 dc_word_t p = tdesc_info_start;
470 dc_word_t q = tdesc_info_end - sizeof(tdesc_chunk1_t);
471 int n = 0;
472 tdesc_chunk1_t chunk;
473 dc_word_t start_address, end_address;
474 int i;
475
476 for (; p <= q; ) {
477 (*read_fcn) (read_env, p, sizeof(tdesc_chunk1_t), (char *)(&chunk));
478 if (chunk.hdr.zeroes != 0) {
479 /* Skip padding. */
480 p += sizeof(dc_word_t);
481 continue;
482 }
483 if (chunk.hdr.info_protocol != 1) {
484 dc_warn (handle, "Unrecognized tdesc info protocol: %d",
485 chunk.hdr.info_protocol);
486 goto next_chunk;
487 }
488 if (chunk.hdr.info_length != 16) {
489 dc_warn (handle, "Incorrect tdesc info length: %d",
490 chunk.hdr.info_length);
491 goto next_chunk;
492 }
493 if (chunk.hdr.info_alignment > 2) {
494 dc_warn (handle, "Incorrect tdesc info alignment: %d",
495 chunk.hdr.info_alignment);
496 goto next_chunk;
497 }
498 start_address = chunk.hdr.start_address;
499 end_address = chunk.hdr.end_address;
500 if ((start_address&3)!=0) {
501 dc_warn (handle,
502 "Tdesc start address is not word-aligned: %#.8X",
503 start_address);
504 goto next_chunk;
505 }
506 if ((end_address&3)!=0) {
507 dc_warn (handle,
508 "Tdesc end address is not word-aligned: %#.8X",
509 end_address);
510 goto next_chunk;
511 }
512 if (start_address > end_address) {
513 /* Note that the range may be null. */
514 dc_warn (handle,
515 "Tdesc start address (%#.8X) follows end address (%#.8X).",
516 start_address, end_address);
517 goto next_chunk;
518 }
519 if (chunk.info.variant != 1) {
520 dc_warn (handle, "Invalid tdesc chunk variant: %d",
521 chunk.info.variant);
522 goto next_chunk;
523 }
524 if (chunk.info.pad1 != 0) {
525 dc_warn (handle, "Tdesc chunk padding is not zero.");
526 goto next_chunk;
527 }
528 if (chunk.info.return_address_info_discriminant != 0) {
529 if ((chunk.info.return_address_info & 3) != 0) {
530 dc_warn (handle,
531 "Tdesc return address offset is not word-aligned: %#.8X",
532 chunk.info.return_address_info);
533 goto next_chunk;
534 }
535 } else {
536 if ((chunk.info.return_address_info & ~31) != 0) {
537 dc_warn (handle,
538 "Invalid tdesc return address register: %d",
539 chunk.info.return_address_info);
540 goto next_chunk;
541 }
542 }
543 if ((chunk.info.register_save_offset & 3) != 0) {
544 dc_warn (handle,
545 "Tdesc register save offset is not word-aligned: %#.8X",
546 chunk.info.register_save_offset);
547 goto next_chunk;
548 }
549
550 tt[n].start_address = start_address;
551 tt[n].end_address = end_address;
552 tt[n].info = chunk.info;
553 n++;
554
555 next_chunk:
556 p += sizeof(tdesc_chunk1_t);
557 }
558 /* Leftover (less than a tdesc_chunk1_t in size) is padding or
559 in error. Ignore it in either case. */
560
561 if (n != 0) {
562
563 /* Sort table by start address. */
564 qsort ((char *)tt, n, sizeof(tdesc_elem_t), dc_compare_tdesc_elems);
565
566 /* Check for overlap among tdesc chunks. */
567 for (i=0; i<(n-1); i++) {
568 if (tt[i].end_address > tt[i+1].start_address)
569 dc_error (handle, "Text chunks overlap.");
570 }
571 }
572
573 /* Finish setting up handle. */
574 handle->tdesc_table = tt;
575 handle->tdesc_table_size = n;
576 }
577 } else {
578 handle->tdesc_table_size = 0;
579 }
580
581 return (dc_handle_t) handle;
582}
583
584
585void dc_terminate (handle)
586 dc_handle_t handle;
587{
588 if (((dc_handle_t)handle)->tdesc_table) {
589 free((char *)(((dc_handle_t)handle)->tdesc_table));
590 }
591 free((char *)handle);
592}
593
594
595
596/*
597
598 Dcontext Model
599
600 For each interesting register (word-sized piece of machine state),
601 a word of value information is kept. This word may
602 be either the value of the register, or the address in
603 subject memory where the value can be found (and changed). In
604 addition, the register may be invalid (in which case the value
605 information is undefined). These three cases are encoded for
606 a given register in the same-numbered bit of two words of flags:
607
608 flags[0] bit flags[1] bit meaning
609 ------------ ------------ -------
610 0 0 register is invalid; info is undefined
611 0 1 register is readable; info is value
612 1 0 register is writable; info is address
613 1 1 (reserved)
614
615 The general registers (r0-r31) are handled by reg_info and
616 reg_flags. The bit number for a register is that register's number.
617 The other registers are grouped together for convenience and are
618 handled by aux_info and aux_flags. The bit numbers for these
619 registers are:
620
621 bit number register
622 ---------- --------
623 0 location
624 1 SXIP
625 2 SNIP
626 3 SFIP
627 4 FPSR
628 5 FPCR
629
630 The SXIP, SNIP, and SFIP are the exception-time values of the
631 XIP, NIP, and FIP registers. They are valid only in the topmost frame.
632 (That is, in any context obtained from dc_previous_context, they
633 are invalid.)
634
635 "location" is a pseudo-register of this model and represents the
636 location of the context. It is always valid. It also has an
637 exactness associated with it. The location and its exactness of a
638 context obtained from dc_previous_context are taken from the
639 return address and its exactness of the context given as an argument
640 to dc_previous_context.
641
642 The following model is recommended for dealing with the partial
643 redundancy between location and the SXIP, SNIP, and SFIP values
644 in the topmost frame. The location should be set to either the
645 SNIP or SXIP value, and its exactness should be set to DC_NO. A
646 change to the register whose value the location is set to should
647 be accompanied by an identical change to the location.
648
649 The PSR is handled separately, because it is a diverse collection
650 of flags. The PSR, as a whole, is always valid. A separate
651 psr_ind flag tells whether the psr_info data is a value or
652 an address. Each bit of the PSR has its own pair of flag bits to
653 mark validity and writability.
654
655*/
656
657
658/* The following value means "other", because state is stored in 2 bits. */
659#define DC_RESERVED 3
660
661
662#define RSTATE(flags, bit) \
663 ((bit_value((flags)[0], bit) << 1) + bit_value((flags)[1], bit))
664
665#define REG_STATE(dcontext, reg) RSTATE(dcontext->reg_flags, reg)
666#define AUX_STATE(dcontext, reg) RSTATE(dcontext->aux_flags, reg)
667#define PSR_STATE(dcontext, reg) RSTATE(dcontext->psr_flags, reg)
668
669
670#define SET_INVALID(flags, bit) \
671 { bit_clear ((flags)[0], bit); bit_clear ((flags)[1], bit); }
672
673#define SET_READABLE(flags, bit) \
674 { bit_clear ((flags)[0], bit); bit_set ((flags)[1], bit); }
675
676#define SET_WRITABLE(flags, bit) \
677 { bit_set ((flags)[0], bit); bit_clear ((flags)[1], bit); }
678
679#define ASSIGN_RSTATE(to_flags, to_bit, from_flags, from_bit) \
680 { bit_assign ((to_flags)[0], to_bit, bit_value((from_flags)[0], from_bit));\
681 bit_assign ((to_flags)[1], to_bit, bit_value((from_flags)[1], from_bit));}
682
683
684#define CHECK_REG_READ(dcontext, reg) \
685 if (REG_STATE(dcontext, reg) == DC_INVALID) \
686 dc_error (dcontext->handle, \
687 "General register %d is not readable.", reg)
688
689#define CHECK_REG_WRITE(dcontext, reg) \
690 if (REG_STATE(dcontext, reg) != DC_WRITABLE) \
691 dc_error (dcontext->handle, \
692 "General register %d is not writable.", reg)
693
694#define CHECK_AUX_READ(dcontext, reg) \
695 if (AUX_STATE(dcontext, reg) == DC_INVALID) \
696 dc_error (dcontext->handle, \
697 "Auxiliary register %d is not readable.", reg)
698
699#define CHECK_AUX_WRITE(dcontext, reg) \
700 if (AUX_STATE(dcontext, reg) != DC_WRITABLE) \
701 dc_error (dcontext->handle, \
702 "Auxiliary register %d is not writable.", reg)
703
704
705
706#define DC_REG_RA 1
707#define DC_REG_FP 30
708#define DC_REG_SP 31
709#define DC_NUM_REG 32
710
711#define DC_AUX_LOC 0
712 /* DC_AUX_LOC must be first, with value 0 */
713#define DC_AUX_SXIP 1
714#define DC_AUX_SNIP 2
715#define DC_AUX_SFIP 3
716#define DC_AUX_FPSR 4
717#define DC_AUX_FPCR 5
718#define DC_NUM_AUX 6
719
720
721
722#define CHECK_REG(dcontext, reg) \
723 if ((reg < 0) || (reg >= DC_NUM_REG)) \
724 dc_error (dcontext->handle, \
725 "Bad general register number: %d", reg)
726
727#define CHECK_AUX(dcontext, reg) \
728 if ((reg < 1) || (reg >= DC_NUM_AUX)) \
729 dc_error (dcontext->handle, \
730 "Bad auxiliary register number: %d", reg)
731 /* CHECK_AUX is not used for location pseudo-register. */
732
733#define CHECK_BIT(dcontext, bit) \
734 if ((bit < 0) || (bit >= 32)) \
735 dc_error (dcontext->handle, \
736 "Bad bit number: %d", bit)
737
738
739
740typedef struct cr_value {
741 int reg;
742 unsigned int off;
743 } dc_cr_value_t;
744
745#define DC_UNDEF 32
746
747/*
748 A "dc_cr_value" represents an execution-time value symbolically, in
749 terms of the initial value of a register (the value on entry to
750 the procedure being analyzed) and a known offset. A value with
751 a 'reg' field value of 0 through 31 represents the value obtained
752 by summing (using 32-bit modulus arithmetic) the initial value of
753 register 'reg' and the value 'off'. Note that the value (0,k)
754 represents the constant value k, that (31,0) represents the CFA, and
755 that (1,0) represents the return address. A value with a 'reg' field
756 of DC_UNDEF represents an indeterminable value; in this case the
757 'off' field is undefined. Other values of 'reg' are erroneous.
758*/
759
760typedef struct cr_data {
761 dc_cr_value_t reg_val[DC_NUM_REG];
762 dc_word_t saved;
763 dc_word_t how;
764 unsigned int where[DC_NUM_REG];
765} dc_cr_data_t;
766
767/*
768 'cr_data' collects all the information needed to represent the
769 symbolic machine state during code reading.
770
771 The 'reg_val' array gives the current dc_cr_value for each register.
772
773 The 'saved', 'how', and 'where' fields combine to describe what
774 registers have been saved, and where. The 'saved' and 'how' fields
775 are implicitly bit arrays over 0..31, where the numbering is from
776 0 on the right. (Hence, 1<<r gives the mask for register r.)
777 If saved[r] is 0, the register is not saved, and how[r] and where[r]
778 are undefined. If saved[r] is 1, then how[r] tells whether register r
779 was saved in another register (how[r]==0) or in the frame (how[r]==1).
780 In the former case, where[r] gives the register number; in the latter
781 case, where[r] gives the frame position.
782*/
783
784
785typedef int dc_register_state_t; /* range 0 to 2 */
786
787#define DC_INVALID 0
788#define DC_READABLE 1
789#define DC_WRITABLE 2
790
791
792
793
794typedef struct dcontext_info {
795 dc_handle_t handle; /* environment of context */
796 dc_word_t reg_info[DC_NUM_REG];
797 dc_word_t reg_flags[2];
798 dc_word_t aux_info[DC_NUM_AUX];
799 dc_word_t aux_flags[2];
800 dc_exactness_t loc_exact;
801 dc_word_t psr_info; /* value or address */
802 dc_word_t psr_ind; /* DC_TRUE iff address */
803 dc_word_t psr_flags[2]; /* per-PSR-bit flags */
804 unsigned int code_reading; /* no tdesc therefore must read code*/
805 union {
806 tdesc_elem_t *tdesc_elem_ptr; /* locates tdesc chunk */
807 dc_cr_data_t *cr_data_ptr; /* or code reading data */
808 } info_ptr;
809} dcontext_info_t;
810
811typedef dcontext_info_t *dc_dcontext_t;
812
813dc_word_t dc_get_value (handle, info, flags, pos)
814 dc_handle_t handle;
815 dc_word_t info[];
816 dc_word_t flags[2];
817 int pos;
818 /* Assumes either DC_READABLE or DC_WRITABLE. */
819{
820 if (bit_test(flags[0], pos)) {
821 /* DC_WRITABLE case */
822 return dc_read_word(handle, info[pos]);
823 } else {
824 /* DC_READABLE case */
825 return info[pos];
826 }
827}
828
829void dc_set_value (handle, info, flags, pos, value)
830 dc_handle_t handle;
831 dc_word_t info[];
832 dc_word_t flags[2];
833 int pos;
834 dc_word_t value;
835 /* Assumes DC_WRITABLE. */
836{
837 dc_write_word(handle, info[pos], value);
838}
839
840
841#define GET_REG_VALUE(dcontext, reg) \
842 dc_get_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg)
843
844#define SET_REG_VALUE(dcontext, reg, value) \
845 dc_set_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg, \
846 value)
847
848#define GET_AUX_VALUE(dcontext, reg) \
849 dc_get_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg)
850
851#define SET_AUX_VALUE(dcontext, reg, value) \
852 dc_set_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg, \
853 value)
854
855
856
857void dc_check_dcontext (dc)
858 dc_dcontext_t dc;
859 /* Check consistency of information supplied to make a dcontext. */
860{
861 int i;
862
863 if ((REG_STATE(dc, 0) != DC_READABLE) || (dc->reg_info[0] != 0))
864 dc_error (dc->handle, "Register 0 is misspecified");
865 for (i = 1; i < DC_NUM_REG; i++)
866 if (REG_STATE(dc, i) == DC_RESERVED)
867 dc_error (dc->handle,
868 "State for general register %d is incorrect", i);
869 for (i = 0; i < DC_NUM_AUX; i++)
870 if (AUX_STATE(dc, i) == DC_RESERVED)
871 dc_error (dc->handle,
872 "State for auxiliary register %d is incorrect", i);
873 if (AUX_STATE(dc, DC_AUX_LOC) == DC_INVALID)
874 dc_error (dc->handle, "Location is specified as invalid");
875 if (GET_AUX_VALUE(dc, DC_AUX_LOC) == 0)
876 dc_error (dc->handle, "Location is zero.");
877 if (dc->loc_exact >= 3)
878 dc_error (dc->handle, "Location exactness is incorrectly specified: %d",
879 dc->loc_exact);
880 if (dc->psr_ind >= 2)
881 dc_error (dc->handle,
882 "PSR indirection flag is incorrectly specified: %d",
883 dc->psr_ind);
884 for (i = 0; i < 32; i++)
885 if (PSR_STATE(dc, i) == DC_RESERVED)
886 dc_error (dc->handle, "State for PSR bit %d is incorrect", i);
887}
888
889
890
891tdesc_elem_t * dc_tdesc_lookup (loc, tt, tt_size, map_info_in_ptr)
892 dc_word_t loc;
893 tdesc_table_t tt;
894 int tt_size;
895 dc_map_info_in_t *map_info_in_ptr;
896 /* Return address of tdesc_elem_t for given location, or NULL if
897 there is no tdesc chunk for the location.
898 */
899{
900 int l = 0;
901 int h = tt_size;
902 int m;
903
904 if (tt_size == 0) {
905 map_info_in_ptr->flags = 0;
906 return (tdesc_elem_t *)NULL;
907 }
908 for (;;) {
909 m = (l + h) / 2;
910 if (m == l) break;
911 if (loc >= tt[m].start_address)
912 l = m;
913 else
914 h = m;
915 }
916 if (loc >= tt[m].end_address) {
917 map_info_in_ptr->preceding_tdesc_end = tt[m].end_address;
918 if (m+1 < tt_size) {
919 map_info_in_ptr->following_tdesc_start = tt[m+1].start_address;
920 map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END |
921 DC_MII_FOLLOWING_TDESC_START;
922 } else {
923 map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END;
924 }
925 return (tdesc_elem_t *)NULL;
926 } else if (loc < tt[m].start_address) {
927 map_info_in_ptr->following_tdesc_start = tt[m].start_address;
928 map_info_in_ptr->flags = DC_MII_FOLLOWING_TDESC_START;
929 return (tdesc_elem_t *)NULL;
930 } else {
931 return (&tt[m]);
932 }
933}
934
935
936
937dc_dcontext_t dc_make_dcontext (handle,
938 reg_info, reg_flags,
939 aux_info, aux_flags, loc_exact,
940 psr_info, psr_ind, psr_flags)
941 dc_handle_t handle;
942 dc_word_t reg_info[DC_NUM_REG];
943 dc_word_t reg_flags[2];
944 dc_word_t aux_info[DC_NUM_AUX];
945 dc_word_t aux_flags[2];
946 dc_exactness_t loc_exact;
947 dc_word_t psr_info;
948 dc_boolean_t psr_ind;
949 dc_word_t psr_flags[2];
950{
951 dc_dcontext_t dc = (dc_dcontext_t) dc_malloc (handle, sizeof(dcontext_info_t));
952 int i;
953 dc_map_info_in_t map_info_in;
954
955 /* Fill in supplied content. */
956 dc->handle = ((dc_handle_t)handle);
957 for (i = 0; i < DC_NUM_REG; i++) dc->reg_info[i] = reg_info[i];
958 for (i = 0; i < 2; i++) dc->reg_flags[i] = reg_flags[i];
959 for (i = 0; i < DC_NUM_AUX; i++) dc->aux_info[i] = aux_info[i];
960 for (i = 0; i < 2; i++) dc->aux_flags[i] = aux_flags[i];
961 dc->loc_exact = loc_exact;
962 dc->psr_info = psr_info;
963 dc->psr_ind = psr_ind;
964 for (i = 0; i < 2; i++) dc->psr_flags[i] = psr_flags[i];
965
966 dc_check_dcontext(dc);
967
968 /* Find tdesc information for the text chunk. */
969 {
970/***************************************************************/
971/* BUG 8/16/89 Found by hls. Not zeroing EV bits of location. */
972/* SHOULD USE dc_location()! */
973/* dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC); */
974/***************************************************************/
975 dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC) & ~3;
976 tdesc_elem_t *tep =
977 dc_tdesc_lookup(loc, ((dc_handle_t)handle)->tdesc_table,
978 ((dc_handle_t)handle)->tdesc_table_size,&map_info_in);
979 if (tep) {
980 dc->code_reading = 0;
981 dc->info_ptr.tdesc_elem_ptr = tep;
982 } else {
983 dc->code_reading = 1;
984 if (!dc->handle->map_fcn) {
985 dc_error (dc->handle, "No tdesc information for %#.8X and no map function supplied.",loc);
986 }
987/****************************************************************/
988/* BUG 9/18/89 Found by hls. Not using dc_malloc() */
989/* dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)malloc(sizeof(dc_cr_data_t )); */
990/****************************************************************/
991 dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)dc_calloc(dc->handle,1,sizeof(dc_cr_data_t ));
992 dc_read_code(loc,dc,map_info_in,dc->info_ptr.cr_data_ptr);
993 }
994 }
995
996 return (dc_dcontext_t) dc;
997}
998
999
1000
1001void dc_free_dcontext (dcontext)
1002 dc_dcontext_t dcontext;
1003{
1004/****************************************************************/
1005/* BUG 9/19/89 Found by hls. Freeing non-pointer value. */
1006/* free((char *)dcontext->code_reading); */
1007/****************************************************************/
1008 if (dcontext->code_reading)
1009 free((char *)dcontext->info_ptr.cr_data_ptr);
1010 free((char *)dcontext);
1011}
1012
1013
1014
1015dc_register_state_t dc_location_state (dcontext)
1016 dc_dcontext_t dcontext;
1017{
1018 return AUX_STATE(((dc_dcontext_t)dcontext), DC_AUX_LOC);
1019}
1020
1021
1022dc_exactness_t dc_location_exactness (dcontext)
1023 dc_dcontext_t dcontext;
1024{
1025 return ((dc_dcontext_t)dcontext)->loc_exact;
1026}
1027
1028
1029dc_word_t dc_location (dcontext)
1030 dc_dcontext_t dcontext;
1031 /* Return high 30 bits only. */
1032{
1033 /* Don't need: CHECK_AUX_READ (((dc_dcontext_t)dcontext), DC_AUX_LOC); */
1034 return GET_AUX_VALUE (((dc_dcontext_t)dcontext), DC_AUX_LOC) & ~3;
1035}
1036
1037
1038dc_boolean_t dc_location_in_text_chunk( dcontext, value )
1039 dc_dcontext_t dcontext;
1040 dc_word_t value;
1041{
1042 /* Check that new location is still within same text chunk. */
1043 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1044/********************************************************************/
1045/* Bug in predicate -- LS adjusted according to OCS documentation.. */
1046/* if ((value < tep->start_address) || (value >= tep->end_address))*/
1047/********************************************************************/
1048 if ((value >= tep->start_address) && (value < tep->end_address))
1049 return DC_TRUE;
1050 else
1051 return DC_FALSE;
1052
1053}
1054
1055
1056void dc_set_location (dcontext, value)
1057 dc_dcontext_t dcontext;
1058 dc_word_t value;
1059 /* Set high 30 bits only. */
1060{
1061 if (dc_location_in_text_chunk( dcontext, value ) != DC_TRUE)
1062 dc_warn (((dc_dcontext_t)dcontext)->handle,
1063 "New location is not in same text chunk.");
1064
1065 CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), DC_AUX_LOC);
1066 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1067 ((dc_dcontext_t)dcontext)->aux_info[DC_AUX_LOC], ~3, value);
1068}
1069
1070
1071
1072dc_register_state_t dc_general_register_state (dcontext, reg)
1073 dc_dcontext_t dcontext;
1074 int reg;
1075{
1076 CHECK_REG (((dc_dcontext_t)dcontext), reg);
1077 return REG_STATE(((dc_dcontext_t)dcontext), reg);
1078}
1079
1080
1081dc_word_t dc_general_register (dcontext, reg)
1082 dc_dcontext_t dcontext;
1083 int reg;
1084{
1085 CHECK_REG (((dc_dcontext_t)dcontext), reg);
1086 CHECK_REG_READ (((dc_dcontext_t)dcontext), reg);
1087 return GET_REG_VALUE(((dc_dcontext_t)dcontext), reg);
1088}
1089
1090
1091void dc_set_general_register (dcontext, reg, value)
1092 dc_dcontext_t dcontext;
1093 int reg;
1094 dc_word_t value;
1095{
1096 CHECK_REG (((dc_dcontext_t)dcontext), reg);
1097 CHECK_REG_WRITE (((dc_dcontext_t)dcontext), reg);
1098 SET_REG_VALUE (((dc_dcontext_t)dcontext), reg, value);
1099}
1100
1101
1102
1103dc_register_state_t dc_auxiliary_register_state (dcontext, reg)
1104 dc_dcontext_t dcontext;
1105 int reg;
1106{
1107 CHECK_AUX (((dc_dcontext_t)dcontext), reg);
1108 return AUX_STATE(((dc_dcontext_t)dcontext), reg);
1109}
1110
1111
1112dc_word_t dc_auxiliary_register (dcontext, reg)
1113 dc_dcontext_t dcontext;
1114 int reg;
1115{
1116 CHECK_AUX (((dc_dcontext_t)dcontext), reg);
1117 CHECK_AUX_READ (((dc_dcontext_t)dcontext), reg);
1118 return GET_AUX_VALUE(((dc_dcontext_t)dcontext), reg);
1119}
1120
1121
1122void dc_set_auxiliary_register (dcontext, reg, value)
1123 dc_dcontext_t dcontext;
1124 int reg;
1125 dc_word_t value;
1126{
1127 CHECK_AUX (((dc_dcontext_t)dcontext), reg);
1128 CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), reg);
1129 SET_AUX_VALUE (((dc_dcontext_t)dcontext), reg, value);
1130}
1131
1132
1133
1134dc_register_state_t dc_psr_register_bit_state (dcontext, bit)
1135 dc_dcontext_t dcontext;
1136 int bit;
1137{
1138 CHECK_BIT (((dc_dcontext_t)dcontext), bit);
1139 return PSR_STATE(((dc_dcontext_t)dcontext), bit);
1140}
1141
1142
1143dc_word_t dc_psr_register (dcontext)
1144 dc_dcontext_t dcontext;
1145{
1146 if (((dc_dcontext_t)dcontext)->psr_ind) {
1147 return dc_read_word(((dc_dcontext_t)dcontext)->handle,
1148 ((dc_dcontext_t)dcontext)->psr_info);
1149 } else {
1150 return ((dc_dcontext_t)dcontext)->psr_info;
1151 }
1152}
1153
1154
1155void dc_set_psr_register (dcontext, mask, value)
1156 dc_dcontext_t dcontext;
1157 dc_word_t mask;
1158 dc_word_t value;
1159 /* Set bits of PSR corresponding to 1 bits in mask. */
1160{
1161 if (((dc_dcontext_t)dcontext)->psr_ind) {
1162 if (((((dc_dcontext_t)dcontext)->psr_flags[0] & mask) != mask) ||
1163 ((((dc_dcontext_t)dcontext)->psr_flags[1] & mask) != 0))
1164 dc_error (((dc_dcontext_t)dcontext)->handle,
1165 "Some PSR bits specified are not writable.");
1166 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1167 ((dc_dcontext_t)dcontext)->psr_info, mask, value);
1168 } else {
1169 dc_error (((dc_dcontext_t)dcontext)->handle, "PSR is not writable.");
1170 }
1171}
1172
1173
1174
1175dc_word_t dc_frame_address (dcontext)
1176 dc_dcontext_t dcontext;
1177{
1178 if (!dcontext->code_reading) {
1179 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1180 return dc_general_register(dcontext,
1181 tep->info.frame_address_register) + tep->info.frame_address_offset;
1182 } else {
1183 if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].reg == DC_REG_SP) {
1184 return (dc_general_register(dcontext,DC_REG_FP)
1185 - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].off);
1186 }
1187 if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].reg == DC_REG_SP) {
1188 return (dc_general_register(dcontext,DC_REG_SP)
1189 - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].off);
1190 }
1191 dc_error (((dc_dcontext_t)dcontext)->handle, "Cannot locate frame pointer.");
1192 }
1193}
1194
1195
1196
1197dc_kind_t dc_context_kind (dcontext)
1198 dc_dcontext_t dcontext;
1199{
1200 return DC_CALL_KIND;
1201}
1202
1203
1204
1205
1206/* operations valid for call contexts only */
1207
1208
1209dc_register_state_t dc_return_address_state (dcontext)
1210 dc_dcontext_t dcontext;
1211{
1212 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1213 int reg;
1214
1215 if (!dcontext->code_reading) {
1216 if (tep->info.return_address_info_discriminant) {
1217 return DC_WRITABLE;
1218 } else {
1219 return REG_STATE(((dc_dcontext_t)dcontext), tep->info.return_address_info);
1220 }
1221 } else {
1222 reg= DC_REG_RA;
1223 if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
1224 if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
1225 return DC_WRITABLE;
1226 } else {
1227 reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
1228 }
1229 }
1230 return REG_STATE(((dc_dcontext_t)dcontext),reg);
1231
1232
1233 }
1234}
1235
1236
1237dc_exactness_t dc_return_address_exactness (dcontext)
1238 dc_dcontext_t dcontext;
1239{
1240 return DC_MAYBE;
1241}
1242
1243
1244dc_word_t dc_return_address (dcontext)
1245 dc_dcontext_t dcontext;
1246 /* Return high 30 bits only. */
1247{
1248 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1249 dc_word_t rai = tep->info.return_address_info;
1250 dc_word_t val;
1251 int reg;
1252
1253 if (!dcontext->code_reading) {
1254 if (tep->info.return_address_info_discriminant) {
1255 val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
1256 dc_frame_address(dcontext) + rai);
1257 } else {
1258 val = dc_general_register (dcontext, rai);
1259 }
1260 } else {
1261 reg=DC_REG_RA;
1262 if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,reg)) {
1263 if (bit_test(dcontext->info_ptr.cr_data_ptr->how,reg)) {
1264 val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
1265 dc_frame_address(dcontext) +
1266 (dcontext->info_ptr.cr_data_ptr->where[reg]));
1267 } else {
1268 reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
1269 val = dc_general_register (dcontext, reg);
1270 }
1271 } else {
1272 val = dc_general_register (dcontext, reg);
1273 }
1274 }
1275 return val & ~3;
1276}
1277
1278
1279void dc_set_return_address (dcontext, value)
1280 dc_dcontext_t dcontext;
1281 dc_word_t value;
1282 /* Set high 30 bits only. */
1283{
1284 if (!dcontext->code_reading) {
1285 tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
1286 dc_word_t rai = tep->info.return_address_info;
1287
1288 if (tep->info.return_address_info_discriminant) {
1289 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1290 dc_frame_address(dcontext) + rai, ~3, value);
1291 } else {
1292 dc_set_general_register (dcontext, rai,
1293 (value & ~3) | (dc_general_register(dcontext, rai) & 3));
1294 }
1295 } else {
1296 if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
1297 if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
1298 dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
1299 dc_frame_address(dcontext)
1300 + dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA], ~3, value);
1301 } else {
1302 dc_set_general_register( dcontext,
1303 dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
1304 }
1305 } else {
1306 dc_set_general_register( dcontext,
1307 dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
1308 }
1309 }
1310}
1311
1312
1313
1314/* operations valid for save contexts only */
1315
1316/* (none) */
1317
1318
1319
1320/* operations valid for exception contexts only */
1321
1322
1323void dc_get_exception_info (dcontext, handler, datum)
1324 dc_dcontext_t dcontext;
1325 dc_word_t *handler;
1326 dc_word_t *datum;
1327{
1328 dc_error (((dc_dcontext_t)dcontext)->handle,
1329 "dc_get_exception_info is not yet implemented.");
1330}
1331
1332
1333
1334/* operations valid for protection contexts only */
1335
1336
1337void dc_get_protection_info (dcontext, handler, datum)
1338 dc_dcontext_t dcontext;
1339 dc_word_t *handler;
1340 dc_word_t *datum;
1341{
1342 dc_error (((dc_dcontext_t)dcontext)->handle,
1343 "dc_get_protection_info is not yet implemented.");
1344}
1345
1346
1347
1348/* operations valid for special contexts only */
1349
1350
1351void dc_get_special_info (dcontext, kind, datum)
1352 dc_dcontext_t dcontext;
1353 dc_word_t *kind;
1354 dc_word_t *datum;
1355{
1356 dc_error (((dc_dcontext_t)dcontext)->handle,
1357 "dc_get_special_info is not yet implemented.");
1358}
1359
1360
1361
1362/* operations valid for all contexts (again) */
1363
1364
1365dc_dcontext_t dc_previous_dcontext (dcontext)
1366 dc_dcontext_t dcontext;
1367 /* Return NULL if there is no previous context. */
1368{
1369 dc_dcontext_t old = (dc_dcontext_t) dcontext;
1370 dcontext_info_t new; /* to serve as temporary storage only */
1371 tdesc_elem_t *tep;
1372 dc_cr_data_t *cdp;
1373 dc_word_t cfa;
1374 int rsm;
1375 dc_word_t offset;
1376 dc_word_t rai;
1377 int r;
1378
1379 if (dc_return_address_state((dc_dcontext_t)old) == DC_INVALID)
1380 dc_error (old->handle, "Return address is invalid.");
1381
1382 if (dc_return_address((dc_dcontext_t)old) == 0)
1383 return (dc_dcontext_t)NULL; /* end of the chain */
1384
1385 /* Copy over old contents. */
1386 new = *old;
1387
1388 cfa = dc_frame_address(old);
1389 /* Restore stack pointer. */
1390 new.reg_info[DC_REG_SP] = cfa;
1391 SET_READABLE (new.reg_flags, DC_REG_SP);
1392
1393 /* Invalidate temporary registers. */
1394 for (r = 1; r <= 13; r++) SET_INVALID (new.reg_flags, r);
1395
1396 if (!old->code_reading) {
1397 tep = old->info_ptr.tdesc_elem_ptr;
1398 /* Restore preserved registers. */
1399 rsm = tep->info.register_save_mask;
1400 offset = cfa + tep->info.register_save_offset;
1401 for (r = 14; r <= 30; r++) {
1402 if (bit_test(rsm, 30-r)) {
1403 new.reg_info[r] = offset;
1404 SET_WRITABLE (new.reg_flags, r);
1405 offset += sizeof(dc_word_t);
1406 }
1407 }
1408
1409 /* Set location from old return address. */
1410 rai = tep->info.return_address_info;
1411 if (tep->info.return_address_info_discriminant) {
1412 new.aux_info[DC_AUX_LOC] = cfa + rai;
1413 SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
1414 } else {
1415 new.aux_info[DC_AUX_LOC] = old->reg_info[rai];
1416 ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC, old->reg_flags, rai);
1417 }
1418 } else {
1419 cdp = old->info_ptr.cr_data_ptr;
1420
1421 /* Restore preserved registers. */
1422 for (r = 14; r <= 30; r++) {
1423 if (bit_test(cdp->saved,r)) {
1424 if (bit_test(cdp->how,r)){ /* saved in the frame */
1425 new.reg_info[r] = cfa+cdp->where[r];
1426 SET_WRITABLE (new.reg_flags, r);
1427 } else { /* saved in the in a register */
1428 new.reg_info[r] = dc_general_register(old,cdp->where[r]);
1429 ASSIGN_RSTATE (new.aux_flags, r, old->reg_flags, cdp->where[r]);
1430 }
1431 } /* not saved, therefore, already valid , no else*/
1432 }
1433
1434 /* Set location from old return address. */
1435 if (bit_test(cdp->saved,DC_REG_RA)) {
1436 if (bit_test(cdp->how,DC_REG_RA)){ /* saved in the frame */
1437 new.aux_info[DC_AUX_LOC] =
1438 new.reg_info[DC_REG_RA] = cfa+cdp->where[DC_REG_RA];
1439 SET_WRITABLE (new.reg_flags, DC_REG_RA);
1440 SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
1441 } else { /* saved in the in a register */
1442 new.reg_info[DC_REG_RA] =
1443 new.aux_info[DC_AUX_LOC] =
1444 dc_general_register(old,cdp->where[DC_REG_RA]);
1445 ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC,
1446 old->reg_flags, cdp->where[DC_REG_RA]);
1447 }
1448 } else { /* not saved, therefore, already valid , set DC_AUX_LOC only*/
1449 new.aux_info[DC_AUX_LOC] =
1450 dc_general_register(old,DC_REG_RA);
1451 ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC,
1452 old->reg_flags, DC_REG_RA);
1453 }
1454 }
1455
1456 /* Invalidate instruction pointers. */
1457 SET_INVALID (new.aux_flags, DC_AUX_SXIP);
1458 SET_INVALID (new.aux_flags, DC_AUX_SNIP);
1459 SET_INVALID (new.aux_flags, DC_AUX_SFIP);
1460
1461 /* No change to FCR registers. */
1462
1463 /* No change to PSR register. */
1464
1465 return dc_make_dcontext ((dc_handle_t)new.handle,
1466 new.reg_info, new.reg_flags,
1467 new.aux_info, new.aux_flags, new.loc_exact,
1468 new.psr_info, new.psr_ind, new.psr_flags);
1469}
1470
1471
1472
1473/* extensions for nonlocal goto */
1474
1475#if 0
1476
1477typedef
1478 struct label {
1479 ???
1480 } label_t;
1481
1482
1483label_t dc_make_label (dcontext, location)
1484 dc_dcontext_t dcontext;
1485 dc_word_t location;
1486{
1487}
1488
1489#endif
1490
1491/* procedure for reading code */
1492
1493dc_read_code(loc,dc,map_info_in,cdp)
1494dc_word_t loc;
1495dc_dcontext_t dc;
1496dc_cr_data_t *cdp;
1497dc_map_info_in_t map_info_in;
1498{
1499dc_map_info_out_t map_info_out;
1500dc_word_t pc;
1501dc_boolean_t found_branch=DC_FALSE;
1502dc_word_t instr;
1503
1504 (*dc->handle->map_fcn)(dc->handle->map_env,loc,map_info_in,&map_info_out);
1505 if (map_info_out.flags & DC_MIO_ENTRY_POINT
1506 && (!(map_info_in.flags & DC_MII_PRECEDING_TDESC_END)
1507 || map_info_out.entry_point >= map_info_in.preceding_tdesc_end
1508 || map_info_out.flags & DC_MIO_LITERAL_ENTRY_POINT)) {
1509 dc_init_cr_data(cdp,(tdesc_elem_t *)NULL);
1510 pc= map_info_out.entry_point;
1511 } else if (map_info_in.flags & DC_MII_PRECEDING_TDESC_END) {
1512 /**/
1513 /* tdesc_lookup gets the tep for the preceeding tdesc information
1514 /* so we call it with one less than the preceding tdesc end since
1515 /* tdesc information is exclusive of the ending address
1516 /**/
1517 dc_init_cr_data(cdp,
1518 dc_tdesc_lookup(map_info_in.preceding_tdesc_end-1,
1519 ((dc_handle_t)dc->handle)->tdesc_table,
1520 ((dc_handle_t)dc->handle)->tdesc_table_size,
1521 &map_info_in));
1522 pc= map_info_in.preceding_tdesc_end;
1523 } else {
1524 dc_error (dc->handle, "Insufficient information for code reading.");
1525 }
1526 for (;;pc+=4) {
1527 if (pc==loc) {
1528 return (DC_TRUE);
1529 }
1530 instr= dc_read_word(dc->handle,pc);
1531 found_branch= dc_decode_finds_branch(dc,instr);
1532 if ((map_info_out.flags & DC_MIO_PROLOGUE_END)
1533 && (pc==map_info_out.prologue_end)) {
1534 break;
1535 }
1536 if (found_branch) {
1537 if (DC_MIO_IMPLICIT_PROLOGUE_END & map_info_out.flags) {
1538 break;
1539 } else {
1540 dc_error (dc->handle, "Found branch before end of prologue.");
1541 }
1542 }
1543 }
1544 if (!(map_info_out.flags & DC_MIO_LITERAL_EPILOGUE_START)
1545 && (map_info_out.epilogue_start >= loc
1546 || !(map_info_out.flags & DC_MIO_EPILOGUE_START))) {
1547 return (DC_TRUE);
1548 }
1549 dc_correct_cr_data(cdp,dc->handle);
1550 for (pc=map_info_out.epilogue_start;pc<loc;pc+=4) {
1551 instr= dc_read_word(dc->handle,pc);
1552 if (dc_decode_finds_branch(dc,instr)) {
1553 return (DC_FALSE);
1554 }
1555 }
1556 return (DC_TRUE);
1557
1558}
1559
1560
1561
1562dc_init_cr_data(cdp,tep)
1563dc_cr_data_t *cdp;
1564tdesc_elem_t *tep;
1565{
1566int reg;
1567dc_word_t rai;
1568dc_word_t raid;
1569dc_word_t rsm;
1570dc_word_t frpos;
1571
1572 if (tep){
1573
1574 /* Start off with all registers undefined and none saved. */
1575 for (reg = 0; reg < DC_NUM_REG; reg++) {
1576 cdp->reg_val[reg].reg = DC_UNDEF;
1577 }
1578 cdp->saved = 0;
1579
1580 /* Overwrite with what tdesc element says. */
1581
1582 cdp->reg_val[tep->info.frame_address_register].reg = DC_REG_SP;
1583 cdp->reg_val[tep->info.frame_address_register].off =
1584 - tep->info.frame_address_offset;
1585
1586 rai = tep->info.return_address_info;
1587 raid = tep->info.return_address_info_discriminant;
1588 if (raid || rai != DC_REG_RA) {
1589 bit_set(cdp->saved,DC_REG_RA);
1590 bit_assign(cdp->how,DC_REG_RA,raid);
1591 cdp->where[DC_REG_RA] = rai;
1592 }
1593
1594 rsm = tep->info.register_save_mask;
1595 frpos = tep->info.register_save_offset;
1596 for (reg = 14; reg <= 30; reg++) {
1597 if (bit_test(rsm, 30-reg)) {
1598 bit_set(cdp->saved,reg);
1599 bit_set(cdp->how,reg);
1600 cdp->where[reg] = frpos;
1601 frpos += sizeof(dc_word_t);
1602 } else {
1603 cdp->reg_val[reg].reg = reg;
1604 cdp->reg_val[reg].off = 0;
1605 }
1606 }
1607
1608 cdp->reg_val[0].reg = 0; /* guarantee what hardware does */
1609 cdp->reg_val[0].off = 0;
1610
1611 } else {
1612 /* Each register has its own initial value. */
1613 for (reg = 0; reg < DC_NUM_REG; reg++) {
1614 cdp->reg_val[reg].reg = reg;
1615 cdp->reg_val[reg].off = 0;
1616 }
1617 /* No register is yet saved. */
1618 cdp->saved = 0;
1619 cdp->how = 0;
1620 }
1621}
1622void dc_correct_cr_data(cdp,handle)
1623dc_cr_data_t *cdp;
1624dc_handle_t handle;
1625{
1626long sr,r;
1627dc_word_t save_regs = 0; /* registers used to save others */
1628 for (r = 1; r < DC_REG_SP; r++) {
1629 if (bit_test(cdp->saved,r) && !bit_test(cdp->how,r)) {
1630 sr = cdp->where[r];
1631 if (bit_test(save_regs,sr)) {
1632 dc_error(handle, "Same register used to save two others.");
1633 }
1634 bit_set(save_regs,sr);
1635 }
1636 }
1637 for (r = 1; r < DC_REG_FP; r++) {
1638 if ((r < 14 || bit_test(cdp->saved,r)) && !bit_test(save_regs,r)) {
1639 cdp->reg_val[r].reg = DC_UNDEF;
1640 }
1641 }
1642 if (bit_test(cdp->saved,DC_REG_FP) &&
1643 cdp->reg_val[DC_REG_FP].reg == DC_REG_SP) { /* is r30 the far? */
1644 cdp->reg_val[DC_REG_SP].reg = DC_UNDEF; /* trash sp */
1645 } else if (cdp->reg_val[DC_REG_SP].reg == DC_REG_SP) { /* is r31 the far? */
1646 if (bit_test(cdp->saved,DC_REG_FP) && !bit_test(save_regs,DC_REG_FP)) {
1647 cdp->reg_val[DC_REG_FP].reg = DC_UNDEF; /* trash r30 */
1648 }
1649 }
1650}
This page took 0.10631 seconds and 4 git commands to generate.