1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // crash_handler_posix:
7*8975f5c5SAndroid Build Coastguard Worker // ANGLE's crash handling and stack walking code. Modified from Skia's:
8*8975f5c5SAndroid Build Coastguard Worker // https://github.com/google/skia/blob/master/tools/CrashHandler.cpp
9*8975f5c5SAndroid Build Coastguard Worker //
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include "util/test_utils.h"
12*8975f5c5SAndroid Build Coastguard Worker
13*8975f5c5SAndroid Build Coastguard Worker #include "common/FixedVector.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "common/angleutils.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker #include <fcntl.h>
19*8975f5c5SAndroid Build Coastguard Worker #include <inttypes.h>
20*8975f5c5SAndroid Build Coastguard Worker #include <stdio.h>
21*8975f5c5SAndroid Build Coastguard Worker #include <stdlib.h>
22*8975f5c5SAndroid Build Coastguard Worker #include <sys/types.h>
23*8975f5c5SAndroid Build Coastguard Worker #include <sys/wait.h>
24*8975f5c5SAndroid Build Coastguard Worker #include <unistd.h>
25*8975f5c5SAndroid Build Coastguard Worker #include <iostream>
26*8975f5c5SAndroid Build Coastguard Worker
27*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA)
28*8975f5c5SAndroid Build Coastguard Worker # if defined(ANGLE_PLATFORM_APPLE)
29*8975f5c5SAndroid Build Coastguard Worker // We only use local unwinding, so we can define this to select a faster implementation.
30*8975f5c5SAndroid Build Coastguard Worker # define UNW_LOCAL_ONLY
31*8975f5c5SAndroid Build Coastguard Worker # include <cxxabi.h>
32*8975f5c5SAndroid Build Coastguard Worker # include <libunwind.h>
33*8975f5c5SAndroid Build Coastguard Worker # include <signal.h>
34*8975f5c5SAndroid Build Coastguard Worker # elif defined(ANGLE_PLATFORM_POSIX)
35*8975f5c5SAndroid Build Coastguard Worker // We'd use libunwind here too, but it's a pain to get installed for
36*8975f5c5SAndroid Build Coastguard Worker // both 32 and 64 bit on bots. Doesn't matter much: catchsegv is best anyway.
37*8975f5c5SAndroid Build Coastguard Worker # include <cxxabi.h>
38*8975f5c5SAndroid Build Coastguard Worker # include <dlfcn.h>
39*8975f5c5SAndroid Build Coastguard Worker # include <execinfo.h>
40*8975f5c5SAndroid Build Coastguard Worker # include <libgen.h>
41*8975f5c5SAndroid Build Coastguard Worker # include <link.h>
42*8975f5c5SAndroid Build Coastguard Worker # include <signal.h>
43*8975f5c5SAndroid Build Coastguard Worker # include <string.h>
44*8975f5c5SAndroid Build Coastguard Worker # endif // defined(ANGLE_PLATFORM_APPLE)
45*8975f5c5SAndroid Build Coastguard Worker #endif // !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA)
46*8975f5c5SAndroid Build Coastguard Worker
47*8975f5c5SAndroid Build Coastguard Worker // This code snippet is coped from Chromium's base/posix/eintr_wrapper.h.
48*8975f5c5SAndroid Build Coastguard Worker #if defined(NDEBUG)
49*8975f5c5SAndroid Build Coastguard Worker # define HANDLE_EINTR(x) \
50*8975f5c5SAndroid Build Coastguard Worker ({ \
51*8975f5c5SAndroid Build Coastguard Worker decltype(x) eintr_wrapper_result; \
52*8975f5c5SAndroid Build Coastguard Worker do \
53*8975f5c5SAndroid Build Coastguard Worker { \
54*8975f5c5SAndroid Build Coastguard Worker eintr_wrapper_result = (x); \
55*8975f5c5SAndroid Build Coastguard Worker } while (eintr_wrapper_result == -1 && errno == EINTR); \
56*8975f5c5SAndroid Build Coastguard Worker eintr_wrapper_result; \
57*8975f5c5SAndroid Build Coastguard Worker })
58*8975f5c5SAndroid Build Coastguard Worker #else
59*8975f5c5SAndroid Build Coastguard Worker # define HANDLE_EINTR(x) \
60*8975f5c5SAndroid Build Coastguard Worker ({ \
61*8975f5c5SAndroid Build Coastguard Worker int eintr_wrapper_counter = 0; \
62*8975f5c5SAndroid Build Coastguard Worker decltype(x) eintr_wrapper_result; \
63*8975f5c5SAndroid Build Coastguard Worker do \
64*8975f5c5SAndroid Build Coastguard Worker { \
65*8975f5c5SAndroid Build Coastguard Worker eintr_wrapper_result = (x); \
66*8975f5c5SAndroid Build Coastguard Worker } while (eintr_wrapper_result == -1 && errno == EINTR && \
67*8975f5c5SAndroid Build Coastguard Worker eintr_wrapper_counter++ < 100); \
68*8975f5c5SAndroid Build Coastguard Worker eintr_wrapper_result; \
69*8975f5c5SAndroid Build Coastguard Worker })
70*8975f5c5SAndroid Build Coastguard Worker #endif // NDEBUG
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker namespace angle
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_FUCHSIA)
75*8975f5c5SAndroid Build Coastguard Worker
PrintStackBacktrace()76*8975f5c5SAndroid Build Coastguard Worker void PrintStackBacktrace()
77*8975f5c5SAndroid Build Coastguard Worker {
78*8975f5c5SAndroid Build Coastguard Worker // No implementations yet.
79*8975f5c5SAndroid Build Coastguard Worker }
80*8975f5c5SAndroid Build Coastguard Worker
InitCrashHandler(CrashCallback * callback)81*8975f5c5SAndroid Build Coastguard Worker void InitCrashHandler(CrashCallback *callback)
82*8975f5c5SAndroid Build Coastguard Worker {
83*8975f5c5SAndroid Build Coastguard Worker // No implementations yet.
84*8975f5c5SAndroid Build Coastguard Worker }
85*8975f5c5SAndroid Build Coastguard Worker
TerminateCrashHandler()86*8975f5c5SAndroid Build Coastguard Worker void TerminateCrashHandler()
87*8975f5c5SAndroid Build Coastguard Worker {
88*8975f5c5SAndroid Build Coastguard Worker // No implementations yet.
89*8975f5c5SAndroid Build Coastguard Worker }
90*8975f5c5SAndroid Build Coastguard Worker
91*8975f5c5SAndroid Build Coastguard Worker #else
92*8975f5c5SAndroid Build Coastguard Worker namespace
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker CrashCallback *gCrashHandlerCallback;
95*8975f5c5SAndroid Build Coastguard Worker } // namespace
96*8975f5c5SAndroid Build Coastguard Worker
97*8975f5c5SAndroid Build Coastguard Worker # if defined(ANGLE_PLATFORM_APPLE)
98*8975f5c5SAndroid Build Coastguard Worker
99*8975f5c5SAndroid Build Coastguard Worker void PrintStackBacktrace()
100*8975f5c5SAndroid Build Coastguard Worker {
101*8975f5c5SAndroid Build Coastguard Worker printf("Backtrace:\n");
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Worker unw_context_t context;
104*8975f5c5SAndroid Build Coastguard Worker unw_getcontext(&context);
105*8975f5c5SAndroid Build Coastguard Worker
106*8975f5c5SAndroid Build Coastguard Worker unw_cursor_t cursor;
107*8975f5c5SAndroid Build Coastguard Worker unw_init_local(&cursor, &context);
108*8975f5c5SAndroid Build Coastguard Worker
109*8975f5c5SAndroid Build Coastguard Worker while (unw_step(&cursor) > 0)
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker static const size_t kMax = 256;
112*8975f5c5SAndroid Build Coastguard Worker char mangled[kMax];
113*8975f5c5SAndroid Build Coastguard Worker unw_word_t offset;
114*8975f5c5SAndroid Build Coastguard Worker unw_get_proc_name(&cursor, mangled, kMax, &offset);
115*8975f5c5SAndroid Build Coastguard Worker
116*8975f5c5SAndroid Build Coastguard Worker int ok = -1;
117*8975f5c5SAndroid Build Coastguard Worker char *demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &ok);
118*8975f5c5SAndroid Build Coastguard Worker printf(" %s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset);
119*8975f5c5SAndroid Build Coastguard Worker if (ok)
120*8975f5c5SAndroid Build Coastguard Worker {
121*8975f5c5SAndroid Build Coastguard Worker free(demangled);
122*8975f5c5SAndroid Build Coastguard Worker }
123*8975f5c5SAndroid Build Coastguard Worker }
124*8975f5c5SAndroid Build Coastguard Worker printf("\n");
125*8975f5c5SAndroid Build Coastguard Worker }
126*8975f5c5SAndroid Build Coastguard Worker
127*8975f5c5SAndroid Build Coastguard Worker static void Handler(int sig)
128*8975f5c5SAndroid Build Coastguard Worker {
129*8975f5c5SAndroid Build Coastguard Worker printf("\nSignal %d:\n", sig);
130*8975f5c5SAndroid Build Coastguard Worker fflush(stdout);
131*8975f5c5SAndroid Build Coastguard Worker
132*8975f5c5SAndroid Build Coastguard Worker if (gCrashHandlerCallback)
133*8975f5c5SAndroid Build Coastguard Worker {
134*8975f5c5SAndroid Build Coastguard Worker (*gCrashHandlerCallback)();
135*8975f5c5SAndroid Build Coastguard Worker }
136*8975f5c5SAndroid Build Coastguard Worker
137*8975f5c5SAndroid Build Coastguard Worker PrintStackBacktrace();
138*8975f5c5SAndroid Build Coastguard Worker fflush(stdout);
139*8975f5c5SAndroid Build Coastguard Worker
140*8975f5c5SAndroid Build Coastguard Worker // Exit NOW. Don't notify other threads, don't call anything registered with atexit().
141*8975f5c5SAndroid Build Coastguard Worker _Exit(sig);
142*8975f5c5SAndroid Build Coastguard Worker }
143*8975f5c5SAndroid Build Coastguard Worker
144*8975f5c5SAndroid Build Coastguard Worker # elif defined(ANGLE_PLATFORM_POSIX)
145*8975f5c5SAndroid Build Coastguard Worker
146*8975f5c5SAndroid Build Coastguard Worker // Can control this at a higher level if required.
147*8975f5c5SAndroid Build Coastguard Worker # define ANGLE_HAS_ADDR2LINE
148*8975f5c5SAndroid Build Coastguard Worker
149*8975f5c5SAndroid Build Coastguard Worker # if defined(ANGLE_HAS_ADDR2LINE)
150*8975f5c5SAndroid Build Coastguard Worker namespace
151*8975f5c5SAndroid Build Coastguard Worker {
152*8975f5c5SAndroid Build Coastguard Worker // The following code was adapted from Chromium's "stack_trace_posix.cc".
153*8975f5c5SAndroid Build Coastguard Worker // Describes a region of mapped memory and the path of the file mapped.
154*8975f5c5SAndroid Build Coastguard Worker struct MappedMemoryRegion
155*8975f5c5SAndroid Build Coastguard Worker {
156*8975f5c5SAndroid Build Coastguard Worker enum Permission
157*8975f5c5SAndroid Build Coastguard Worker {
158*8975f5c5SAndroid Build Coastguard Worker READ = 1 << 0,
159*8975f5c5SAndroid Build Coastguard Worker WRITE = 1 << 1,
160*8975f5c5SAndroid Build Coastguard Worker EXECUTE = 1 << 2,
161*8975f5c5SAndroid Build Coastguard Worker PRIVATE = 1 << 3, // If set, region is private, otherwise it is shared.
162*8975f5c5SAndroid Build Coastguard Worker };
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Worker // The address range [start,end) of mapped memory.
165*8975f5c5SAndroid Build Coastguard Worker uintptr_t start;
166*8975f5c5SAndroid Build Coastguard Worker uintptr_t end;
167*8975f5c5SAndroid Build Coastguard Worker
168*8975f5c5SAndroid Build Coastguard Worker // Byte offset into |path| of the range mapped into memory.
169*8975f5c5SAndroid Build Coastguard Worker unsigned long long offset;
170*8975f5c5SAndroid Build Coastguard Worker
171*8975f5c5SAndroid Build Coastguard Worker // Image base, if this mapping corresponds to an ELF image.
172*8975f5c5SAndroid Build Coastguard Worker uintptr_t base;
173*8975f5c5SAndroid Build Coastguard Worker
174*8975f5c5SAndroid Build Coastguard Worker // Bitmask of read/write/execute/private/shared permissions.
175*8975f5c5SAndroid Build Coastguard Worker uint8_t permissions;
176*8975f5c5SAndroid Build Coastguard Worker
177*8975f5c5SAndroid Build Coastguard Worker // Name of the file mapped into memory.
178*8975f5c5SAndroid Build Coastguard Worker //
179*8975f5c5SAndroid Build Coastguard Worker // NOTE: path names aren't guaranteed to point at valid files. For example,
180*8975f5c5SAndroid Build Coastguard Worker // "[heap]" and "[stack]" are used to represent the location of the process'
181*8975f5c5SAndroid Build Coastguard Worker // heap and stack, respectively.
182*8975f5c5SAndroid Build Coastguard Worker std::string path;
183*8975f5c5SAndroid Build Coastguard Worker };
184*8975f5c5SAndroid Build Coastguard Worker
185*8975f5c5SAndroid Build Coastguard Worker using MemoryRegionArray = std::vector<MappedMemoryRegion>;
186*8975f5c5SAndroid Build Coastguard Worker
187*8975f5c5SAndroid Build Coastguard Worker bool ReadProcMaps(std::string *proc_maps)
188*8975f5c5SAndroid Build Coastguard Worker {
189*8975f5c5SAndroid Build Coastguard Worker // seq_file only writes out a page-sized amount on each call. Refer to header
190*8975f5c5SAndroid Build Coastguard Worker // file for details.
191*8975f5c5SAndroid Build Coastguard Worker const long kReadSize = sysconf(_SC_PAGESIZE);
192*8975f5c5SAndroid Build Coastguard Worker
193*8975f5c5SAndroid Build Coastguard Worker int fd(HANDLE_EINTR(open("/proc/self/maps", O_RDONLY)));
194*8975f5c5SAndroid Build Coastguard Worker if (fd == -1)
195*8975f5c5SAndroid Build Coastguard Worker {
196*8975f5c5SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't open /proc/self/maps\n");
197*8975f5c5SAndroid Build Coastguard Worker return false;
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker proc_maps->clear();
200*8975f5c5SAndroid Build Coastguard Worker
201*8975f5c5SAndroid Build Coastguard Worker while (true)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker // To avoid a copy, resize |proc_maps| so read() can write directly into it.
204*8975f5c5SAndroid Build Coastguard Worker // Compute |buffer| afterwards since resize() may reallocate.
205*8975f5c5SAndroid Build Coastguard Worker size_t pos = proc_maps->size();
206*8975f5c5SAndroid Build Coastguard Worker proc_maps->resize(pos + kReadSize);
207*8975f5c5SAndroid Build Coastguard Worker void *buffer = &(*proc_maps)[pos];
208*8975f5c5SAndroid Build Coastguard Worker
209*8975f5c5SAndroid Build Coastguard Worker ssize_t bytes_read = HANDLE_EINTR(read(fd, buffer, kReadSize));
210*8975f5c5SAndroid Build Coastguard Worker if (bytes_read < 0)
211*8975f5c5SAndroid Build Coastguard Worker {
212*8975f5c5SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't read /proc/self/maps\n");
213*8975f5c5SAndroid Build Coastguard Worker proc_maps->clear();
214*8975f5c5SAndroid Build Coastguard Worker close(fd);
215*8975f5c5SAndroid Build Coastguard Worker return false;
216*8975f5c5SAndroid Build Coastguard Worker }
217*8975f5c5SAndroid Build Coastguard Worker
218*8975f5c5SAndroid Build Coastguard Worker // ... and don't forget to trim off excess bytes.
219*8975f5c5SAndroid Build Coastguard Worker proc_maps->resize(pos + bytes_read);
220*8975f5c5SAndroid Build Coastguard Worker
221*8975f5c5SAndroid Build Coastguard Worker if (bytes_read == 0)
222*8975f5c5SAndroid Build Coastguard Worker break;
223*8975f5c5SAndroid Build Coastguard Worker }
224*8975f5c5SAndroid Build Coastguard Worker
225*8975f5c5SAndroid Build Coastguard Worker close(fd);
226*8975f5c5SAndroid Build Coastguard Worker return true;
227*8975f5c5SAndroid Build Coastguard Worker }
228*8975f5c5SAndroid Build Coastguard Worker
229*8975f5c5SAndroid Build Coastguard Worker bool ParseProcMaps(const std::string &input, MemoryRegionArray *regions_out)
230*8975f5c5SAndroid Build Coastguard Worker {
231*8975f5c5SAndroid Build Coastguard Worker ASSERT(regions_out);
232*8975f5c5SAndroid Build Coastguard Worker MemoryRegionArray regions;
233*8975f5c5SAndroid Build Coastguard Worker
234*8975f5c5SAndroid Build Coastguard Worker // This isn't async safe nor terribly efficient, but it doesn't need to be at
235*8975f5c5SAndroid Build Coastguard Worker // this point in time.
236*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> lines = SplitString(input, "\n", TRIM_WHITESPACE, SPLIT_WANT_ALL);
237*8975f5c5SAndroid Build Coastguard Worker
238*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < lines.size(); ++i)
239*8975f5c5SAndroid Build Coastguard Worker {
240*8975f5c5SAndroid Build Coastguard Worker // Due to splitting on '\n' the last line should be empty.
241*8975f5c5SAndroid Build Coastguard Worker if (i == lines.size() - 1)
242*8975f5c5SAndroid Build Coastguard Worker {
243*8975f5c5SAndroid Build Coastguard Worker if (!lines[i].empty())
244*8975f5c5SAndroid Build Coastguard Worker {
245*8975f5c5SAndroid Build Coastguard Worker fprintf(stderr, "ParseProcMaps: Last line not empty");
246*8975f5c5SAndroid Build Coastguard Worker return false;
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker break;
249*8975f5c5SAndroid Build Coastguard Worker }
250*8975f5c5SAndroid Build Coastguard Worker
251*8975f5c5SAndroid Build Coastguard Worker MappedMemoryRegion region;
252*8975f5c5SAndroid Build Coastguard Worker const char *line = lines[i].c_str();
253*8975f5c5SAndroid Build Coastguard Worker char permissions[5] = {'\0'}; // Ensure NUL-terminated string.
254*8975f5c5SAndroid Build Coastguard Worker uint8_t dev_major = 0;
255*8975f5c5SAndroid Build Coastguard Worker uint8_t dev_minor = 0;
256*8975f5c5SAndroid Build Coastguard Worker long inode = 0;
257*8975f5c5SAndroid Build Coastguard Worker int path_index = 0;
258*8975f5c5SAndroid Build Coastguard Worker
259*8975f5c5SAndroid Build Coastguard Worker // Sample format from man 5 proc:
260*8975f5c5SAndroid Build Coastguard Worker //
261*8975f5c5SAndroid Build Coastguard Worker // address perms offset dev inode pathname
262*8975f5c5SAndroid Build Coastguard Worker // 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
263*8975f5c5SAndroid Build Coastguard Worker //
264*8975f5c5SAndroid Build Coastguard Worker // The final %n term captures the offset in the input string, which is used
265*8975f5c5SAndroid Build Coastguard Worker // to determine the path name. It *does not* increment the return value.
266*8975f5c5SAndroid Build Coastguard Worker // Refer to man 3 sscanf for details.
267*8975f5c5SAndroid Build Coastguard Worker if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4c %llx %hhx:%hhx %ld %n", ®ion.start,
268*8975f5c5SAndroid Build Coastguard Worker ®ion.end, permissions, ®ion.offset, &dev_major, &dev_minor, &inode,
269*8975f5c5SAndroid Build Coastguard Worker &path_index) < 7)
270*8975f5c5SAndroid Build Coastguard Worker {
271*8975f5c5SAndroid Build Coastguard Worker fprintf(stderr, "ParseProcMaps: sscanf failed for line: %s\n", line);
272*8975f5c5SAndroid Build Coastguard Worker return false;
273*8975f5c5SAndroid Build Coastguard Worker }
274*8975f5c5SAndroid Build Coastguard Worker
275*8975f5c5SAndroid Build Coastguard Worker region.permissions = 0;
276*8975f5c5SAndroid Build Coastguard Worker
277*8975f5c5SAndroid Build Coastguard Worker if (permissions[0] == 'r')
278*8975f5c5SAndroid Build Coastguard Worker region.permissions |= MappedMemoryRegion::READ;
279*8975f5c5SAndroid Build Coastguard Worker else if (permissions[0] != '-')
280*8975f5c5SAndroid Build Coastguard Worker return false;
281*8975f5c5SAndroid Build Coastguard Worker
282*8975f5c5SAndroid Build Coastguard Worker if (permissions[1] == 'w')
283*8975f5c5SAndroid Build Coastguard Worker region.permissions |= MappedMemoryRegion::WRITE;
284*8975f5c5SAndroid Build Coastguard Worker else if (permissions[1] != '-')
285*8975f5c5SAndroid Build Coastguard Worker return false;
286*8975f5c5SAndroid Build Coastguard Worker
287*8975f5c5SAndroid Build Coastguard Worker if (permissions[2] == 'x')
288*8975f5c5SAndroid Build Coastguard Worker region.permissions |= MappedMemoryRegion::EXECUTE;
289*8975f5c5SAndroid Build Coastguard Worker else if (permissions[2] != '-')
290*8975f5c5SAndroid Build Coastguard Worker return false;
291*8975f5c5SAndroid Build Coastguard Worker
292*8975f5c5SAndroid Build Coastguard Worker if (permissions[3] == 'p')
293*8975f5c5SAndroid Build Coastguard Worker region.permissions |= MappedMemoryRegion::PRIVATE;
294*8975f5c5SAndroid Build Coastguard Worker else if (permissions[3] != 's' && permissions[3] != 'S') // Shared memory.
295*8975f5c5SAndroid Build Coastguard Worker return false;
296*8975f5c5SAndroid Build Coastguard Worker
297*8975f5c5SAndroid Build Coastguard Worker // Pushing then assigning saves us a string copy.
298*8975f5c5SAndroid Build Coastguard Worker regions.push_back(region);
299*8975f5c5SAndroid Build Coastguard Worker regions.back().path.assign(line + path_index);
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker
302*8975f5c5SAndroid Build Coastguard Worker regions_out->swap(regions);
303*8975f5c5SAndroid Build Coastguard Worker return true;
304*8975f5c5SAndroid Build Coastguard Worker }
305*8975f5c5SAndroid Build Coastguard Worker
306*8975f5c5SAndroid Build Coastguard Worker // Set the base address for each memory region by reading ELF headers in
307*8975f5c5SAndroid Build Coastguard Worker // process memory.
308*8975f5c5SAndroid Build Coastguard Worker void SetBaseAddressesForMemoryRegions(MemoryRegionArray ®ions)
309*8975f5c5SAndroid Build Coastguard Worker {
310*8975f5c5SAndroid Build Coastguard Worker int mem_fd(HANDLE_EINTR(open("/proc/self/mem", O_RDONLY | O_CLOEXEC)));
311*8975f5c5SAndroid Build Coastguard Worker if (mem_fd == -1)
312*8975f5c5SAndroid Build Coastguard Worker return;
313*8975f5c5SAndroid Build Coastguard Worker
314*8975f5c5SAndroid Build Coastguard Worker auto safe_memcpy = [&mem_fd](void *dst, uintptr_t src, size_t size) {
315*8975f5c5SAndroid Build Coastguard Worker return HANDLE_EINTR(pread(mem_fd, dst, size, src)) == ssize_t(size);
316*8975f5c5SAndroid Build Coastguard Worker };
317*8975f5c5SAndroid Build Coastguard Worker
318*8975f5c5SAndroid Build Coastguard Worker uintptr_t cur_base = 0;
319*8975f5c5SAndroid Build Coastguard Worker for (MappedMemoryRegion &r : regions)
320*8975f5c5SAndroid Build Coastguard Worker {
321*8975f5c5SAndroid Build Coastguard Worker ElfW(Ehdr) ehdr;
322*8975f5c5SAndroid Build Coastguard Worker static_assert(SELFMAG <= sizeof(ElfW(Ehdr)), "SELFMAG too large");
323*8975f5c5SAndroid Build Coastguard Worker if ((r.permissions & MappedMemoryRegion::READ) &&
324*8975f5c5SAndroid Build Coastguard Worker safe_memcpy(&ehdr, r.start, sizeof(ElfW(Ehdr))) &&
325*8975f5c5SAndroid Build Coastguard Worker memcmp(ehdr.e_ident, ELFMAG, SELFMAG) == 0)
326*8975f5c5SAndroid Build Coastguard Worker {
327*8975f5c5SAndroid Build Coastguard Worker switch (ehdr.e_type)
328*8975f5c5SAndroid Build Coastguard Worker {
329*8975f5c5SAndroid Build Coastguard Worker case ET_EXEC:
330*8975f5c5SAndroid Build Coastguard Worker cur_base = 0;
331*8975f5c5SAndroid Build Coastguard Worker break;
332*8975f5c5SAndroid Build Coastguard Worker case ET_DYN:
333*8975f5c5SAndroid Build Coastguard Worker // Find the segment containing file offset 0. This will correspond
334*8975f5c5SAndroid Build Coastguard Worker // to the ELF header that we just read. Normally this will have
335*8975f5c5SAndroid Build Coastguard Worker // virtual address 0, but this is not guaranteed. We must subtract
336*8975f5c5SAndroid Build Coastguard Worker // the virtual address from the address where the ELF header was
337*8975f5c5SAndroid Build Coastguard Worker // mapped to get the base address.
338*8975f5c5SAndroid Build Coastguard Worker //
339*8975f5c5SAndroid Build Coastguard Worker // If we fail to find a segment for file offset 0, use the address
340*8975f5c5SAndroid Build Coastguard Worker // of the ELF header as the base address.
341*8975f5c5SAndroid Build Coastguard Worker cur_base = r.start;
342*8975f5c5SAndroid Build Coastguard Worker for (unsigned i = 0; i != ehdr.e_phnum; ++i)
343*8975f5c5SAndroid Build Coastguard Worker {
344*8975f5c5SAndroid Build Coastguard Worker ElfW(Phdr) phdr;
345*8975f5c5SAndroid Build Coastguard Worker if (safe_memcpy(&phdr, r.start + ehdr.e_phoff + i * sizeof(phdr),
346*8975f5c5SAndroid Build Coastguard Worker sizeof(phdr)) &&
347*8975f5c5SAndroid Build Coastguard Worker phdr.p_type == PT_LOAD && phdr.p_offset == 0)
348*8975f5c5SAndroid Build Coastguard Worker {
349*8975f5c5SAndroid Build Coastguard Worker cur_base = r.start - phdr.p_vaddr;
350*8975f5c5SAndroid Build Coastguard Worker break;
351*8975f5c5SAndroid Build Coastguard Worker }
352*8975f5c5SAndroid Build Coastguard Worker }
353*8975f5c5SAndroid Build Coastguard Worker break;
354*8975f5c5SAndroid Build Coastguard Worker default:
355*8975f5c5SAndroid Build Coastguard Worker // ET_REL or ET_CORE. These aren't directly executable, so they
356*8975f5c5SAndroid Build Coastguard Worker // don't affect the base address.
357*8975f5c5SAndroid Build Coastguard Worker break;
358*8975f5c5SAndroid Build Coastguard Worker }
359*8975f5c5SAndroid Build Coastguard Worker }
360*8975f5c5SAndroid Build Coastguard Worker
361*8975f5c5SAndroid Build Coastguard Worker r.base = cur_base;
362*8975f5c5SAndroid Build Coastguard Worker }
363*8975f5c5SAndroid Build Coastguard Worker
364*8975f5c5SAndroid Build Coastguard Worker close(mem_fd);
365*8975f5c5SAndroid Build Coastguard Worker }
366*8975f5c5SAndroid Build Coastguard Worker
367*8975f5c5SAndroid Build Coastguard Worker // Parses /proc/self/maps in order to compile a list of all object file names
368*8975f5c5SAndroid Build Coastguard Worker // for the modules that are loaded in the current process.
369*8975f5c5SAndroid Build Coastguard Worker // Returns true on success.
370*8975f5c5SAndroid Build Coastguard Worker bool CacheMemoryRegions(MemoryRegionArray ®ions)
371*8975f5c5SAndroid Build Coastguard Worker {
372*8975f5c5SAndroid Build Coastguard Worker // Reads /proc/self/maps.
373*8975f5c5SAndroid Build Coastguard Worker std::string contents;
374*8975f5c5SAndroid Build Coastguard Worker if (!ReadProcMaps(&contents))
375*8975f5c5SAndroid Build Coastguard Worker {
376*8975f5c5SAndroid Build Coastguard Worker fprintf(stderr, "CacheMemoryRegions: Failed to read /proc/self/maps\n");
377*8975f5c5SAndroid Build Coastguard Worker return false;
378*8975f5c5SAndroid Build Coastguard Worker }
379*8975f5c5SAndroid Build Coastguard Worker
380*8975f5c5SAndroid Build Coastguard Worker // Parses /proc/self/maps.
381*8975f5c5SAndroid Build Coastguard Worker if (!ParseProcMaps(contents, ®ions))
382*8975f5c5SAndroid Build Coastguard Worker {
383*8975f5c5SAndroid Build Coastguard Worker fprintf(stderr, "CacheMemoryRegions: Failed to parse the contents of /proc/self/maps\n");
384*8975f5c5SAndroid Build Coastguard Worker return false;
385*8975f5c5SAndroid Build Coastguard Worker }
386*8975f5c5SAndroid Build Coastguard Worker
387*8975f5c5SAndroid Build Coastguard Worker SetBaseAddressesForMemoryRegions(regions);
388*8975f5c5SAndroid Build Coastguard Worker return true;
389*8975f5c5SAndroid Build Coastguard Worker }
390*8975f5c5SAndroid Build Coastguard Worker
391*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kAddr2LineMaxParameters = 50;
392*8975f5c5SAndroid Build Coastguard Worker using Addr2LineCommandLine = angle::FixedVector<const char *, kAddr2LineMaxParameters>;
393*8975f5c5SAndroid Build Coastguard Worker
394*8975f5c5SAndroid Build Coastguard Worker void CallAddr2Line(const Addr2LineCommandLine &commandLine)
395*8975f5c5SAndroid Build Coastguard Worker {
396*8975f5c5SAndroid Build Coastguard Worker pid_t pid = fork();
397*8975f5c5SAndroid Build Coastguard Worker if (pid < 0)
398*8975f5c5SAndroid Build Coastguard Worker {
399*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error: Failed to fork()" << std::endl;
400*8975f5c5SAndroid Build Coastguard Worker }
401*8975f5c5SAndroid Build Coastguard Worker else if (pid > 0)
402*8975f5c5SAndroid Build Coastguard Worker {
403*8975f5c5SAndroid Build Coastguard Worker int status;
404*8975f5c5SAndroid Build Coastguard Worker waitpid(pid, &status, 0);
405*8975f5c5SAndroid Build Coastguard Worker // Ignore the status, since we aren't going to handle it anyway.
406*8975f5c5SAndroid Build Coastguard Worker }
407*8975f5c5SAndroid Build Coastguard Worker else
408*8975f5c5SAndroid Build Coastguard Worker {
409*8975f5c5SAndroid Build Coastguard Worker // Child process executes addr2line
410*8975f5c5SAndroid Build Coastguard Worker //
411*8975f5c5SAndroid Build Coastguard Worker // See comment in test_utils_posix.cpp::PosixProcess regarding const_cast.
412*8975f5c5SAndroid Build Coastguard Worker execvp(commandLine[0], const_cast<char *const *>(commandLine.data()));
413*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error: Child process returned from exevc()" << std::endl;
414*8975f5c5SAndroid Build Coastguard Worker _exit(EXIT_FAILURE); // exec never returns
415*8975f5c5SAndroid Build Coastguard Worker }
416*8975f5c5SAndroid Build Coastguard Worker }
417*8975f5c5SAndroid Build Coastguard Worker
418*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kMaxAddressLen = 1024;
419*8975f5c5SAndroid Build Coastguard Worker using AddressBuffer = angle::FixedVector<char, kMaxAddressLen>;
420*8975f5c5SAndroid Build Coastguard Worker
421*8975f5c5SAndroid Build Coastguard Worker const char *ResolveAddress(const MemoryRegionArray ®ions,
422*8975f5c5SAndroid Build Coastguard Worker const std::string &resolvedModule,
423*8975f5c5SAndroid Build Coastguard Worker const char *address,
424*8975f5c5SAndroid Build Coastguard Worker AddressBuffer &buffer)
425*8975f5c5SAndroid Build Coastguard Worker {
426*8975f5c5SAndroid Build Coastguard Worker size_t lastModuleSlash = resolvedModule.rfind('/');
427*8975f5c5SAndroid Build Coastguard Worker ASSERT(lastModuleSlash != std::string::npos);
428*8975f5c5SAndroid Build Coastguard Worker std::string baseModule = resolvedModule.substr(lastModuleSlash);
429*8975f5c5SAndroid Build Coastguard Worker
430*8975f5c5SAndroid Build Coastguard Worker for (const MappedMemoryRegion ®ion : regions)
431*8975f5c5SAndroid Build Coastguard Worker {
432*8975f5c5SAndroid Build Coastguard Worker size_t pathSlashPos = region.path.rfind('/');
433*8975f5c5SAndroid Build Coastguard Worker if (pathSlashPos != std::string::npos && region.path.substr(pathSlashPos) == baseModule)
434*8975f5c5SAndroid Build Coastguard Worker {
435*8975f5c5SAndroid Build Coastguard Worker uintptr_t scannedAddress;
436*8975f5c5SAndroid Build Coastguard Worker int scanReturn = sscanf(address, "%" SCNxPTR, &scannedAddress);
437*8975f5c5SAndroid Build Coastguard Worker ASSERT(scanReturn == 1);
438*8975f5c5SAndroid Build Coastguard Worker scannedAddress -= region.base;
439*8975f5c5SAndroid Build Coastguard Worker char printBuffer[255] = {};
440*8975f5c5SAndroid Build Coastguard Worker size_t scannedSize = sprintf(printBuffer, "0x%" PRIXPTR, scannedAddress);
441*8975f5c5SAndroid Build Coastguard Worker size_t bufferSize = buffer.size();
442*8975f5c5SAndroid Build Coastguard Worker buffer.resize(bufferSize + scannedSize + 1, 0);
443*8975f5c5SAndroid Build Coastguard Worker memcpy(&buffer[bufferSize], printBuffer, scannedSize);
444*8975f5c5SAndroid Build Coastguard Worker return &buffer[bufferSize];
445*8975f5c5SAndroid Build Coastguard Worker }
446*8975f5c5SAndroid Build Coastguard Worker }
447*8975f5c5SAndroid Build Coastguard Worker
448*8975f5c5SAndroid Build Coastguard Worker return address;
449*8975f5c5SAndroid Build Coastguard Worker }
450*8975f5c5SAndroid Build Coastguard Worker // This is only required when the current CWD does not match the initial CWD and could be replaced
451*8975f5c5SAndroid Build Coastguard Worker // by storing the initial CWD state globally. It is only changed in vulkan_icd.cpp.
452*8975f5c5SAndroid Build Coastguard Worker std::string RemoveOverlappingPath(const std::string &resolvedModule)
453*8975f5c5SAndroid Build Coastguard Worker {
454*8975f5c5SAndroid Build Coastguard Worker // Build path from CWD in case CWD matches executable directory
455*8975f5c5SAndroid Build Coastguard Worker // but relative paths are from initial cwd.
456*8975f5c5SAndroid Build Coastguard Worker const Optional<std::string> &cwd = angle::GetCWD();
457*8975f5c5SAndroid Build Coastguard Worker if (!cwd.valid())
458*8975f5c5SAndroid Build Coastguard Worker {
459*8975f5c5SAndroid Build Coastguard Worker std::cerr << "Error getting CWD to print the backtrace." << std::endl;
460*8975f5c5SAndroid Build Coastguard Worker return resolvedModule;
461*8975f5c5SAndroid Build Coastguard Worker }
462*8975f5c5SAndroid Build Coastguard Worker else
463*8975f5c5SAndroid Build Coastguard Worker {
464*8975f5c5SAndroid Build Coastguard Worker std::string absolutePath = cwd.value();
465*8975f5c5SAndroid Build Coastguard Worker size_t lastPathSepLoc = resolvedModule.find_last_of(GetPathSeparator());
466*8975f5c5SAndroid Build Coastguard Worker std::string relativePath = resolvedModule.substr(0, lastPathSepLoc);
467*8975f5c5SAndroid Build Coastguard Worker
468*8975f5c5SAndroid Build Coastguard Worker // Remove "." from the relativePath path
469*8975f5c5SAndroid Build Coastguard Worker // For example: ./out/LinuxDebug/angle_perftests
470*8975f5c5SAndroid Build Coastguard Worker size_t pos = relativePath.find('.');
471*8975f5c5SAndroid Build Coastguard Worker if (pos != std::string::npos)
472*8975f5c5SAndroid Build Coastguard Worker {
473*8975f5c5SAndroid Build Coastguard Worker // If found then erase it from string
474*8975f5c5SAndroid Build Coastguard Worker relativePath.erase(pos, 1);
475*8975f5c5SAndroid Build Coastguard Worker }
476*8975f5c5SAndroid Build Coastguard Worker
477*8975f5c5SAndroid Build Coastguard Worker // Remove the overlapping relative path from the CWD so we can build the full
478*8975f5c5SAndroid Build Coastguard Worker // absolute path.
479*8975f5c5SAndroid Build Coastguard Worker // For example:
480*8975f5c5SAndroid Build Coastguard Worker // absolutePath = /home/timvp/code/angle/out/LinuxDebug
481*8975f5c5SAndroid Build Coastguard Worker // relativePath = /out/LinuxDebug
482*8975f5c5SAndroid Build Coastguard Worker pos = absolutePath.find(relativePath);
483*8975f5c5SAndroid Build Coastguard Worker if (pos != std::string::npos)
484*8975f5c5SAndroid Build Coastguard Worker {
485*8975f5c5SAndroid Build Coastguard Worker // If found then erase it from string
486*8975f5c5SAndroid Build Coastguard Worker absolutePath.erase(pos, relativePath.length());
487*8975f5c5SAndroid Build Coastguard Worker }
488*8975f5c5SAndroid Build Coastguard Worker return absolutePath + GetPathSeparator() + resolvedModule;
489*8975f5c5SAndroid Build Coastguard Worker }
490*8975f5c5SAndroid Build Coastguard Worker }
491*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
492*8975f5c5SAndroid Build Coastguard Worker # endif // defined(ANGLE_HAS_ADDR2LINE)
493*8975f5c5SAndroid Build Coastguard Worker
494*8975f5c5SAndroid Build Coastguard Worker void PrintStackBacktrace()
495*8975f5c5SAndroid Build Coastguard Worker {
496*8975f5c5SAndroid Build Coastguard Worker printf("Backtrace:\n");
497*8975f5c5SAndroid Build Coastguard Worker
498*8975f5c5SAndroid Build Coastguard Worker void *stack[64];
499*8975f5c5SAndroid Build Coastguard Worker const int count = backtrace(stack, ArraySize(stack));
500*8975f5c5SAndroid Build Coastguard Worker char **symbols = backtrace_symbols(stack, count);
501*8975f5c5SAndroid Build Coastguard Worker
502*8975f5c5SAndroid Build Coastguard Worker # if defined(ANGLE_HAS_ADDR2LINE)
503*8975f5c5SAndroid Build Coastguard Worker
504*8975f5c5SAndroid Build Coastguard Worker MemoryRegionArray regions;
505*8975f5c5SAndroid Build Coastguard Worker CacheMemoryRegions(regions);
506*8975f5c5SAndroid Build Coastguard Worker
507*8975f5c5SAndroid Build Coastguard Worker // Child process executes addr2line
508*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kAddr2LineFixedParametersCount = 6;
509*8975f5c5SAndroid Build Coastguard Worker Addr2LineCommandLine commandLineArgs = {
510*8975f5c5SAndroid Build Coastguard Worker "addr2line", "-s", "-p", "-f", "-C", "-e",
511*8975f5c5SAndroid Build Coastguard Worker };
512*8975f5c5SAndroid Build Coastguard Worker const char *currentModule = "";
513*8975f5c5SAndroid Build Coastguard Worker std::string resolvedModule;
514*8975f5c5SAndroid Build Coastguard Worker AddressBuffer addressBuffer;
515*8975f5c5SAndroid Build Coastguard Worker
516*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < count; i++)
517*8975f5c5SAndroid Build Coastguard Worker {
518*8975f5c5SAndroid Build Coastguard Worker char *symbol = symbols[i];
519*8975f5c5SAndroid Build Coastguard Worker
520*8975f5c5SAndroid Build Coastguard Worker // symbol looks like the following:
521*8975f5c5SAndroid Build Coastguard Worker //
522*8975f5c5SAndroid Build Coastguard Worker // path/to/module(+localAddress) [address]
523*8975f5c5SAndroid Build Coastguard Worker //
524*8975f5c5SAndroid Build Coastguard Worker // If module is not an absolute path, it needs to be resolved.
525*8975f5c5SAndroid Build Coastguard Worker
526*8975f5c5SAndroid Build Coastguard Worker char *module = symbol;
527*8975f5c5SAndroid Build Coastguard Worker char *address = strchr(symbol, '[') + 1;
528*8975f5c5SAndroid Build Coastguard Worker
529*8975f5c5SAndroid Build Coastguard Worker *strchr(module, '(') = 0;
530*8975f5c5SAndroid Build Coastguard Worker *strchr(address, ']') = 0;
531*8975f5c5SAndroid Build Coastguard Worker
532*8975f5c5SAndroid Build Coastguard Worker // If module is the same as last, continue batching addresses. If commandLineArgs has
533*8975f5c5SAndroid Build Coastguard Worker // reached its capacity however, make the call to addr2line already. Note that there should
534*8975f5c5SAndroid Build Coastguard Worker // be one entry left for the terminating nullptr at the end of the command line args.
535*8975f5c5SAndroid Build Coastguard Worker if (strcmp(module, currentModule) == 0 &&
536*8975f5c5SAndroid Build Coastguard Worker commandLineArgs.size() + 1 < commandLineArgs.max_size())
537*8975f5c5SAndroid Build Coastguard Worker {
538*8975f5c5SAndroid Build Coastguard Worker commandLineArgs.push_back(
539*8975f5c5SAndroid Build Coastguard Worker ResolveAddress(regions, resolvedModule, address, addressBuffer));
540*8975f5c5SAndroid Build Coastguard Worker continue;
541*8975f5c5SAndroid Build Coastguard Worker }
542*8975f5c5SAndroid Build Coastguard Worker
543*8975f5c5SAndroid Build Coastguard Worker // If there's a command batched, execute it before modifying currentModule (a pointer to
544*8975f5c5SAndroid Build Coastguard Worker // which is stored in the command line args).
545*8975f5c5SAndroid Build Coastguard Worker if (currentModule[0] != 0)
546*8975f5c5SAndroid Build Coastguard Worker {
547*8975f5c5SAndroid Build Coastguard Worker commandLineArgs.push_back(nullptr);
548*8975f5c5SAndroid Build Coastguard Worker CallAddr2Line(commandLineArgs);
549*8975f5c5SAndroid Build Coastguard Worker addressBuffer.clear();
550*8975f5c5SAndroid Build Coastguard Worker }
551*8975f5c5SAndroid Build Coastguard Worker
552*8975f5c5SAndroid Build Coastguard Worker // Reset the command line and remember this module as the current.
553*8975f5c5SAndroid Build Coastguard Worker resolvedModule = currentModule = module;
554*8975f5c5SAndroid Build Coastguard Worker commandLineArgs.resize(kAddr2LineFixedParametersCount);
555*8975f5c5SAndroid Build Coastguard Worker
556*8975f5c5SAndroid Build Coastguard Worker // First check if the a relative path simply resolved to an absolute one from cwd,
557*8975f5c5SAndroid Build Coastguard Worker // for abolute paths this resolves symlinks.
558*8975f5c5SAndroid Build Coastguard Worker char *realPath = realpath(resolvedModule.c_str(), NULL);
559*8975f5c5SAndroid Build Coastguard Worker if (realPath)
560*8975f5c5SAndroid Build Coastguard Worker {
561*8975f5c5SAndroid Build Coastguard Worker resolvedModule = std::string(realPath);
562*8975f5c5SAndroid Build Coastguard Worker free(realPath);
563*8975f5c5SAndroid Build Coastguard Worker }
564*8975f5c5SAndroid Build Coastguard Worker // We need an absolute path to get to the executable and all of the various shared objects,
565*8975f5c5SAndroid Build Coastguard Worker // but the caller may have used a relative path to launch the executable, so build one up if
566*8975f5c5SAndroid Build Coastguard Worker // we don't see a leading '/'.
567*8975f5c5SAndroid Build Coastguard Worker else if (resolvedModule.at(0) != GetPathSeparator())
568*8975f5c5SAndroid Build Coastguard Worker {
569*8975f5c5SAndroid Build Coastguard Worker // For some modules we receive a relative path from the build directory (executable
570*8975f5c5SAndroid Build Coastguard Worker // directory) instead of the execution directory (current directory). This happens
571*8975f5c5SAndroid Build Coastguard Worker // for libVkLayer_khronos_validation.so. If realpath fails to create an absolute
572*8975f5c5SAndroid Build Coastguard Worker // path, try constructing one from the build directory.
573*8975f5c5SAndroid Build Coastguard Worker // This will resolve paths like `angledata/../libVkLayer_khronos_validation.so` to
574*8975f5c5SAndroid Build Coastguard Worker // `/home/user/angle/out/Debug/libVkLayer_khronos_validation.so`
575*8975f5c5SAndroid Build Coastguard Worker std::string pathFromExecDir =
576*8975f5c5SAndroid Build Coastguard Worker GetExecutableDirectory() + GetPathSeparator() + resolvedModule;
577*8975f5c5SAndroid Build Coastguard Worker realPath = realpath(pathFromExecDir.c_str(), NULL);
578*8975f5c5SAndroid Build Coastguard Worker if (realPath)
579*8975f5c5SAndroid Build Coastguard Worker {
580*8975f5c5SAndroid Build Coastguard Worker resolvedModule = std::string(realPath);
581*8975f5c5SAndroid Build Coastguard Worker free(realPath);
582*8975f5c5SAndroid Build Coastguard Worker }
583*8975f5c5SAndroid Build Coastguard Worker else
584*8975f5c5SAndroid Build Coastguard Worker {
585*8975f5c5SAndroid Build Coastguard Worker // Try removing overlapping path as a last resort.
586*8975f5c5SAndroid Build Coastguard Worker // This will resolve `./out/Debug/angle_end2end_tests` to
587*8975f5c5SAndroid Build Coastguard Worker // `/home/user/angle/out/Debug/angle_end2end_tests` when CWD is
588*8975f5c5SAndroid Build Coastguard Worker // `/home/user/angle/out/Debug`, which is caused by ScopedVkLoaderEnvironment.
589*8975f5c5SAndroid Build Coastguard Worker // This is required for printing traces during vk::Renderer init.
590*8975f5c5SAndroid Build Coastguard Worker // Since we do not store the initial CWD globally we need to reconstruct here
591*8975f5c5SAndroid Build Coastguard Worker // by removing the overlapping path.
592*8975f5c5SAndroid Build Coastguard Worker std::string removeOverlappingPath = RemoveOverlappingPath(resolvedModule);
593*8975f5c5SAndroid Build Coastguard Worker realPath = realpath(removeOverlappingPath.c_str(), NULL);
594*8975f5c5SAndroid Build Coastguard Worker if (realPath)
595*8975f5c5SAndroid Build Coastguard Worker {
596*8975f5c5SAndroid Build Coastguard Worker resolvedModule = std::string(realPath);
597*8975f5c5SAndroid Build Coastguard Worker free(realPath);
598*8975f5c5SAndroid Build Coastguard Worker }
599*8975f5c5SAndroid Build Coastguard Worker else
600*8975f5c5SAndroid Build Coastguard Worker {
601*8975f5c5SAndroid Build Coastguard Worker WARN() << "Could not resolve path for module with relative path "
602*8975f5c5SAndroid Build Coastguard Worker << resolvedModule;
603*8975f5c5SAndroid Build Coastguard Worker }
604*8975f5c5SAndroid Build Coastguard Worker }
605*8975f5c5SAndroid Build Coastguard Worker }
606*8975f5c5SAndroid Build Coastguard Worker else
607*8975f5c5SAndroid Build Coastguard Worker {
608*8975f5c5SAndroid Build Coastguard Worker WARN() << "Could not resolve path for module with absolute path " << resolvedModule;
609*8975f5c5SAndroid Build Coastguard Worker }
610*8975f5c5SAndroid Build Coastguard Worker
611*8975f5c5SAndroid Build Coastguard Worker const char *resolvedAddress =
612*8975f5c5SAndroid Build Coastguard Worker ResolveAddress(regions, resolvedModule, address, addressBuffer);
613*8975f5c5SAndroid Build Coastguard Worker
614*8975f5c5SAndroid Build Coastguard Worker commandLineArgs.push_back(resolvedModule.c_str());
615*8975f5c5SAndroid Build Coastguard Worker commandLineArgs.push_back(resolvedAddress);
616*8975f5c5SAndroid Build Coastguard Worker }
617*8975f5c5SAndroid Build Coastguard Worker
618*8975f5c5SAndroid Build Coastguard Worker // Call addr2line for the last batch of addresses.
619*8975f5c5SAndroid Build Coastguard Worker if (currentModule[0] != 0)
620*8975f5c5SAndroid Build Coastguard Worker {
621*8975f5c5SAndroid Build Coastguard Worker commandLineArgs.push_back(nullptr);
622*8975f5c5SAndroid Build Coastguard Worker CallAddr2Line(commandLineArgs);
623*8975f5c5SAndroid Build Coastguard Worker }
624*8975f5c5SAndroid Build Coastguard Worker # else
625*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < count; i++)
626*8975f5c5SAndroid Build Coastguard Worker {
627*8975f5c5SAndroid Build Coastguard Worker Dl_info info;
628*8975f5c5SAndroid Build Coastguard Worker if (dladdr(stack[i], &info) && info.dli_sname)
629*8975f5c5SAndroid Build Coastguard Worker {
630*8975f5c5SAndroid Build Coastguard Worker // Make sure this is large enough to hold the fully demangled names, otherwise we could
631*8975f5c5SAndroid Build Coastguard Worker // segault/hang here. For example, Vulkan validation layer errors can be deep enough
632*8975f5c5SAndroid Build Coastguard Worker // into the stack that very large symbol names are generated.
633*8975f5c5SAndroid Build Coastguard Worker char demangled[4096];
634*8975f5c5SAndroid Build Coastguard Worker size_t len = ArraySize(demangled);
635*8975f5c5SAndroid Build Coastguard Worker int ok;
636*8975f5c5SAndroid Build Coastguard Worker
637*8975f5c5SAndroid Build Coastguard Worker abi::__cxa_demangle(info.dli_sname, demangled, &len, &ok);
638*8975f5c5SAndroid Build Coastguard Worker if (ok == 0)
639*8975f5c5SAndroid Build Coastguard Worker {
640*8975f5c5SAndroid Build Coastguard Worker printf(" %s\n", demangled);
641*8975f5c5SAndroid Build Coastguard Worker continue;
642*8975f5c5SAndroid Build Coastguard Worker }
643*8975f5c5SAndroid Build Coastguard Worker }
644*8975f5c5SAndroid Build Coastguard Worker printf(" %s\n", symbols[i]);
645*8975f5c5SAndroid Build Coastguard Worker }
646*8975f5c5SAndroid Build Coastguard Worker # endif // defined(ANGLE_HAS_ADDR2LINE)
647*8975f5c5SAndroid Build Coastguard Worker }
648*8975f5c5SAndroid Build Coastguard Worker
649*8975f5c5SAndroid Build Coastguard Worker static void Handler(int sig)
650*8975f5c5SAndroid Build Coastguard Worker {
651*8975f5c5SAndroid Build Coastguard Worker printf("\nSignal %d [%s]:\n", sig, strsignal(sig));
652*8975f5c5SAndroid Build Coastguard Worker
653*8975f5c5SAndroid Build Coastguard Worker if (gCrashHandlerCallback)
654*8975f5c5SAndroid Build Coastguard Worker {
655*8975f5c5SAndroid Build Coastguard Worker (*gCrashHandlerCallback)();
656*8975f5c5SAndroid Build Coastguard Worker }
657*8975f5c5SAndroid Build Coastguard Worker
658*8975f5c5SAndroid Build Coastguard Worker PrintStackBacktrace();
659*8975f5c5SAndroid Build Coastguard Worker
660*8975f5c5SAndroid Build Coastguard Worker // Exit NOW. Don't notify other threads, don't call anything registered with atexit().
661*8975f5c5SAndroid Build Coastguard Worker _Exit(sig);
662*8975f5c5SAndroid Build Coastguard Worker }
663*8975f5c5SAndroid Build Coastguard Worker
664*8975f5c5SAndroid Build Coastguard Worker # endif // defined(ANGLE_PLATFORM_APPLE)
665*8975f5c5SAndroid Build Coastguard Worker
666*8975f5c5SAndroid Build Coastguard Worker static constexpr int kSignals[] = {
667*8975f5c5SAndroid Build Coastguard Worker SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP,
668*8975f5c5SAndroid Build Coastguard Worker };
669*8975f5c5SAndroid Build Coastguard Worker
670*8975f5c5SAndroid Build Coastguard Worker void InitCrashHandler(CrashCallback *callback)
671*8975f5c5SAndroid Build Coastguard Worker {
672*8975f5c5SAndroid Build Coastguard Worker gCrashHandlerCallback = callback;
673*8975f5c5SAndroid Build Coastguard Worker for (int sig : kSignals)
674*8975f5c5SAndroid Build Coastguard Worker {
675*8975f5c5SAndroid Build Coastguard Worker // Register our signal handler unless something's already done so (e.g. catchsegv).
676*8975f5c5SAndroid Build Coastguard Worker void (*prev)(int) = signal(sig, Handler);
677*8975f5c5SAndroid Build Coastguard Worker if (prev != SIG_DFL)
678*8975f5c5SAndroid Build Coastguard Worker {
679*8975f5c5SAndroid Build Coastguard Worker signal(sig, prev);
680*8975f5c5SAndroid Build Coastguard Worker }
681*8975f5c5SAndroid Build Coastguard Worker }
682*8975f5c5SAndroid Build Coastguard Worker }
683*8975f5c5SAndroid Build Coastguard Worker
684*8975f5c5SAndroid Build Coastguard Worker void TerminateCrashHandler()
685*8975f5c5SAndroid Build Coastguard Worker {
686*8975f5c5SAndroid Build Coastguard Worker gCrashHandlerCallback = nullptr;
687*8975f5c5SAndroid Build Coastguard Worker for (int sig : kSignals)
688*8975f5c5SAndroid Build Coastguard Worker {
689*8975f5c5SAndroid Build Coastguard Worker void (*prev)(int) = signal(sig, SIG_DFL);
690*8975f5c5SAndroid Build Coastguard Worker if (prev != Handler && prev != SIG_DFL)
691*8975f5c5SAndroid Build Coastguard Worker {
692*8975f5c5SAndroid Build Coastguard Worker signal(sig, prev);
693*8975f5c5SAndroid Build Coastguard Worker }
694*8975f5c5SAndroid Build Coastguard Worker }
695*8975f5c5SAndroid Build Coastguard Worker }
696*8975f5c5SAndroid Build Coastguard Worker
697*8975f5c5SAndroid Build Coastguard Worker #endif // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_FUCHSIA)
698*8975f5c5SAndroid Build Coastguard Worker
699*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
700