]> Git Repo - binutils.git/blob - gdb/tdesc.c
ansi name abuse changes
[binutils.git] / gdb / tdesc.c
1 /* This file has been modified by Data General Corporation, November 1989. */
2
3 /*
4 This 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
28 typedef int dc_boolean_t;   /* range 0 .. 1 */
29 #define DC_FALSE 0
30 #define DC_TRUE 1
31
32
33 typedef 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 */
48 typedef 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. */
64 typedef 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
75 typedef 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
93 typedef 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
103 typedef 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
109 typedef 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
119 typedef 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
131 typedef struct tdesc_chunk1 {
132    tdesc_chunk_hdr_t    hdr;
133    tdesc_chunk_info1_t  info;
134 } tdesc_chunk1_t;
135
136
137 typedef 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
148 typedef 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
155 typedef 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
209 extern char *malloc();
210 extern char *calloc();
211 extern 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
221 typedef 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
227 typedef tdesc_elem_t *tdesc_table_t;
228
229 void dc_correct_cr_data();
230
231 int 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;
238    if (s1 > s2) return  1;
239    e1 = ((tdesc_elem_t *) elem1)->end_address;
240    e2 = ((tdesc_elem_t *) elem2)->end_address;
241    if (e1 < e2) return -1;
242    if (e1 > e2) return  1;
243    return 0;
244 }
245
246
247 typedef 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
263 typedef 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>
278 extern int vsprintf();
279
280 /* Exit status for exception-processing machinery failure */
281 #define DC_EXCEPTION_FAILURE    250
282
283 void 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
300 void 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
311 void 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
329 char* 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
343 char* 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
356 dc_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
367 void 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
383 void 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
394 dc_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
585 void 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
740 typedef 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
760 typedef 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
785 typedef 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
794 typedef 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
811 typedef dcontext_info_t *dc_dcontext_t;
812
813 dc_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
829 void 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
857 void 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
891 tdesc_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
937 dc_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
1001 void 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
1015 dc_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
1022 dc_exactness_t dc_location_exactness (dcontext)
1023    dc_dcontext_t dcontext;
1024 {
1025    return ((dc_dcontext_t)dcontext)->loc_exact;
1026 }
1027
1028
1029 dc_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
1038 dc_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
1056 void 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
1072 dc_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
1081 dc_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
1091 void 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
1103 dc_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
1112 dc_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
1122 void 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
1134 dc_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
1143 dc_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
1155 void 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
1175 dc_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
1197 dc_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
1209 dc_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
1237 dc_exactness_t dc_return_address_exactness (dcontext)
1238    dc_dcontext_t dcontext;
1239 {
1240    return DC_MAYBE;
1241 }
1242
1243
1244 dc_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
1279 void 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
1323 void 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
1337 void 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
1351 void 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
1365 dc_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
1477 typedef
1478    struct label {
1479       ???
1480    } label_t;
1481
1482
1483 label_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
1493 dc_read_code(loc,dc,map_info_in,cdp)
1494 dc_word_t loc;
1495 dc_dcontext_t dc;
1496 dc_cr_data_t *cdp;
1497 dc_map_info_in_t map_info_in;
1498 {
1499 dc_map_info_out_t map_info_out;
1500 dc_word_t pc;
1501 dc_boolean_t found_branch=DC_FALSE;
1502 dc_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
1562 dc_init_cr_data(cdp,tep)
1563 dc_cr_data_t *cdp;
1564 tdesc_elem_t *tep;
1565 {
1566 int reg;
1567 dc_word_t rai;
1568 dc_word_t raid;
1569 dc_word_t rsm;
1570 dc_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 }
1622 void dc_correct_cr_data(cdp,handle)
1623 dc_cr_data_t *cdp;
1624 dc_handle_t handle;
1625 {
1626 long sr,r;
1627 dc_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.116381 seconds and 4 git commands to generate.