LDMX Software
Exception.cxx
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/types.h>
5#include <sys/wait.h>
6#include <unistd.h>
7
10static char *addr2line(const char *image, void *addr, bool color_output) {
11 static char exename[4096] = {0};
12 static char result[4096] = {0};
13
14 if (exename[0] == 0) {
15 int ret = readlink("/proc/self/exe", exename, 4095);
16 if (ret == -1) {
17 exename[0] = 0;
18 return result;
19 }
20 exename[ret] = 0;
21 }
22
23 int pipefd[2];
24 if (pipe(pipefd) != 0) {
25 return result;
26 }
27 pid_t pid = fork();
28 if (pid == 0) {
29 close(pipefd[0]);
30 dup2(pipefd[1], STDOUT_FILENO);
31 dup2(pipefd[1], STDERR_FILENO);
32 if (execlp("addr2line", "addr2line", exename, "-f", "-C", "-e", image,
33 reinterpret_cast<void *>(NULL)) == -1) {
34 exit(0);
35 }
36 }
37
38 close(pipefd[1]);
39 const int line_max_length = 4096;
40 char *line = result;
41 ssize_t len = read(pipefd[0], line, line_max_length);
42 close(pipefd[0]);
43 if (len == 0) {
44 return result;
45 }
46 line[len] = 0;
47
48 if (waitpid(pid, NULL, 0) != pid) {
49 return result;
50 }
51 if (line[0] == '?') {
52 line[0] = 0;
53 return line;
54 // char* straddr = Safe::ptoa(addr, *memory);
55 if (color_output) {
56 strcpy(line, "\033[32;1m"); // NOLINT(runtime/printf)
57 }
58 // strcat(line, straddr); // NOLINT(runtime/printf)
59 if (color_output) {
60 strcat(line, "\033[0m"); // NOLINT(runtime/printf)
61 }
62 strcat(line, " at "); // NOLINT(runtime/printf)
63 strcat(line, image); // NOLINT(runtime/printf)
64 strcat(line, " "); // NOLINT(runtime/printf)
65 } else {
66 if (*(strstr(line, "\n") + 1) == '?') {
67 // char* straddr = Safe::ptoa(addr, *memory);
68 strcpy(strstr(line, "\n") + 1, image); // NOLINT(runtime/printf)
69 strcat(line, ":"); // NOLINT(runtime/printf)
70 // strcat(line, straddr); // NOLINT(runtime/printf)
71 // strcat(line, "\n"); // NOLINT(runtime/printf)
72 }
73 }
74 return line;
75}
76
77/*
78 * Copyright (c) 2009-2017, Farooq Mela
79 * All rights reserved.
80 *
81 * Redistribution and use in source and binary forms, with or without
82 * modification, are permitted provided that the following conditions are met:
83 *
84 * 1. Redistributions of source code must retain the above copyright
85 * notice, this list of conditions and the following disclaimer.
86 * 2. Redistributions in binary form must reproduce the above copyright
87 * notice, this list of conditions and the following disclaimer in the
88 * documentation and/or other materials provided with the distribution.
89 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
90 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
91 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
92 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
93 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
94 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
95 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
96 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
97 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
98 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
99 * POSSIBILITY OF SUCH DAMAGE.
100 */
101
102#include <cxxabi.h> // for __cxa_demangle
103#include <dlfcn.h> // for dladdr
104#include <execinfo.h> // for backtrace
105
106#include <cstdio>
107#include <cstdlib>
108#include <sstream>
109#include <string>
110
111// This function produces a stack backtrace with demangled function & method
112// names.
113static std::string Backtrace(int skip = 1) throw() {
114 void *callstack[128];
115 const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
116 char buf[1024];
117 int nFrames = backtrace(callstack, nMaxFrames);
118 char **symbols = backtrace_symbols(callstack, nFrames);
119
120 std::ostringstream trace_buf;
121 for (int i = skip; i < nFrames - 2; i++) {
122 // printf("%s\n", symbols[i]);
123
124 Dl_info info;
125 if (dladdr(callstack[i], &info) && info.dli_sname) {
126 char *demangled = NULL;
127 int status = -1;
128 if (info.dli_sname[0] == '_')
129 demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status);
130 char *line = addr2line(info.dli_fname, callstack[i], false);
131
132 snprintf(buf, sizeof(buf), "%5d %s + %zd %s\n",
133 i - skip, // int(2 + sizeof(void*) * 2), callstack[i],
134 status == 0 ? demangled
135 : info.dli_sname == 0 ? symbols[i]
136 : info.dli_sname,
137 (char *)callstack[i] - (char *)info.dli_saddr, line);
138
139 free(demangled);
140 } else {
141 snprintf(buf, sizeof(buf), "%5d %s\n",
142 i - skip, // int(2 + sizeof(void*) * 2), callstack[i],
143 symbols[i]);
144 }
145 trace_buf << buf;
146 }
147 free(symbols);
148 if (nFrames == nMaxFrames) trace_buf << "[truncated]\n";
149 return trace_buf.str();
150}
151
152#include "Framework/Exception/Exception.h"
153
154namespace framework {
155namespace exception {
156void Exception::buildStackTrace() throw() { stackTrace_ = Backtrace(2); }
157} // namespace exception
158} // namespace framework
std::string stackTrace_
The stack trace.
Definition Exception.h:112
All classes in the ldmx-sw project use this namespace.
Definition PerfDict.cxx:45