~ubuntu-branches/debian/experimental/linux-tools/experimental

« back to all changes in this revision

Viewing changes to tools/perf/util/unwind.c

  • Committer: Package Import Robot
  • Author(s): Ben Hutchings
  • Date: 2014-02-02 16:57:49 UTC
  • mfrom: (1.1.10) (0.1.21 sid)
  • Revision ID: package-import@ubuntu.com-20140202165749-tw94o9t1t0a8txk6
Tags: 3.13-1~exp2
Merge changes from sid up to 3.12.6-3

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
 
40
40
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
41
41
 
 
42
extern int
 
43
UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
 
44
                                 unw_word_t ip,
 
45
                                 unw_word_t segbase,
 
46
                                 const char *obj_name, unw_word_t start,
 
47
                                 unw_word_t end);
 
48
 
 
49
#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
 
50
 
42
51
#define DW_EH_PE_FORMAT_MASK    0x0f    /* format of the encoded value */
43
52
#define DW_EH_PE_APPL_MASK      0x70    /* how the value is to be applied */
44
53
 
245
254
        return 0;
246
255
}
247
256
 
248
 
static int read_unwind_spec(struct dso *dso, struct machine *machine,
249
 
                            u64 *table_data, u64 *segbase, u64 *fde_count)
 
257
static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
 
258
                                     u64 *table_data, u64 *segbase,
 
259
                                     u64 *fde_count)
250
260
{
251
261
        int ret = -EINVAL, fd;
252
262
        u64 offset;
255
265
        if (fd < 0)
256
266
                return -EINVAL;
257
267
 
 
268
        /* Check the .eh_frame section for unwinding info */
258
269
        offset = elf_section_offset(fd, ".eh_frame_hdr");
259
270
        close(fd);
260
271
 
263
274
                                          table_data, segbase,
264
275
                                          fde_count);
265
276
 
266
 
        /* TODO .debug_frame check if eh_frame_hdr fails */
267
277
        return ret;
268
278
}
269
279
 
 
280
#ifndef NO_LIBUNWIND_DEBUG_FRAME
 
281
static int read_unwind_spec_debug_frame(struct dso *dso,
 
282
                                        struct machine *machine, u64 *offset)
 
283
{
 
284
        int fd = dso__data_fd(dso, machine);
 
285
 
 
286
        if (fd < 0)
 
287
                return -EINVAL;
 
288
 
 
289
        /* Check the .debug_frame section for unwinding info */
 
290
        *offset = elf_section_offset(fd, ".debug_frame");
 
291
        close(fd);
 
292
 
 
293
        if (*offset)
 
294
                return 0;
 
295
 
 
296
        return -EINVAL;
 
297
}
 
298
#endif
 
299
 
270
300
static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
271
301
{
272
302
        struct addr_location al;
291
321
 
292
322
        pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
293
323
 
294
 
        if (read_unwind_spec(map->dso, ui->machine,
295
 
                             &table_data, &segbase, &fde_count))
296
 
                return -EINVAL;
297
 
 
298
 
        memset(&di, 0, sizeof(di));
299
 
        di.format   = UNW_INFO_FORMAT_REMOTE_TABLE;
300
 
        di.start_ip = map->start;
301
 
        di.end_ip   = map->end;
302
 
        di.u.rti.segbase    = map->start + segbase;
303
 
        di.u.rti.table_data = map->start + table_data;
304
 
        di.u.rti.table_len  = fde_count * sizeof(struct table_entry)
305
 
                              / sizeof(unw_word_t);
306
 
        return dwarf_search_unwind_table(as, ip, &di, pi,
307
 
                                         need_unwind_info, arg);
 
324
        /* Check the .eh_frame section for unwinding info */
 
325
        if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
 
326
                                       &table_data, &segbase, &fde_count)) {
 
327
                memset(&di, 0, sizeof(di));
 
328
                di.format   = UNW_INFO_FORMAT_REMOTE_TABLE;
 
329
                di.start_ip = map->start;
 
330
                di.end_ip   = map->end;
 
331
                di.u.rti.segbase    = map->start + segbase;
 
332
                di.u.rti.table_data = map->start + table_data;
 
333
                di.u.rti.table_len  = fde_count * sizeof(struct table_entry)
 
334
                                      / sizeof(unw_word_t);
 
335
                return dwarf_search_unwind_table(as, ip, &di, pi,
 
336
                                                 need_unwind_info, arg);
 
337
        }
 
338
 
 
339
#ifndef NO_LIBUNWIND_DEBUG_FRAME
 
340
        /* Check the .debug_frame section for unwinding info */
 
341
        if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
 
342
                memset(&di, 0, sizeof(di));
 
343
                dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name,
 
344
                                       map->start, map->end);
 
345
                return dwarf_search_unwind_table(as, ip, &di, pi,
 
346
                                                 need_unwind_info, arg);
 
347
        }
 
348
#endif
 
349
 
 
350
        return -EINVAL;
308
351
}
309
352
 
310
353
static int access_fpreg(unw_addr_space_t __maybe_unused as,
516
559
};
517
560
 
518
561
static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
519
 
                       void *arg)
 
562
                       void *arg, int max_stack)
520
563
{
521
564
        unw_addr_space_t addr_space;
522
565
        unw_cursor_t c;
532
575
        if (ret)
533
576
                display_error(ret);
534
577
 
535
 
        while (!ret && (unw_step(&c) > 0)) {
 
578
        while (!ret && (unw_step(&c) > 0) && max_stack--) {
536
579
                unw_word_t ip;
537
580
 
538
581
                unw_get_reg(&c, UNW_REG_IP, &ip);
545
588
 
546
589
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
547
590
                        struct machine *machine, struct thread *thread,
548
 
                        u64 sample_uregs, struct perf_sample *data)
 
591
                        u64 sample_uregs, struct perf_sample *data,
 
592
                        int max_stack)
549
593
{
550
594
        unw_word_t ip;
551
595
        struct unwind_info ui = {
567
611
        if (ret)
568
612
                return -ENOMEM;
569
613
 
570
 
        return get_entries(&ui, cb, arg);
 
614
        return get_entries(&ui, cb, arg, max_stack);
571
615
}