xref: /aosp_15_r20/external/gwp_asan/android/test_backtrace.cpp (revision b302aa5039729da396909ef03e815160dab4448c)
1*b302aa50SMitch Phillips /*
2*b302aa50SMitch Phillips  * Copyright (C) 2020 The Android Open Source Project
3*b302aa50SMitch Phillips  *
4*b302aa50SMitch Phillips  * Licensed under the Apache License, Version 2.0 (the "License");
5*b302aa50SMitch Phillips  * you may not use this file except in compliance with the License.
6*b302aa50SMitch Phillips  * You may obtain a copy of the License at
7*b302aa50SMitch Phillips  *
8*b302aa50SMitch Phillips  *      http://www.apache.org/licenses/LICENSE-2.0
9*b302aa50SMitch Phillips  *
10*b302aa50SMitch Phillips  * Unless required by applicable law or agreed to in writing, software
11*b302aa50SMitch Phillips  * distributed under the License is distributed on an "AS IS" BASIS,
12*b302aa50SMitch Phillips  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b302aa50SMitch Phillips  * See the License for the specific language governing permissions and
14*b302aa50SMitch Phillips  * limitations under the License.
15*b302aa50SMitch Phillips  */
16*b302aa50SMitch Phillips 
17*b302aa50SMitch Phillips #include "gwp_asan/common.h"
18*b302aa50SMitch Phillips #include "gwp_asan/optional/backtrace.h"
19*b302aa50SMitch Phillips #include "gwp_asan/optional/segv_handler.h"
20*b302aa50SMitch Phillips 
21*b302aa50SMitch Phillips #include <unwindstack/Maps.h>
22*b302aa50SMitch Phillips #include <unwindstack/Memory.h>
23*b302aa50SMitch Phillips #include <unwindstack/Regs.h>
24*b302aa50SMitch Phillips #include <unwindstack/RegsGetLocal.h>
25*b302aa50SMitch Phillips #include <unwindstack/Unwinder.h>
26*b302aa50SMitch Phillips 
27*b302aa50SMitch Phillips namespace {
28*b302aa50SMitch Phillips // In reality, on Android, we use two separate unwinders. GWP-ASan internally
29*b302aa50SMitch Phillips // uses a fast, frame-pointer unwinder for allocation/deallocation stack traces
30*b302aa50SMitch Phillips // (android_unsafe_frame_pointer_chase, provided by bionic libc). When a process
31*b302aa50SMitch Phillips // crashes, debuggerd unwinds the access trace using libunwindstack, which is a
32*b302aa50SMitch Phillips // slow CFI-based unwinder. We don't split the unwinders in the test harness,
33*b302aa50SMitch Phillips // and frame-pointer unwinding doesn't work properly though a signal handler, so
34*b302aa50SMitch Phillips // we opt to use libunwindstack in this test. This has the effect that we get
35*b302aa50SMitch Phillips // potentially more detailed stack frames in the allocation/deallocation traces
36*b302aa50SMitch Phillips // (as we don't use the production unwinder), but that's fine for test-only.
BacktraceUnwindstack(uintptr_t * TraceBuffer,size_t Size)37*b302aa50SMitch Phillips size_t BacktraceUnwindstack(uintptr_t *TraceBuffer, size_t Size) {
38*b302aa50SMitch Phillips   unwindstack::LocalMaps maps;
39*b302aa50SMitch Phillips   if (!maps.Parse()) {
40*b302aa50SMitch Phillips     return 0;
41*b302aa50SMitch Phillips   }
42*b302aa50SMitch Phillips 
43*b302aa50SMitch Phillips   auto process_memory = unwindstack::Memory::CreateProcessMemoryThreadCached(getpid());
44*b302aa50SMitch Phillips   std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
45*b302aa50SMitch Phillips   unwindstack::RegsGetLocal(regs.get());
46*b302aa50SMitch Phillips   unwindstack::Unwinder unwinder(Size, &maps, regs.get(), process_memory);
47*b302aa50SMitch Phillips   unwinder.Unwind();
48*b302aa50SMitch Phillips   for (const auto &frame : unwinder.frames()) {
49*b302aa50SMitch Phillips     *TraceBuffer = frame.pc;
50*b302aa50SMitch Phillips     TraceBuffer++;
51*b302aa50SMitch Phillips   }
52*b302aa50SMitch Phillips   return unwinder.NumFrames();
53*b302aa50SMitch Phillips }
54*b302aa50SMitch Phillips 
55*b302aa50SMitch Phillips // We don't need any custom handling for the Segv backtrace - the unwindstack
56*b302aa50SMitch Phillips // unwinder has no problems with unwinding through a signal handler.
SegvBacktrace(uintptr_t * TraceBuffer,size_t Size,void *)57*b302aa50SMitch Phillips size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size, void * /*Context*/) {
58*b302aa50SMitch Phillips   return BacktraceUnwindstack(TraceBuffer, Size);
59*b302aa50SMitch Phillips }
60*b302aa50SMitch Phillips 
61*b302aa50SMitch Phillips // This function is a good mimic as to what's happening in the out-of-process
62*b302aa50SMitch Phillips // tombstone daemon (see debuggerd for more information). In our case, we want
63*b302aa50SMitch Phillips // to provide symbolized backtraces during ***testing only*** here. This
64*b302aa50SMitch Phillips // function called from a signal handler, and is extraordinarily not
65*b302aa50SMitch Phillips // signal-safe, but works for our purposes.
PrintBacktraceUnwindstack(uintptr_t * TraceBuffer,size_t TraceLength,gwp_asan::Printf_t Print)66*b302aa50SMitch Phillips void PrintBacktraceUnwindstack(uintptr_t *TraceBuffer, size_t TraceLength,
67*b302aa50SMitch Phillips                                gwp_asan::Printf_t Print) {
68*b302aa50SMitch Phillips   unwindstack::UnwinderFromPid unwinder(
69*b302aa50SMitch Phillips       gwp_asan::AllocationMetadata::kMaxTraceLengthToCollect, getpid());
70*b302aa50SMitch Phillips   unwinder.SetRegs(unwindstack::Regs::CreateFromLocal());
71*b302aa50SMitch Phillips   if (!unwinder.Init()) {
72*b302aa50SMitch Phillips     Print("  Unable to init unwinder: %s\n", unwinder.LastErrorCodeString());
73*b302aa50SMitch Phillips     return;
74*b302aa50SMitch Phillips   }
75*b302aa50SMitch Phillips 
76*b302aa50SMitch Phillips   for (size_t i = 0; i < TraceLength; ++i) {
77*b302aa50SMitch Phillips     unwindstack::FrameData frame_data =
78*b302aa50SMitch Phillips         unwinder.BuildFrameFromPcOnly(TraceBuffer[i]);
79*b302aa50SMitch Phillips     frame_data.num = i;
80*b302aa50SMitch Phillips     Print("  %s\n", unwinder.FormatFrame(frame_data).c_str());
81*b302aa50SMitch Phillips   }
82*b302aa50SMitch Phillips }
83*b302aa50SMitch Phillips 
84*b302aa50SMitch Phillips } // anonymous namespace
85*b302aa50SMitch Phillips 
86*b302aa50SMitch Phillips namespace gwp_asan {
87*b302aa50SMitch Phillips namespace backtrace {
getBacktraceFunction()88*b302aa50SMitch Phillips options::Backtrace_t getBacktraceFunction() { return BacktraceUnwindstack; }
89*b302aa50SMitch Phillips 
getPrintBacktraceFunction()90*b302aa50SMitch Phillips PrintBacktrace_t getPrintBacktraceFunction() {
91*b302aa50SMitch Phillips   return PrintBacktraceUnwindstack;
92*b302aa50SMitch Phillips }
93*b302aa50SMitch Phillips 
getSegvBacktraceFunction()94*b302aa50SMitch Phillips SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
95*b302aa50SMitch Phillips } // namespace backtrace
96*b302aa50SMitch Phillips } // namespace gwp_asan
97