Add branch trace information to struct thread_info.
[platform/upstream/binutils.git] / gdb / btrace.c
1 /* Branch trace support for GDB, the GNU debugger.
2
3    Copyright (C) 2013 Free Software Foundation, Inc.
4
5    Contributed by Intel Corp. <markus.t.metzger@intel.com>
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "btrace.h"
23 #include "gdbthread.h"
24 #include "exceptions.h"
25 #include "inferior.h"
26 #include "target.h"
27 #include "record.h"
28 #include "symtab.h"
29 #include "disasm.h"
30 #include "source.h"
31 #include "filenames.h"
32
33 /* Print a record debug message.  Use do ... while (0) to avoid ambiguities
34    when used in if statements.  */
35
36 #define DEBUG(msg, args...)                                             \
37   do                                                                    \
38     {                                                                   \
39       if (record_debug != 0)                                            \
40         fprintf_unfiltered (gdb_stdlog,                                 \
41                             "[btrace] " msg "\n", ##args);              \
42     }                                                                   \
43   while (0)
44
45 #define DEBUG_FTRACE(msg, args...) DEBUG ("[ftrace] " msg, ##args)
46
47 /* Initialize the instruction iterator.  */
48
49 static void
50 btrace_init_insn_iterator (struct btrace_thread_info *btinfo)
51 {
52   DEBUG ("init insn iterator");
53
54   btinfo->insn_iterator.begin = 1;
55   btinfo->insn_iterator.end = 0;
56 }
57
58 /* Initialize the function iterator.  */
59
60 static void
61 btrace_init_func_iterator (struct btrace_thread_info *btinfo)
62 {
63   DEBUG ("init func iterator");
64
65   btinfo->func_iterator.begin = 1;
66   btinfo->func_iterator.end = 0;
67 }
68
69 /* Compute the instruction trace from the block trace.  */
70
71 static VEC (btrace_inst_s) *
72 compute_itrace (VEC (btrace_block_s) *btrace)
73 {
74   VEC (btrace_inst_s) *itrace;
75   struct gdbarch *gdbarch;
76   unsigned int b;
77
78   DEBUG ("compute itrace");
79
80   itrace = NULL;
81   gdbarch = target_gdbarch ();
82   b = VEC_length (btrace_block_s, btrace);
83
84   while (b-- != 0)
85     {
86       btrace_block_s *block;
87       CORE_ADDR pc;
88
89       block = VEC_index (btrace_block_s, btrace, b);
90       pc = block->begin;
91
92       /* Add instructions for this block.  */
93       for (;;)
94         {
95           btrace_inst_s *inst;
96           int size;
97
98           /* We should hit the end of the block.  Warn if we went too far.  */
99           if (block->end < pc)
100             {
101               warning (_("Recorded trace may be corrupted."));
102               break;
103             }
104
105           inst = VEC_safe_push (btrace_inst_s, itrace, NULL);
106           inst->pc = pc;
107
108           /* We're done once we pushed the instruction at the end.  */
109           if (block->end == pc)
110             break;
111
112           size = gdb_insn_length (gdbarch, pc);
113
114           /* Make sure we terminate if we fail to compute the size.  */
115           if (size <= 0)
116             {
117               warning (_("Recorded trace may be incomplete."));
118               break;
119             }
120
121           pc += size;
122         }
123     }
124
125   return itrace;
126 }
127
128 /* Return the function name of a recorded function segment for printing.
129    This function never returns NULL.  */
130
131 static const char *
132 ftrace_print_function_name (struct btrace_func *bfun)
133 {
134   struct minimal_symbol *msym;
135   struct symbol *sym;
136
137   msym = bfun->msym;
138   sym = bfun->sym;
139
140   if (sym != NULL)
141     return SYMBOL_PRINT_NAME (sym);
142
143   if (msym != NULL)
144     return SYMBOL_PRINT_NAME (msym);
145
146   return "<unknown>";
147 }
148
149 /* Return the file name of a recorded function segment for printing.
150    This function never returns NULL.  */
151
152 static const char *
153 ftrace_print_filename (struct btrace_func *bfun)
154 {
155   struct symbol *sym;
156   const char *filename;
157
158   sym = bfun->sym;
159
160   if (sym != NULL)
161     filename = symtab_to_filename_for_display (sym->symtab);
162   else
163     filename = "<unknown>";
164
165   return filename;
166 }
167
168 /* Print an ftrace debug status message.  */
169
170 static void
171 ftrace_debug (struct btrace_func *bfun, const char *prefix)
172 {
173   DEBUG_FTRACE ("%s: fun = %s, file = %s, lines = [%d; %d], insn = [%u; %u]",
174                 prefix, ftrace_print_function_name (bfun),
175                 ftrace_print_filename (bfun), bfun->lbegin, bfun->lend,
176                 bfun->ibegin, bfun->iend);
177 }
178
179 /* Initialize a recorded function segment.  */
180
181 static void
182 ftrace_init_func (struct btrace_func *bfun, struct minimal_symbol *mfun,
183                   struct symbol *fun, unsigned int idx)
184 {
185   bfun->msym = mfun;
186   bfun->sym = fun;
187   bfun->lbegin = INT_MAX;
188   bfun->lend = 0;
189   bfun->ibegin = idx;
190   bfun->iend = idx;
191 }
192
193 /* Check whether the function has changed.  */
194
195 static int
196 ftrace_function_switched (struct btrace_func *bfun,
197                           struct minimal_symbol *mfun, struct symbol *fun)
198 {
199   struct minimal_symbol *msym;
200   struct symbol *sym;
201
202   /* The function changed if we did not have one before.  */
203   if (bfun == NULL)
204     return 1;
205
206   msym = bfun->msym;
207   sym = bfun->sym;
208
209   /* If the minimal symbol changed, we certainly switched functions.  */
210   if (mfun != NULL && msym != NULL
211       && strcmp (SYMBOL_LINKAGE_NAME (mfun), SYMBOL_LINKAGE_NAME (msym)) != 0)
212     return 1;
213
214   /* If the symbol changed, we certainly switched functions.  */
215   if (fun != NULL && sym != NULL)
216     {
217       const char *bfname, *fname;
218
219       /* Check the function name.  */
220       if (strcmp (SYMBOL_LINKAGE_NAME (fun), SYMBOL_LINKAGE_NAME (sym)) != 0)
221         return 1;
222
223       /* Check the location of those functions, as well.  */
224       bfname = symtab_to_fullname (sym->symtab);
225       fname = symtab_to_fullname (fun->symtab);
226       if (filename_cmp (fname, bfname) != 0)
227         return 1;
228     }
229
230   return 0;
231 }
232
233 /* Check if we should skip this file when generating the function call
234    history.  We would want to do that if, say, a macro that is defined
235    in another file is expanded in this function.  */
236
237 static int
238 ftrace_skip_file (struct btrace_func *bfun, const char *filename)
239 {
240   struct symbol *sym;
241   const char *bfile;
242
243   sym = bfun->sym;
244
245   if (sym != NULL)
246     bfile = symtab_to_fullname (sym->symtab);
247   else
248     bfile = "";
249
250   if (filename == NULL)
251     filename = "";
252
253   return (filename_cmp (bfile, filename) != 0);
254 }
255
256 /* Compute the function trace from the instruction trace.  */
257
258 static VEC (btrace_func_s) *
259 compute_ftrace (VEC (btrace_inst_s) *itrace)
260 {
261   VEC (btrace_func_s) *ftrace;
262   struct btrace_inst *binst;
263   struct btrace_func *bfun;
264   unsigned int idx;
265
266   DEBUG ("compute ftrace");
267
268   ftrace = NULL;
269   bfun = NULL;
270
271   for (idx = 0; VEC_iterate (btrace_inst_s, itrace, idx, binst); ++idx)
272     {
273       struct symtab_and_line sal;
274       struct minimal_symbol *mfun;
275       struct symbol *fun;
276       const char *filename;
277       CORE_ADDR pc;
278
279       pc = binst->pc;
280
281       /* Try to determine the function we're in.  We use both types of symbols
282          to avoid surprises when we sometimes get a full symbol and sometimes
283          only a minimal symbol.  */
284       fun = find_pc_function (pc);
285       mfun = lookup_minimal_symbol_by_pc (pc);
286
287       if (fun == NULL && mfun == NULL)
288         {
289           DEBUG_FTRACE ("no symbol at %u, pc=%s", idx,
290                         core_addr_to_string_nz (pc));
291           continue;
292         }
293
294       /* If we're switching functions, we start over.  */
295       if (ftrace_function_switched (bfun, mfun, fun))
296         {
297           bfun = VEC_safe_push (btrace_func_s, ftrace, NULL);
298
299           ftrace_init_func (bfun, mfun, fun, idx);
300           ftrace_debug (bfun, "init");
301         }
302
303       /* Update the instruction range.  */
304       bfun->iend = idx;
305       ftrace_debug (bfun, "update insns");
306
307       /* Let's see if we have source correlation, as well.  */
308       sal = find_pc_line (pc, 0);
309       if (sal.symtab == NULL || sal.line == 0)
310         {
311           DEBUG_FTRACE ("no lines at %u, pc=%s", idx,
312                         core_addr_to_string_nz (pc));
313           continue;
314         }
315
316       /* Check if we switched files.  This could happen if, say, a macro that
317          is defined in another file is expanded here.  */
318       filename = symtab_to_fullname (sal.symtab);
319       if (ftrace_skip_file (bfun, filename))
320         {
321           DEBUG_FTRACE ("ignoring file at %u, pc=%s, file=%s", idx,
322                         core_addr_to_string_nz (pc), filename);
323           continue;
324         }
325
326       /* Update the line range.  */
327       bfun->lbegin = min (bfun->lbegin, sal.line);
328       bfun->lend = max (bfun->lend, sal.line);
329       ftrace_debug (bfun, "update lines");
330     }
331
332   return ftrace;
333 }
334
335 /* See btrace.h.  */
336
337 void
338 btrace_enable (struct thread_info *tp)
339 {
340   if (tp->btrace.target != NULL)
341     return;
342
343   if (!target_supports_btrace ())
344     error (_("Target does not support branch tracing."));
345
346   DEBUG ("enable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
347
348   tp->btrace.target = target_enable_btrace (tp->ptid);
349 }
350
351 /* See btrace.h.  */
352
353 void
354 btrace_disable (struct thread_info *tp)
355 {
356   struct btrace_thread_info *btp = &tp->btrace;
357   int errcode = 0;
358
359   if (btp->target == NULL)
360     return;
361
362   DEBUG ("disable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
363
364   target_disable_btrace (btp->target);
365   btp->target = NULL;
366
367   btrace_clear (tp);
368 }
369
370 /* See btrace.h.  */
371
372 void
373 btrace_teardown (struct thread_info *tp)
374 {
375   struct btrace_thread_info *btp = &tp->btrace;
376   int errcode = 0;
377
378   if (btp->target == NULL)
379     return;
380
381   DEBUG ("teardown thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
382
383   target_teardown_btrace (btp->target);
384   btp->target = NULL;
385
386   btrace_clear (tp);
387 }
388
389 /* See btrace.h.  */
390
391 void
392 btrace_fetch (struct thread_info *tp)
393 {
394   struct btrace_thread_info *btinfo;
395   VEC (btrace_block_s) *btrace;
396
397   DEBUG ("fetch thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
398
399   btinfo = &tp->btrace;
400   if (btinfo->target == NULL)
401     return;
402
403   btrace = target_read_btrace (btinfo->target, btrace_read_new);
404   if (VEC_empty (btrace_block_s, btrace))
405     return;
406
407   btrace_clear (tp);
408
409   btinfo->btrace = btrace;
410   btinfo->itrace = compute_itrace (btinfo->btrace);
411   btinfo->ftrace = compute_ftrace (btinfo->itrace);
412
413   /* Initialize branch trace iterators.  */
414   btrace_init_insn_iterator (btinfo);
415   btrace_init_func_iterator (btinfo);
416 }
417
418 /* See btrace.h.  */
419
420 void
421 btrace_clear (struct thread_info *tp)
422 {
423   struct btrace_thread_info *btinfo;
424
425   DEBUG ("clear thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
426
427   btinfo = &tp->btrace;
428
429   VEC_free (btrace_block_s, btinfo->btrace);
430   VEC_free (btrace_inst_s, btinfo->itrace);
431   VEC_free (btrace_func_s, btinfo->ftrace);
432
433   btinfo->btrace = NULL;
434   btinfo->itrace = NULL;
435   btinfo->ftrace = NULL;
436 }
437
438 /* See btrace.h.  */
439
440 void
441 btrace_free_objfile (struct objfile *objfile)
442 {
443   struct thread_info *tp;
444
445   DEBUG ("free objfile");
446
447   ALL_THREADS (tp)
448     btrace_clear (tp);
449 }