xref: /aosp_15_r20/external/angle/util/posix/crash_handler_posix.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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", &region.start,
268*8975f5c5SAndroid Build Coastguard Worker                    &region.end, permissions, &region.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 &regions)
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 &regions)
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, &regions))
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 &regions,
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 &region : 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