Coverage Report

Created: 2025-07-11 06:40

/src/varnish-cache/lib/libvarnish/vbt.c
Line
Count
Source (jump to first uncovered line)
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2022 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 * Author: Guillaume Quintard <guillaume@varnish-software.com>
8
 * Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 *
31
 * We tend to print back-traces when there is a fatal error, so the VBT code
32
 * should avoid assertions.
33
 */
34
35
#include "config.h"
36
37
#include <stdlib.h>
38
#include <stdio.h>
39
#include <string.h>
40
41
#ifdef WITH_UNWIND
42
#  include <libunwind.h>
43
#endif
44
45
#ifdef HAVE_EXECINFO_H
46
#  include <execinfo.h>
47
#endif
48
49
#include "vdef.h"
50
#include "vas.h"
51
#include "vbt.h"
52
#include "vsb.h"
53
54
#include "miniobj.h"
55
56
#ifdef WITH_UNWIND
57
static int
58
vbt_unwind(struct vsb *vsb)
59
{
60
  unw_cursor_t cursor; unw_context_t uc;
61
  unw_word_t ip, sp;
62
  unw_word_t offp;
63
  char fname[1024];
64
  const char *sep;
65
  int ret;
66
67
  ret = unw_getcontext(&uc);
68
  if (ret != 0) {
69
    VSB_printf(vsb, "Backtrace not available "
70
        "(unw_getcontext returned %d)\n", ret);
71
    return (-1);
72
  }
73
  ret = unw_init_local(&cursor, &uc);
74
  if (ret != 0) {
75
    VSB_printf(vsb, "Backtrace not available "
76
        "(unw_init_local returned %d)\n", ret);
77
    return (-1);
78
  }
79
  while (unw_step(&cursor) > 0) {
80
    fname[0] = '\0';
81
    sep = "";
82
    if (!unw_get_reg(&cursor, UNW_REG_IP, &ip)) {
83
      VSB_printf(vsb, "ip=0x%lx", (long) ip);
84
      sep = " ";
85
    }
86
    if (!unw_get_reg(&cursor, UNW_REG_SP, &sp)) {
87
      VSB_printf(vsb, "%ssp=0x%lx", sep, (long) sp);
88
      sep = " ";
89
    }
90
    if (!unw_get_proc_name(&cursor, fname, sizeof(fname), &offp)) {
91
      VSB_printf(vsb, "%s<%s+0x%lx>",
92
          sep, fname[0] ? fname : "<unknown>", (long)offp);
93
    }
94
    VSB_putc(vsb, '\n');
95
  }
96
97
  return (0);
98
}
99
#endif
100
101
#ifdef HAVE_EXECINFO_H
102
0
#  define BACKTRACE_LEVELS  20
103
104
static void
105
vbt_execinfo(struct vsb *vsb)
106
0
{
107
0
  void *array[BACKTRACE_LEVELS];
108
0
  size_t size;
109
0
  size_t i;
110
0
  char **strings;
111
0
  char *p;
112
0
  char buf[32];
113
114
0
  size = backtrace (array, BACKTRACE_LEVELS);
115
0
  if (size > BACKTRACE_LEVELS) {
116
0
    VSB_printf(vsb, "Backtrace not available (ret=%zu)\n", size);
117
0
    return;
118
0
  }
119
0
  for (i = 0; i < size; i++) {
120
0
    bprintf(buf, "%p", array[i]);
121
0
    VSB_printf(vsb, "%s: ", buf);
122
0
    strings = backtrace_symbols(&array[i], 1);
123
0
    if (strings == NULL || strings[0] == NULL) {
124
0
      VSB_cat(vsb, "(?)");
125
0
    } else {
126
0
      p = strings[0];
127
0
      if (!memcmp(buf, p, strlen(buf))) {
128
0
        p += strlen(buf);
129
0
        if (*p == ':')
130
0
          p++;
131
0
        while (*p == ' ')
132
0
          p++;
133
0
      }
134
0
      VSB_cat(vsb, p);
135
0
    }
136
0
    VSB_cat(vsb, "\n");
137
0
    free(strings);
138
0
  }
139
0
}
140
#endif
141
142
void
143
VBT_format(struct vsb *vsb)
144
0
{
145
146
0
  if (!VALID_OBJ(vsb, VSB_MAGIC))
147
0
    return;
148
#ifdef WITH_UNWIND
149
  if (!vbt_unwind(vsb))
150
    return;
151
#  ifdef HAVE_EXECINFO_H
152
  VSB_cat(vsb, "Falling back to execinfo backtrace\n");
153
#  endif
154
#endif
155
156
0
#ifdef HAVE_EXECINFO_H
157
0
  vbt_execinfo(vsb);
158
0
#endif
159
0
}
160
161
int
162
VBT_dump(size_t len, char buf[len])
163
0
{
164
0
  struct vsb vsb[1];
165
166
0
  if (VSB_init(vsb, buf, len) == NULL)
167
0
    return (-1);
168
169
0
  VSB_printf(vsb, "Backtrace:\n");
170
0
  VSB_indent(vsb, 2);
171
0
  VBT_format(vsb);
172
0
  VSB_indent(vsb, -2);
173
174
0
  return (0);
175
0
}