blob: 190e880c228b01dff3abec0e934fa4ebf3f3f3fd [file] [log] [blame]
Damjan Marion78925602024-05-23 13:06:39 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2024 Cisco Systems, Inc.
3 */
4
5#define _GNU_SOURCE
6#include <dlfcn.h>
7
8#include <vppinfra/clib.h>
9#include <vppinfra/stack.h>
10#include <vppinfra/error.h>
11
12#if HAVE_LIBUNWIND == 1
13
14#define UNW_LOCAL_ONLY
15#include <libunwind.h>
16
17static __thread unw_cursor_t cursor;
18static __thread unw_context_t context;
19
20#endif
21
22__clib_export clib_stack_frame_t *
23clib_stack_frame_get (clib_stack_frame_t *sf)
24{
25#if HAVE_LIBUNWIND == 1
26 Dl_info info = {};
27
28 if (sf->index == 0)
29 {
30 if (unw_getcontext (&context) < 0)
31 {
32 clib_warning ("libunwind: cannot get local machine state\n");
33 return 0;
34 }
35 if (unw_init_local (&cursor, &context) < 0)
36 {
37 clib_warning (
38 "libunwind: cannot initialize cursor for local unwinding\n");
39 return 0;
40 }
41 if (unw_step (&cursor) < 1)
42 return 0;
43 }
44 else if (unw_step (&cursor) < 1)
45 return 0;
46
47 if (unw_get_reg (&cursor, UNW_REG_IP, &sf->ip))
48 {
49 clib_warning ("libunwind: cannot read IP\n");
50 return 0;
51 }
52
53 if (unw_get_reg (&cursor, UNW_REG_SP, &sf->sp))
54 {
55 clib_warning ("libunwind: cannot read SP\n");
56 return 0;
57 }
58
59 if (unw_get_proc_name (&cursor, sf->name, sizeof (sf->name), &sf->offset) <
60 0)
61 sf->name[0] = sf->offset = 0;
62
63 sf->is_signal_frame = unw_is_signal_frame (&cursor) ? 1 : 0;
64
65 if (dladdr ((void *) sf->ip, &info))
66 sf->file_name = info.dli_fname;
67 else
68 sf->file_name = 0;
69
70 sf->index++;
71 return sf;
72#else
73 return 0;
74#endif
75}