e6e002796c36358623bf3ea0889437753c0ec92d
[libfirm] / ir / debug / debugger.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief     Helper function for integerated debug support
23  * @author    Michael Beck
24  * @date      2005
25  * @version   $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef DEBUG_libfirm
32
33 #ifdef _WIN32
34 #define WIN32_LEAN_AND_MEAN
35 #include <windows.h>
36
37 #define strncasecmp strnicmp
38 #endif
39
40 #ifdef HAVE_STDLIB_H
41 #include <stdlib.h>
42 #endif
43
44 #include <stdio.h>
45 #include <signal.h>
46
47 #ifdef HAVE_STRING_H
48 #include <string.h>
49 #endif
50 #ifdef HAVE_STRINGS_H
51 #include <strings.h>
52 #endif
53
54 #include <ctype.h>
55
56 #include "set.h"
57 #include "ident.h"
58 #include "irhooks.h"
59 #include "irgraph_t.h"
60 #include "entity_t.h"
61 #include "irprintf.h"
62 #include "typewalk.h"
63 #include "irdump.h"
64 #include "debug.h"
65
66 #ifdef _WIN32
67 /* Break into the debugger. The Win32 way. */
68 void firm_debug_break(void) {
69         DebugBreak();
70 }
71 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
72 /* Break into the debugger. The ia32/x86_64 way under GCC. */
73 void firm_debug_break(void) {
74         __asm__ __volatile__("int3");
75 }
76 #else
77 /* Break into the debugger. Poor Unix way. */
78 void firm_debug_break(void) {
79         raise(SIGINT);
80 }
81 #endif /* _WIN32 */
82
83 /** supported breakpoint kinds */
84 typedef enum {
85         BP_NR    = 'n',   /**< break on node number. */
86         BP_IDENT = 'i'    /**< break on ident. */
87 } bp_kind;
88
89 /**
90  * Reasons for node number breakpoints.
91  */
92 typedef enum _bp_reasons_t {
93         BP_ON_NEW_NODE,    /**< break if node with number is created */
94         BP_ON_REPLACE,     /**< break if node with number is replaced */
95         BP_ON_LOWER,       /**< break if node with number is lowered */
96         BP_ON_REMIRG,      /**< break if an IRG is removed */
97         BP_ON_NEW_ENT,     /**< break if a new entity is created */
98         BP_ON_NEW_TYPE,    /**< break if a new type is created */
99         BP_MAX_REASON
100 } bp_reasons_t;
101
102 /** A breakpoint. */
103 typedef struct _breakpoint {
104         bp_kind      kind;        /**< the kind of this break point */
105         unsigned     bpnr;        /**< break point number */
106         int          active;      /**< non-zero, if this break point is active */
107         bp_reasons_t reason;      /**< reason for the breakpoint */
108         struct _breakpoint *next; /**< link to the next one */
109 } breakpoint;
110
111 /** A number breakpoint. */
112 typedef struct {
113         breakpoint   bp;       /**< the breakpoint data */
114         long         nr;       /**< the node number */
115 } bp_nr_t;
116
117 /** Calculate the hash value for a node breakpoint. */
118 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
119
120 /** An ident breakpoint. */
121 typedef struct {
122         breakpoint   bp;       /**< the breakpoint data */
123         ident        *id;      /**< the ident */
124 } bp_ident_t;
125
126 /** Calculate the hash value for an ident breakpoint. */
127 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
128
129 /** The set containing the breakpoints on node numbers. */
130 static set *bp_numbers;
131
132 /** The set containing the breakpoints on idents. */
133 static set *bp_idents;
134
135 /**< the list of all breakpoints */
136 static breakpoint *bp_list;
137
138 /** number of the current break point */
139 static unsigned bp_num = 0;
140
141 /** set if break on init command was issued. */
142 static int break_on_init = 0;
143
144 /** the hook entries for the Firm debugger module. */
145 static hook_entry_t debugger_hooks[hook_last];
146
147 /** number of active breakpoints to maintain hooks. */
148 static unsigned num_active_bp[BP_MAX_REASON];
149
150 /**
151  * The debug message buffer
152  */
153 static char firm_dbg_msg_buf[2048];
154
155 /**
156  * If set, the debug extension writes all output to the
157  * firm_dbg_msg_buf buffer
158  */
159 static int redir_output = 0;
160
161 /**
162  * Is set to one, if the debug extension is active
163  */
164 static int is_active = 0;
165
166 /** hook the hook h with function fkt. */
167 #define HOOK(h, fkt) \
168 do {                                      \
169         debugger_hooks[h].hook._##h = fkt;    \
170         register_hook(h, &debugger_hooks[h]); \
171 } while(0)
172
173 /** unhook the hook h */
174 #define UNHOOK(h) \
175 do {                                        \
176         unregister_hook(h, &debugger_hooks[h]); \
177         debugger_hooks[h].hook._##h = NULL;     \
178 } while(0)
179
180 /** returns non-zero if a entry hook h is used */
181 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
182
183 /* some macros needed to create the info string */
184 #define _DBG_VERSION(major, minor)  #major "." #minor
185 #define DBG_VERSION(major, minor)   _DBG_VERSION(major, minor)
186 #define API_VERSION(major, minor)   "API:" DBG_VERSION(major, minor)
187
188 /* the API version: change if needed */
189 #define FIRM_DBG_MAJOR  1
190 #define FIRM_DBG_MINOR  0
191
192 /** for automatic detection of the debug extension */
193 static const char *firm_debug_info_string =
194         API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
195
196 /**
197  * Returns non-zero, if the debug extension is active
198  */
199 int firm_debug_active(void) {
200         return is_active;
201 }  /* firm_debug_active */
202
203 /**
204  * Reset the debug text buffer.
205  */
206 static void reset_dbg_buf(void) {
207         firm_dbg_msg_buf[0] = '\0';
208 }  /* reset_dbg_buf */
209
210 /**
211  * Add text to the debug text buffer.
212  */
213 static void add_to_dbg_buf(const char *buf) {
214         strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
215 }  /* add_to_dbg_buf */
216
217 /**
218  * Return the content of the debug text buffer.
219  *
220  * To be called from the debugger.
221  */
222 const char *firm_debug_text(void) {
223         firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
224         return firm_dbg_msg_buf;
225 }  /* firm_debug_text */
226
227 /**
228  * debug output
229  */
230 static void dbg_printf(const char *fmt, ...)
231 {
232         char buf[1024];
233
234         va_list args;
235         va_start(args, fmt);
236
237         if (fmt[0] != '+')
238                 reset_dbg_buf();
239         else
240                 ++fmt;
241
242         ir_vsnprintf(buf, sizeof(buf), fmt, args);
243         va_end(args);
244
245         if (redir_output)
246                 add_to_dbg_buf(buf);
247         else
248                 puts(buf);
249 }  /* dbg_printf */
250
251 /**
252  * A new node is created.
253  *
254  * @param ctx   the hook context
255  * @param irg   the IR graph on which the node is created
256  * @param node  the new IR node that was created
257  */
258 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
259 {
260         bp_nr_t key, *elem;
261
262         key.nr        = get_irn_node_nr(node);
263         key.bp.reason = BP_ON_NEW_NODE;
264
265         elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
266         if (elem && elem->bp.active) {
267                 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
268                 firm_debug_break();
269         }
270 }  /* dbg_new_node */
271
272 /**
273  * A node is replaced.
274  *
275  * @param ctx   the hook context
276  * @param old   the IR node the is replaced
277  * @param nw    the new IR node that will replace old
278  */
279 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
280 {
281         bp_nr_t key, *elem;
282
283         key.nr        = get_irn_node_nr(old);
284         key.bp.reason = BP_ON_REPLACE;
285
286         elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
287         if (elem && elem->bp.active) {
288                 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
289                 firm_debug_break();
290         }
291 }  /* dbg_replace */
292
293 /**
294  * A new node is lowered.
295  *
296  * @param ctx   the hook context
297  * @param node  the new IR node that will be lowered
298  */
299 static void dbg_lower(void *ctx, ir_node *node)
300 {
301         bp_nr_t key, *elem;
302
303         key.nr        = get_irn_node_nr(node);
304         key.bp.reason = BP_ON_LOWER;
305
306         elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
307         if (elem && elem->bp.active) {
308                 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
309                 firm_debug_break();
310         }
311 }  /* dbg_lower */
312
313 /**
314  * A graph will be deleted.
315  *
316  * @param ctx   the hook context
317  * @param irg   the IR graph that will be deleted
318  */
319 static void dbg_free_graph(void *ctx, ir_graph *irg)
320 {
321         {
322                 bp_nr_t key, *elem;
323                 key.nr        = get_irg_graph_nr(irg);
324                 key.bp.reason = BP_ON_REMIRG;
325
326                 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
327                 if (elem && elem->bp.active) {
328                         ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
329                         firm_debug_break();
330                 }
331         }
332         {
333                 bp_ident_t key, *elem;
334                 ir_entity *ent = get_irg_entity(irg);
335
336                 if (! ent)
337                         return;
338
339                 key.id        = get_entity_ident(ent);
340                 key.bp.reason = BP_ON_REMIRG;
341
342                 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
343                 if (elem && elem->bp.active) {
344                         dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
345                         firm_debug_break();
346                 }
347         }
348 }  /* dbg_free_graph */
349
350 /**
351  * An entity was created.
352  *
353  * @param ctx   the hook context
354  * @param ent   the newly created entity
355  */
356 static void dbg_new_entity(void *ctx, ir_entity *ent)
357 {
358         {
359                 bp_ident_t key, *elem;
360
361                 key.id        = get_entity_ident(ent);
362                 key.bp.reason = BP_ON_NEW_ENT;
363
364                 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
365                 if (elem && elem->bp.active) {
366                         ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
367                         firm_debug_break();
368                 }
369         }
370         {
371                 bp_nr_t key, *elem;
372
373                 key.nr        = get_entity_nr(ent);
374                 key.bp.reason = BP_ON_NEW_ENT;
375
376                 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
377                 if (elem && elem->bp.active) {
378                         dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
379                         firm_debug_break();
380                 }
381         }
382 }  /* dbg_new_entity */
383
384 /**
385  * A type was created.
386  *
387  * @param ctx   the hook context
388  * @param tp    the newly created type
389  */
390 static void dbg_new_type(void *ctx, ir_type *tp)
391 {
392         {
393                 bp_nr_t key, *elem;
394
395                 key.nr        = get_type_nr(tp);
396                 key.bp.reason = BP_ON_NEW_TYPE;
397
398                 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
399                 if (elem && elem->bp.active) {
400                         ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
401                         firm_debug_break();
402                 }
403         }
404         {
405                 bp_ident_t key, *elem;
406
407                 key.id        = get_type_ident(tp);
408                 key.bp.reason = BP_ON_NEW_TYPE;
409
410                 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
411                 if (elem && elem->bp.active) {
412                         dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
413                         firm_debug_break();
414                 }
415         }
416 }  /* dbg_new_type */
417
418 /**
419  * Return the reason string.
420  */
421 static const char *reason_str(bp_reasons_t reason)
422 {
423         switch (reason) {
424         case BP_ON_NEW_NODE: return "node creation";
425         case BP_ON_REPLACE:  return "node replace";
426         case BP_ON_LOWER:    return "node lowering";
427         case BP_ON_REMIRG:   return "removing IRG";
428         case BP_ON_NEW_ENT:  return "entity creation";
429         case BP_ON_NEW_TYPE: return "type creation";
430         default:             assert(0);
431         }
432         return "unknown";
433 }  /* reason_str */
434
435 /**
436  * Compare two number breakpoints.
437  */
438 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
439 {
440         const bp_nr_t *e1 = elt;
441         const bp_nr_t *e2 = key;
442
443         return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
444 }  /* cmp_nr_bp */
445
446 /**
447  * Compare two ident breakpoints.
448  */
449 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
450 {
451         const bp_ident_t *e1 = elt;
452         const bp_ident_t *e2 = key;
453
454         return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
455 }  /* cmp_ident_bp */
456
457 /**
458  * Update the hooks.
459  */
460 static void update_hooks(breakpoint *bp)
461 {
462 #define CASE_ON(a, b)  case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
463 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
464
465         if (bp->active)
466                 ++num_active_bp[bp->reason];
467         else
468                 --num_active_bp[bp->reason];
469
470         if (num_active_bp[bp->reason] > 0) {
471                 /* register the hooks on demand */
472                 switch (bp->reason) {
473                 CASE_ON(BP_ON_NEW_NODE, new_node);
474                 CASE_ON(BP_ON_REPLACE, replace);
475                 CASE_ON(BP_ON_LOWER, lower);
476                 CASE_ON(BP_ON_REMIRG, free_graph);
477                 CASE_ON(BP_ON_NEW_ENT, new_entity);
478                 CASE_ON(BP_ON_NEW_TYPE, new_type);
479                 default:
480                         ;
481                 }
482         }
483         else {
484                 /* unregister the hook on demand */
485                 switch (bp->reason) {
486                 CASE_OFF(BP_ON_NEW_NODE, new_node);
487                 CASE_OFF(BP_ON_REPLACE, replace);
488                 CASE_OFF(BP_ON_LOWER, lower);
489                 CASE_OFF(BP_ON_REMIRG, free_graph);
490                 CASE_OFF(BP_ON_NEW_ENT, new_entity);
491                 CASE_OFF(BP_ON_NEW_TYPE, new_type);
492                 default:
493                         ;
494                 }
495         }
496 #undef CASE_ON
497 #undef CASE_OFF
498 }  /* update_hooks */
499
500 /**
501  * Break if nr is reached.
502  */
503 static void break_on_nr(long nr, bp_reasons_t reason)
504 {
505         bp_nr_t key, *elem;
506
507         key.bp.kind   = BP_NR;
508         key.bp.bpnr   = 0;
509         key.bp.active = 1;
510         key.bp.reason = reason;
511         key.nr        = nr;
512
513         elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
514
515         if (elem->bp.bpnr == 0) {
516                 /* new break point */
517                 elem->bp.bpnr = ++bp_num;
518                 elem->bp.next = bp_list;
519                 bp_list = &elem->bp;
520
521                 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
522
523                 update_hooks(&elem->bp);
524         }
525 }  /* break_on_nr */
526
527 /**
528  * Break if ident name is reached.
529  */
530 static void break_on_ident(const char *name, bp_reasons_t reason) {
531         bp_ident_t key, *elem;
532
533         key.bp.kind   = BP_IDENT;
534         key.bp.bpnr   = 0;
535         key.bp.active = 1;
536         key.bp.reason = reason;
537         key.id        = new_id_from_str(name);
538
539         elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
540
541         if (elem->bp.bpnr == 0) {
542                 /* new break point */
543                 elem->bp.bpnr = ++bp_num;
544                 elem->bp.next = bp_list;
545                 bp_list = &elem->bp;
546
547                 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
548
549                 update_hooks(&elem->bp);
550         }
551 }  /* break_on_ident */
552
553 /**
554  * Sets/resets the active flag of breakpoint bp.
555  */
556 static void bp_activate(unsigned bp, int active)
557 {
558         breakpoint *p;
559
560         for (p = bp_list; p; p = p->next) {
561                 if (p->bpnr == bp) {
562                         if (p->active != active) {
563                                 p->active = active;
564                                 update_hooks(p);
565                         }
566
567                         dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
568                         return;
569                 }
570         }
571         dbg_printf("Error: Firm BP %u not exists.\n", bp);
572 }  /* bp_activate */
573
574
575 /**
576  * Show a list of supported commands
577  */
578 static void show_commands(void) {
579         dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
580                 ".init                  break after initialization\n"
581                 ".create nr             break if node nr was created\n"
582                 ".replace nr            break if node nr is replaced by another node\n"
583                 ".lower nr              break before node nr is lowered\n"
584                 ".remirg nr|name        break if the irg of nr or entity name is deleted\n"
585                 ".newent nr|name        break if the entity nr or name was created\n"
586                 ".newtype nr|name       break if the type nr or name was created\n"
587                 ".bp                    show all breakpoints\n"
588                 ".enable nr             enable breakpoint nr\n"
589                 ".disable nr            disable breakpoint nr\n"
590                 ".showtype nr|name      show content of the type nr or name\n"
591                 ".showent nr|name       show content of the entity nr or name\n"
592                 ".setmask name msk      sets the debug module name to mask msk\n"
593                 ".setlvl  name lvl      sets the debug module name to level lvl\n"
594                 ".setoutfile name file  redirects debug output of module name to file\n"
595                 ".irgname name          prints address and graph number of a method given by its name\n"
596                 ".irgldname ldname      prints address and graph number of a method given by its ldname\n"
597                 ".help                  list all commands\n"
598                 );
599 }  /* show_commands */
600
601 /**
602  * Shows all Firm breakpoints.
603  */
604 static void show_bp(void) {
605         breakpoint *p;
606         bp_nr_t  *node_p;
607         bp_ident_t *ident_p;
608         int have_one = 0;
609
610         dbg_printf("Firm Breakpoints:");
611         for (p = bp_list; p; p = p->next) {
612                 have_one = 1;
613                 dbg_printf("+\n  BP %u: ", p->bpnr);
614
615                 switch (p->kind) {
616                 case BP_NR:
617                         node_p = (bp_nr_t *)p;
618                         dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
619                         break;
620
621                 case BP_IDENT:
622                         ident_p = (bp_ident_t *)p;
623                         dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
624                         break;
625                 }
626
627                 dbg_printf(p->active ? "+enabled" : "+disabled");
628         }
629         dbg_printf(have_one ? "+\n" : "+ NONE\n");
630 }  /* show_bp */
631
632 /**
633  * firm_dbg_register() expects that the name is stored persistent.
634  * So we need this little helper function
635  */
636 static firm_dbg_module_t *dbg_register(const char *name) {
637         ident *id = new_id_from_str(name);
638
639         return firm_dbg_register(get_id_str(id));
640 }  /* dbg_register */
641
642 /**
643  * Sets the debug mask of module name to lvl
644  */
645 static void set_dbg_level(const char *name, unsigned lvl)
646 {
647         firm_dbg_module_t *module = dbg_register(name);
648
649         if (firm_dbg_get_mask(module) != lvl) {
650                 firm_dbg_set_mask(module, lvl);
651
652                 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
653         }
654 }  /* set_dbg_level */
655
656 /**
657  * Redirects the debug output of module name to fname
658  */
659 static void set_dbg_outfile(const char *name, const char *fname)
660 {
661         firm_dbg_module_t *module = dbg_register(name);
662         FILE *f = fopen(fname, "w");
663
664         if (! f) {
665                 perror(fname);
666                 return;
667         }
668
669         firm_dbg_set_file(module, f);
670         dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
671 }  /* set_dbg_outfile */
672
673 /**
674  * Show info about a firm thing.
675  */
676 static void show_firm_object(void *firm_thing) {
677         FILE *f = stdout;
678
679         if (firm_thing == NULL) {
680                 fprintf(f, "<NULL>\n");
681                 return;
682         }
683         switch (get_kind(firm_thing)) {
684         case k_BAD:
685                 fprintf(f, "BAD: (%p)\n", firm_thing);
686                 break;
687         case k_entity:
688                 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
689                 break;
690         case k_type:
691                 dump_type_to_file(f, firm_thing, dump_verbosity_max);
692                 break;
693         case k_ir_graph:
694         case k_ir_node:
695         case k_ir_mode:
696         case k_ir_op:
697         case k_tarval:
698         case k_ir_loop:
699         case k_ir_compound_graph_path:
700         case k_ir_extblk:
701         case k_ir_prog:
702                 fprintf(f, "NIY\n");
703                 break;
704         default:
705                 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
706         }
707 }  /* show_firm_object */
708
709 /**
710  * Find a firm type by its number.
711  */
712 static ir_type *find_type_nr(long nr) {
713         int i, n = get_irp_n_types();
714         ir_type *tp;
715
716         for (i = 0; i < n; ++i) {
717                 tp = get_irp_type(i);
718                 if (get_type_nr(tp) == nr)
719                         return tp;
720         }
721         tp = get_glob_type();
722         if (get_type_nr(tp) == nr)
723                 return tp;
724         return NULL;
725 }  /* find_type_nr */
726
727 /**
728  * Find a firm type by its name.
729  */
730 static ir_type *find_type_name(const char *name) {
731         int i, n = get_irp_n_types();
732         ir_type *tp;
733
734         for (i = 0; i < n; ++i) {
735                 tp = get_irp_type(i);
736                 if (strcmp(get_type_name(tp), name) == 0)
737                         return tp;
738         }
739         tp = get_glob_type();
740         if (strcmp(get_type_name(tp), name) == 0)
741                 return tp;
742         return NULL;
743 }  /* find_type_name */
744
745 /** The environment for the entity search functions. */
746 typedef struct find_env {
747         union {
748                 long        nr;   /**< the number that is searched for */
749                 const char *name; /**< the name that is searched for */
750         } u;
751         ir_entity *res;     /**< the result */
752 } find_env_t;
753
754 /**
755  * Type-walker: Find an entity with given number.
756  */
757 static void check_ent_nr(type_or_ent *tore, void *ctx) {
758         ir_entity *ent = (ir_entity *)tore;
759         find_env_t *env = ctx;
760
761         if (is_entity(ent))
762                 if (get_entity_nr(ent) == env->u.nr) {
763                         env->res = ent;
764                 }
765 }  /* check_ent_nr */
766
767 /**
768  * Type-walker: Find an entity with given name.
769  */
770 static void check_ent_name(type_or_ent *tore, void *ctx) {
771         ir_entity *ent = (ir_entity *)tore;
772         find_env_t *env = ctx;
773
774         if (is_entity(ent))
775                 if (strcmp(get_entity_name(ent), env->u.name) == 0) {
776                         env->res = ent;
777                 }
778 }  /* check_ent_name */
779
780 /**
781  * Find a firm entity by its number.
782  */
783 static ir_entity *find_entity_nr(long nr) {
784         find_env_t env;
785
786         env.u.nr = nr;
787         env.res  = NULL;
788         type_walk(check_ent_nr, NULL, &env);
789         return env.res;
790 }  /* find_entity_nr */
791
792 /**
793  * Find a firm entity by its name.
794  */
795 static ir_entity *find_entity_name(const char *name) {
796         find_env_t env;
797
798         env.u.name = name;
799         env.res    = NULL;
800         type_walk(check_ent_name, NULL, &env);
801         return env.res;
802 }  /* find_entity_name */
803
804 /**
805  * Search methods for a name.
806  */
807 static void show_by_name(type_or_ent *tore, void *env) {
808         ident *id = (ident *)env;
809
810         if (is_entity(tore)) {
811                 ir_entity *ent = (ir_entity *)tore;
812
813                 if (is_method_entity(ent)) {
814                         if (get_entity_ident(ent) == id) {
815                                 ir_type *owner = get_entity_owner(ent);
816                                 ir_graph *irg = get_entity_irg(ent);
817
818                                 if (owner != get_glob_type()) {
819                                         printf("%s::%s", get_type_name(owner), get_id_str(id));
820                                 } else {
821                                         printf("%s", get_id_str(id));
822                                 }
823                                 if (irg)
824                                         printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
825                                 else
826                                         printf(" NULL\n");
827                         }
828                 }
829         }
830 }  /* show_by_name */
831
832 /**
833  * Search methods for a ldname.
834  */
835 static void show_by_ldname(type_or_ent *tore, void *env) {
836         ident *id = (ident *)env;
837
838         if (is_entity(tore)) {
839                 ir_entity *ent = (ir_entity *)tore;
840
841                 if (is_method_entity(ent)) {
842                         if (get_entity_ld_ident(ent) == id) {
843                                 ir_type *owner = get_entity_owner(ent);
844                                 ir_graph *irg = get_entity_irg(ent);
845
846                                 if (owner != get_glob_type()) {
847                                         printf("%s::%s", get_type_name(owner), get_id_str(id));
848                                 } else {
849                                         printf("%s", get_id_str(id));
850                                 }
851                                 if (irg)
852                                         printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
853                                 else
854                                         printf(" NULL\n");
855                         }
856                 }
857         }
858 }  /* show_by_ldname */
859
860 /**
861  * prints the address and graph number of all irgs with given name
862  */
863 static void irg_name(const char *name) {
864         ident *id = new_id_from_str(name);
865
866         type_walk(show_by_name, NULL, (void *)id);
867 }  /* irg_name */
868
869 /**
870  * prints the address and graph number of all irgs with given ld_name
871  */
872 static void irg_ld_name(const char *name) {
873         ident *id = new_id_from_str(name);
874
875         type_walk(show_by_ldname, NULL, (void *)id);
876 }  /* irg_ld_name */
877
878 enum tokens {
879         tok_create = 256,
880         tok_replace,
881         tok_lower,
882         tok_remirg,
883         tok_newent,
884         tok_newtype,
885         tok_showtype,
886         tok_showent,
887         tok_init,
888         tok_bp,
889         tok_enable,
890         tok_disable,
891         tok_setmask,
892         tok_setlvl,
893         tok_setoutfile,
894         tok_irgname,
895         tok_irgldname,
896         tok_help,
897         tok_identifier,
898         tok_number,
899         tok_eof,
900         tok_error
901 };
902
903 static const char *reserved[] = {
904         "create",
905         "replace",
906         "lower",
907         "remirg",
908         "newent",
909         "newtype",
910         "showtype",
911         "showent",
912         "init",
913         "bp",
914         "enable",
915         "disable",
916         "setmask",
917         "setlvl",
918         "setoutfile",
919         "irgname",
920         "irgldname",
921         "help"
922 };
923
924 /**
925  * The Lexer data.
926  */
927 static struct lexer {
928         int has_token;        /**< set if a token is cached. */
929         unsigned cur_token;   /**< current token. */
930         unsigned number;      /**< current token attribute. */
931         const char *s;        /**< current token attribute. */
932         unsigned len;         /**< current token attribute. */
933
934         const char *curr_pos;
935         const char *end_pos;
936         const char *tok_start;
937 } lexer;
938
939 /**
940  * Initialize the lexer.
941  */
942 static void init_lexer(const char *input) {
943         lexer.has_token = 0;
944         lexer.curr_pos  = input;
945         lexer.end_pos   = input + strlen(input);
946 }  /* init_lexer */
947
948
949 /**
950  * Get the next char from the input.
951  */
952 static char next_char(void) {
953         if (lexer.curr_pos >= lexer.end_pos)
954                 return '\0';
955         return *lexer.curr_pos++;
956 }  /* next_char */
957
958 #define unput()         if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
959
960 #undef MIN
961 #define MIN(a, b) (a) < (b) ? (a) : (b)
962
963 /**
964  * The lexer.
965  */
966 static unsigned get_token(void) {
967         char c;
968         int i;
969
970         /* skip white space */
971         do {
972                 c = next_char();
973         } while (c != '\0' && isspace(c));
974
975         lexer.tok_start = lexer.curr_pos - 1;
976         if (c == '.') {
977                 /* command begins here */
978                 int len = 0;
979
980                 do {
981                         c = next_char();
982                         ++len;
983                 } while (isalpha(c));
984                 unput();
985
986                 --len;
987                 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
988                         if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0')
989                                 break;
990                 }
991                 if (i >= 0)
992                         return 256 + i;
993                 return tok_error;
994         } else if (isalpha(c)) {
995                 /* identifier */
996                 lexer.s = lexer.curr_pos - 1;
997
998                 do {
999                         c = next_char();
1000                 } while (isgraph(c));
1001                 unput();
1002                 lexer.len = lexer.curr_pos - lexer.s;
1003                 return tok_identifier;
1004         } else if (isdigit(c) || c == '-') {
1005                 unsigned number = 0;
1006                 unsigned sign   = 0;
1007
1008                 /* we support negative numbers as well, so one can easily set all bits with -1 */
1009                 if (c == '-') {
1010                         sign = 1;
1011                         c    = next_char();
1012                 }
1013
1014                 if (c == '0') {
1015                         c = next_char();
1016
1017                         if (c == 'x' || c == 'X') {
1018                                 for (;;) {
1019                                         c = next_char();
1020
1021                                         if (! isxdigit(c))
1022                                                 break;
1023                                         if (isdigit(c))
1024                                                 number = (number << 4) | (c - '0');
1025                                         else
1026                                                 number = (number << 4) | (toupper(c) - 'A' + 10);
1027                                 }
1028                                 unput();
1029                                 lexer.number = number;
1030                                 return tok_number;
1031                         }
1032                 }
1033                 for (;;) {
1034                         if (! isdigit(c))
1035                                 break;
1036                         number = number * 10 + (c - '0');
1037                         c = next_char();
1038                 }
1039                 unput();
1040                 lexer.number = sign ? 0 - number : number;
1041                 return tok_number;
1042         }
1043         else if (c == '\0')
1044                 return tok_eof;
1045         return c;
1046 }  /* get_token */
1047
1048 /**
1049  * High level function to use from debugger interface
1050  *
1051  * Supported commands:
1052  *  .create nr    break if node nr was created
1053  *  .help         list all commands
1054  */
1055 void firm_debug(const char *cmd) {
1056         char name[1024], fname[1024];
1057         int len;
1058
1059         init_lexer(cmd);
1060
1061         for (;;) {
1062                 unsigned token;
1063
1064                 token = get_token();
1065
1066                 switch (token) {
1067                 case tok_eof:
1068                         goto leave;
1069
1070                 case tok_create:
1071                         token = get_token();
1072                         if (token != tok_number)
1073                                 goto error;
1074                         break_on_nr(lexer.number, BP_ON_NEW_NODE);
1075                         break;
1076
1077                 case tok_replace:
1078                         token = get_token();
1079                         if (token != tok_number)
1080                                 goto error;
1081                         break_on_nr(lexer.number, BP_ON_REPLACE);
1082                         break;
1083
1084                 case tok_lower:
1085                         token = get_token();
1086                         if (token != tok_number)
1087                                 goto error;
1088                         break_on_nr(lexer.number, BP_ON_LOWER);
1089                         break;
1090
1091                 case tok_remirg:
1092                         token = get_token();
1093
1094                         if (token == tok_number)
1095                                 break_on_nr(lexer.number, BP_ON_REMIRG);
1096                         else if (token == tok_identifier) {
1097                                 len = MIN(lexer.len, 1023);
1098                                 strncpy(name, lexer.s, len);
1099                                 name[len] = '\0';
1100                                 break_on_ident(name, BP_ON_REMIRG);
1101                         } else
1102                                 goto error;
1103                         break;
1104
1105                 case tok_newent:
1106                         token = get_token();
1107
1108                         if (token == tok_number)
1109                                 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1110                         else if (token == tok_identifier) {
1111                                 len = MIN(lexer.len, 1023);
1112                                 strncpy(name, lexer.s, len);
1113                                 name[len] = '\0';
1114                                 break_on_ident(name, BP_ON_NEW_ENT);
1115                         } else
1116                                 goto error;
1117                         break;
1118
1119                 case tok_newtype:
1120                         token = get_token();
1121
1122                         if (token == tok_number)
1123                                 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1124                         else if (token == tok_identifier) {
1125                                 len = MIN(lexer.len, 1023);
1126                                 strncpy(name, lexer.s, len);
1127                                 name[len] = '\0';
1128                                 break_on_ident(name, BP_ON_NEW_TYPE);
1129                         } else
1130                                 goto error;
1131                         break;
1132
1133                 case tok_showtype:
1134                         token = get_token();
1135
1136                         if (token == tok_number)
1137                                 show_firm_object(find_type_nr(lexer.number));
1138                         else if (token == tok_identifier) {
1139                                 len = MIN(lexer.len, 1023);
1140                                 strncpy(name, lexer.s, len);
1141                                 name[len] = '\0';
1142                                 show_firm_object(find_type_name(name));
1143                         } else
1144                                 goto error;
1145                         break;
1146
1147                 case tok_showent:
1148                         token = get_token();
1149
1150                         if (token == tok_number)
1151                                 show_firm_object(find_entity_nr(lexer.number));
1152                         else if (token == tok_identifier) {
1153                                 len = MIN(lexer.len, 1023);
1154                                 strncpy(name, lexer.s, len);
1155                                 name[len] = '\0';
1156                                 show_firm_object(find_entity_name(name));
1157                         } else
1158                                 goto error;
1159                         break;
1160
1161                 case tok_init:
1162                         break_on_init = 1;
1163                         break;
1164
1165                 case tok_bp:
1166                         show_bp();
1167                         break;
1168
1169                 case tok_enable:
1170                         token = get_token();
1171                         if (token != tok_number)
1172                                 goto error;
1173                         bp_activate(lexer.number, 1);
1174                         break;
1175
1176                 case tok_disable:
1177                         token = get_token();
1178                         if (token != tok_number)
1179                                 goto error;
1180                         bp_activate(lexer.number, 0);
1181                         break;
1182
1183                 case tok_setmask:
1184                         token = get_token();
1185                         if (token != tok_identifier)
1186                                 goto error;
1187                         len = MIN(lexer.len, 1023);
1188                         strncpy(name, lexer.s, len);
1189                         name[len] = '\0';
1190
1191                         token = get_token();
1192                         if (token != tok_number)
1193                                 goto error;
1194                         set_dbg_level(name, lexer.number);
1195                         break;
1196
1197                 case tok_setlvl:
1198                         token = get_token();
1199                         if (token != tok_identifier)
1200                                 goto error;
1201                         len = MIN(lexer.len, 1023);
1202                         strncpy(name, lexer.s, len);
1203                         name[len] = '\0';
1204
1205                         token = get_token();
1206                         if (token != tok_number)
1207                                 goto error;
1208                         set_dbg_level(name, (1 << lexer.number) - 1);
1209                         break;
1210
1211                 case tok_setoutfile:
1212                         token = get_token();
1213                         if (token != tok_identifier)
1214                                 goto error;
1215                         len = MIN(lexer.len, 1023);
1216                         strncpy(name, lexer.s, len);
1217                         name[len] = '\0';
1218
1219                         token = get_token();
1220                         if (token != tok_identifier)
1221                                 goto error;
1222                         len = MIN(lexer.len, 1023);
1223                         strncpy(fname, lexer.s, len);
1224                         fname[len] = '\0';
1225                         set_dbg_outfile(name, fname);
1226
1227                 case tok_irgname:
1228                         token = get_token();
1229                         if (token != tok_identifier)
1230                                 goto error;
1231                         len = MIN(lexer.len, 1023);
1232                         strncpy(name, lexer.s, len);
1233                         name[len] = '\0';
1234                         irg_name(name);
1235
1236                 case tok_irgldname:
1237                         token = get_token();
1238                         if (token != tok_identifier)
1239                                 goto error;
1240                         len = MIN(lexer.len, 1023);
1241                         strncpy(name, lexer.s, len);
1242                         name[len] = '\0';
1243                         irg_ld_name(name);
1244                         break;
1245
1246                 case tok_help:
1247                         show_commands();
1248                         break;
1249
1250                 case tok_error:
1251                 default:
1252 error:
1253                         printf("Error: before %s\n", lexer.tok_start);
1254                         show_commands();
1255                         goto leave;
1256                 }
1257
1258                 token = get_token();
1259                 if (token == tok_eof)
1260                         break;
1261                 if (token != ';')
1262                         goto error;
1263         }
1264 leave:
1265         ;
1266 }  /* firm_debug */
1267
1268 /* creates the debugger tables */
1269 void firm_init_debugger(void)
1270 {
1271         char *env;
1272
1273         bp_numbers = new_set(cmp_nr_bp, 8);
1274         bp_idents  = new_set(cmp_ident_bp, 8);
1275
1276         env = getenv("FIRMDBG");
1277
1278         is_active = 1;
1279
1280         if (env)
1281                 firm_debug(env);
1282
1283         if (break_on_init)
1284                 firm_debug_break();
1285 }  /* firm_init_debugger */
1286
1287 #else
1288
1289 /* some picky compiler do not allow empty files */
1290 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
1291
1292 #endif /* NDEBUG */
1293
1294 /**
1295  * @page debugger   The Firm debugger extension
1296  *
1297  * Firm contains a debugger extension. This allows to set debugger breakpoints
1298  * an various events.
1299  * The extension uses a text interface which can be accessed from most debuggers.
1300  * More than one command can be given separated by ';'.
1301  *
1302  * @section sec_cmd Supported commands
1303  *
1304  * The following commands are currently supported:
1305  *
1306  * @b .init
1307  *
1308  * Break immediately after the debugger extension was initialized.
1309  * Typically this command is used in the environment to stop the execution
1310  * of a Firm compiler right after the initialization, like this:
1311  *
1312  * $export FIRMDBG=".init"
1313  *
1314  * @b .create nr
1315  *
1316  * Break if a new IR-node with node number nr was created.
1317  * Typically used to find the place where wrong nodes are created.
1318  *
1319  * @b .replace nr
1320  *
1321  * Break before IR-node with node number nr is replaced by another node.
1322  *
1323  * @b .lower nr
1324  *
1325  * Break before IR-node with node number nr is lowered.
1326  *
1327  * @b .remirg nr
1328  *
1329  * Break if the irg with graph number nr is deleted.
1330  *
1331  * @b .remirg name
1332  *
1333  * Break if the irg of entity name is deleted.
1334  *
1335  * @b .newent nr
1336  *
1337  * Break if the entity with number nr was created.
1338  *
1339  * @b .newent name
1340  *
1341  * Break if the entity name was created.
1342  *
1343  * @b .newtype nr
1344  *
1345  * Break if the type with number nr was created.
1346  *
1347  * @b .newtype name
1348  *
1349  * Break if the type name was created.
1350  *
1351  * @b .bp
1352  *
1353  * Show all Firm internal breakpoints.
1354  *
1355  * @b .enable nr
1356  *
1357  * Enables breakpoint nr.
1358  *
1359  * @b .disable nr
1360  *
1361  * Disables breakpoint nr.
1362  *
1363  * @b .showent nr
1364  *
1365  * Show the content of entity nr.
1366  *
1367  * @b .showent name
1368  *
1369  * Show the content of entity name.
1370  *
1371  * @b .showtype nr
1372  *
1373  * Show the content of type nr.
1374  *
1375  * @b .showtype name
1376  *
1377  * Show the content of type name.
1378  *
1379  * @b .setmask name msk
1380  *
1381  * Sets the debug module name to mask msk.
1382  *
1383  * @b .setlvl name lvl
1384  *
1385  * Sets the debug module name to level lvl.
1386  *
1387  * @b .setoutfile name file
1388  *
1389  * Redirects debug output of module name to file.
1390  *
1391  * @b .irgname name
1392  *
1393  * Prints address and graph number of a method given by its name.
1394  *
1395  * @b .irgldname name
1396  *
1397  * Prints address and graph number of a method given by its linker name.
1398  *
1399  * @b .help
1400  *
1401  * List all commands.
1402  *
1403  *
1404  * The Firm debugger extension can be accessed using the function firm_debug().
1405  * The following example shows how to set a creation breakpoint in GDB when
1406  * node 2101 is created.
1407  *
1408  * -# set FIRMDBG=".init"
1409  * -# start gdb with your compiler
1410  * -# after gdb breaks, issue
1411  *
1412  * call firm_debug(".create 2101")
1413  *
1414  * On the console the following text should be issued:
1415  *
1416  * Firm BP 1: creation of Node 2101
1417  *
1418  *
1419  * @section gdb_macro GDB macro
1420  *
1421  * Add the following to your .gdbinit file:
1422  * @code
1423  #
1424  # define firm "cmd"  Firm debugger extension
1425  #
1426  define firm
1427  call firm_debug($arg0)
1428  end
1429  * @endcode
1430  *
1431  * Then, all Firm debugger extension commands can be accessed in the gdb
1432  * console using the firm prefix, eg.:
1433  *
1434  * firm ".create 2101"
1435  *
1436  * firm ".help"
1437  */