xref: /aosp_15_r20/external/cronet/base/debug/stack_trace_fuchsia.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <elf.h>
8*6777b538SAndroid Build Coastguard Worker #include <link.h>
9*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
10*6777b538SAndroid Build Coastguard Worker #include <threads.h>
11*6777b538SAndroid Build Coastguard Worker #include <unwind.h>
12*6777b538SAndroid Build Coastguard Worker #include <zircon/process.h>
13*6777b538SAndroid Build Coastguard Worker #include <zircon/syscalls.h>
14*6777b538SAndroid Build Coastguard Worker #include <zircon/syscalls/port.h>
15*6777b538SAndroid Build Coastguard Worker #include <zircon/types.h>
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #include <algorithm>
18*6777b538SAndroid Build Coastguard Worker #include <array>
19*6777b538SAndroid Build Coastguard Worker #include <iomanip>
20*6777b538SAndroid Build Coastguard Worker #include <iostream>
21*6777b538SAndroid Build Coastguard Worker #include <string_view>
22*6777b538SAndroid Build Coastguard Worker #include <type_traits>
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker #include "base/atomic_sequence_num.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/debug/elf_reader.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker namespace base {
29*6777b538SAndroid Build Coastguard Worker namespace debug {
30*6777b538SAndroid Build Coastguard Worker namespace {
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker struct BacktraceData {
33*6777b538SAndroid Build Coastguard Worker   const void** trace_array;
34*6777b538SAndroid Build Coastguard Worker   size_t* count;
35*6777b538SAndroid Build Coastguard Worker   size_t max;
36*6777b538SAndroid Build Coastguard Worker };
37*6777b538SAndroid Build Coastguard Worker 
UnwindStore(struct _Unwind_Context * context,void * user_data)38*6777b538SAndroid Build Coastguard Worker _Unwind_Reason_Code UnwindStore(struct _Unwind_Context* context,
39*6777b538SAndroid Build Coastguard Worker                                 void* user_data) {
40*6777b538SAndroid Build Coastguard Worker   BacktraceData* data = reinterpret_cast<BacktraceData*>(user_data);
41*6777b538SAndroid Build Coastguard Worker   uintptr_t pc = _Unwind_GetIP(context);
42*6777b538SAndroid Build Coastguard Worker   data->trace_array[*data->count] = reinterpret_cast<void*>(pc);
43*6777b538SAndroid Build Coastguard Worker   *data->count += 1;
44*6777b538SAndroid Build Coastguard Worker   if (*data->count == data->max)
45*6777b538SAndroid Build Coastguard Worker     return _URC_END_OF_STACK;
46*6777b538SAndroid Build Coastguard Worker   return _URC_NO_REASON;
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker // Build a "rwx" C string-based representation of the permission bits.
50*6777b538SAndroid Build Coastguard Worker // The output buffer is reused across calls, and should not be retained across
51*6777b538SAndroid Build Coastguard Worker // consecutive invocations of this function.
PermissionFlagsToString(int flags,char permission_buf[4])52*6777b538SAndroid Build Coastguard Worker const char* PermissionFlagsToString(int flags, char permission_buf[4]) {
53*6777b538SAndroid Build Coastguard Worker   char* permission = permission_buf;
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker   if (flags & PF_R)
56*6777b538SAndroid Build Coastguard Worker     (*permission++) = 'r';
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker   if (flags & PF_W)
59*6777b538SAndroid Build Coastguard Worker     (*permission++) = 'w';
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker   if (flags & PF_X)
62*6777b538SAndroid Build Coastguard Worker     (*permission++) = 'x';
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker   *permission = '\0';
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker   return permission_buf;
67*6777b538SAndroid Build Coastguard Worker }
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker // Stores and queries debugging symbol map info for the current process.
70*6777b538SAndroid Build Coastguard Worker class SymbolMap {
71*6777b538SAndroid Build Coastguard Worker  public:
72*6777b538SAndroid Build Coastguard Worker   struct Segment {
73*6777b538SAndroid Build Coastguard Worker     const void* addr = nullptr;
74*6777b538SAndroid Build Coastguard Worker     size_t relative_addr = 0;
75*6777b538SAndroid Build Coastguard Worker     int permission_flags = 0;
76*6777b538SAndroid Build Coastguard Worker     size_t size = 0;
77*6777b538SAndroid Build Coastguard Worker   };
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker   struct Module {
80*6777b538SAndroid Build Coastguard Worker     // Maximum number of PT_LOAD segments to process per ELF binary. Most
81*6777b538SAndroid Build Coastguard Worker     // binaries have only 2-3 such segments.
82*6777b538SAndroid Build Coastguard Worker     static constexpr size_t kMaxSegmentCount = 8;
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker     const void* addr = nullptr;
85*6777b538SAndroid Build Coastguard Worker     std::array<Segment, kMaxSegmentCount> segments;
86*6777b538SAndroid Build Coastguard Worker     size_t segment_count = 0;
87*6777b538SAndroid Build Coastguard Worker     char name[ZX_MAX_NAME_LEN + 1] = {0};
88*6777b538SAndroid Build Coastguard Worker     char build_id[kMaxBuildIdStringLength + 1] = {0};
89*6777b538SAndroid Build Coastguard Worker   };
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker   SymbolMap();
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   SymbolMap(const SymbolMap&) = delete;
94*6777b538SAndroid Build Coastguard Worker   SymbolMap& operator=(const SymbolMap&) = delete;
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker   ~SymbolMap() = default;
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   // Gets all entries for the symbol map.
GetModules()99*6777b538SAndroid Build Coastguard Worker   span<Module> GetModules() { return {modules_.data(), count_}; }
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker  private:
102*6777b538SAndroid Build Coastguard Worker   // Component builds of Chrome pull about 250 shared libraries (on Linux), so
103*6777b538SAndroid Build Coastguard Worker   // 512 entries should be enough in most cases.
104*6777b538SAndroid Build Coastguard Worker   static const size_t kMaxMapEntries = 512;
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker   void Populate();
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker   // Sorted in descending order by address, for lookup purposes.
109*6777b538SAndroid Build Coastguard Worker   std::array<Module, kMaxMapEntries> modules_;
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker   size_t count_ = 0;
112*6777b538SAndroid Build Coastguard Worker   bool valid_ = false;
113*6777b538SAndroid Build Coastguard Worker };
114*6777b538SAndroid Build Coastguard Worker 
SymbolMap()115*6777b538SAndroid Build Coastguard Worker SymbolMap::SymbolMap() {
116*6777b538SAndroid Build Coastguard Worker   Populate();
117*6777b538SAndroid Build Coastguard Worker }
118*6777b538SAndroid Build Coastguard Worker 
Populate()119*6777b538SAndroid Build Coastguard Worker void SymbolMap::Populate() {
120*6777b538SAndroid Build Coastguard Worker   zx_handle_t process = zx_process_self();
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker   // Retrieve the debug info struct.
123*6777b538SAndroid Build Coastguard Worker   uintptr_t debug_addr;
124*6777b538SAndroid Build Coastguard Worker   zx_status_t status = zx_object_get_property(
125*6777b538SAndroid Build Coastguard Worker       process, ZX_PROP_PROCESS_DEBUG_ADDR, &debug_addr, sizeof(debug_addr));
126*6777b538SAndroid Build Coastguard Worker   if (status != ZX_OK) {
127*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Couldn't get symbol map for process: " << status;
128*6777b538SAndroid Build Coastguard Worker     return;
129*6777b538SAndroid Build Coastguard Worker   }
130*6777b538SAndroid Build Coastguard Worker   r_debug* debug_info = reinterpret_cast<r_debug*>(debug_addr);
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker   // Get the link map from the debug info struct.
133*6777b538SAndroid Build Coastguard Worker   link_map* lmap = reinterpret_cast<link_map*>(debug_info->r_map);
134*6777b538SAndroid Build Coastguard Worker   if (!lmap) {
135*6777b538SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Null link_map for process.";
136*6777b538SAndroid Build Coastguard Worker     return;
137*6777b538SAndroid Build Coastguard Worker   }
138*6777b538SAndroid Build Coastguard Worker 
139*6777b538SAndroid Build Coastguard Worker   // Populate ELF binary metadata into |modules_|.
140*6777b538SAndroid Build Coastguard Worker   while (lmap != nullptr) {
141*6777b538SAndroid Build Coastguard Worker     if (count_ >= kMaxMapEntries)
142*6777b538SAndroid Build Coastguard Worker       break;
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker     SymbolMap::Module& next_entry = modules_[count_];
145*6777b538SAndroid Build Coastguard Worker     ++count_;
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker     next_entry.addr = reinterpret_cast<void*>(lmap->l_addr);
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker     // Create Segment sub-entries for all PT_LOAD headers.
150*6777b538SAndroid Build Coastguard Worker     // Each Segment corresponds to a "mmap" line in the output.
151*6777b538SAndroid Build Coastguard Worker     next_entry.segment_count = 0;
152*6777b538SAndroid Build Coastguard Worker     for (const Elf64_Phdr& phdr : GetElfProgramHeaders(next_entry.addr)) {
153*6777b538SAndroid Build Coastguard Worker       if (phdr.p_type != PT_LOAD)
154*6777b538SAndroid Build Coastguard Worker         continue;
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker       if (next_entry.segment_count > Module::kMaxSegmentCount) {
157*6777b538SAndroid Build Coastguard Worker         LOG(WARNING) << "Exceeded the maximum number of segments.";
158*6777b538SAndroid Build Coastguard Worker         break;
159*6777b538SAndroid Build Coastguard Worker       }
160*6777b538SAndroid Build Coastguard Worker 
161*6777b538SAndroid Build Coastguard Worker       Segment segment;
162*6777b538SAndroid Build Coastguard Worker       segment.addr =
163*6777b538SAndroid Build Coastguard Worker           reinterpret_cast<const char*>(next_entry.addr) + phdr.p_vaddr;
164*6777b538SAndroid Build Coastguard Worker       segment.relative_addr = phdr.p_vaddr;
165*6777b538SAndroid Build Coastguard Worker       segment.size = phdr.p_memsz;
166*6777b538SAndroid Build Coastguard Worker       segment.permission_flags = static_cast<int>(phdr.p_flags);
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker       next_entry.segments[next_entry.segment_count] = std::move(segment);
169*6777b538SAndroid Build Coastguard Worker       ++next_entry.segment_count;
170*6777b538SAndroid Build Coastguard Worker     }
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker     // Get the human-readable library name from the ELF header, falling back on
173*6777b538SAndroid Build Coastguard Worker     // using names from the link map for binaries that aren't shared libraries.
174*6777b538SAndroid Build Coastguard Worker     std::optional<std::string_view> elf_library_name =
175*6777b538SAndroid Build Coastguard Worker         ReadElfLibraryName(next_entry.addr);
176*6777b538SAndroid Build Coastguard Worker     if (elf_library_name) {
177*6777b538SAndroid Build Coastguard Worker       strlcpy(next_entry.name, elf_library_name->data(),
178*6777b538SAndroid Build Coastguard Worker               elf_library_name->size() + 1);
179*6777b538SAndroid Build Coastguard Worker     } else {
180*6777b538SAndroid Build Coastguard Worker       std::string_view link_map_name(lmap->l_name[0] ? lmap->l_name
181*6777b538SAndroid Build Coastguard Worker                                                      : "<executable>");
182*6777b538SAndroid Build Coastguard Worker 
183*6777b538SAndroid Build Coastguard Worker       // The "module" stack trace annotation doesn't allow for strings which
184*6777b538SAndroid Build Coastguard Worker       // resemble paths, so extract the filename portion from |link_map_name|.
185*6777b538SAndroid Build Coastguard Worker       size_t directory_prefix_idx = link_map_name.find_last_of("/");
186*6777b538SAndroid Build Coastguard Worker       if (directory_prefix_idx != StringPiece::npos) {
187*6777b538SAndroid Build Coastguard Worker         link_map_name = link_map_name.substr(
188*6777b538SAndroid Build Coastguard Worker             directory_prefix_idx + 1,
189*6777b538SAndroid Build Coastguard Worker             link_map_name.size() - directory_prefix_idx - 1);
190*6777b538SAndroid Build Coastguard Worker       }
191*6777b538SAndroid Build Coastguard Worker       strlcpy(next_entry.name, link_map_name.data(), link_map_name.size() + 1);
192*6777b538SAndroid Build Coastguard Worker     }
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker     if (!ReadElfBuildId(next_entry.addr, false, next_entry.build_id)) {
195*6777b538SAndroid Build Coastguard Worker       LOG(WARNING) << "Couldn't read build ID.";
196*6777b538SAndroid Build Coastguard Worker       continue;
197*6777b538SAndroid Build Coastguard Worker     }
198*6777b538SAndroid Build Coastguard Worker 
199*6777b538SAndroid Build Coastguard Worker     lmap = lmap->l_next;
200*6777b538SAndroid Build Coastguard Worker   }
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   valid_ = true;
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker // Returns true if |address| is contained by any of the memory regions
206*6777b538SAndroid Build Coastguard Worker // mapped for |module_entry|.
ModuleContainsFrameAddress(const void * address,const SymbolMap::Module & module_entry)207*6777b538SAndroid Build Coastguard Worker bool ModuleContainsFrameAddress(const void* address,
208*6777b538SAndroid Build Coastguard Worker                                 const SymbolMap::Module& module_entry) {
209*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < module_entry.segment_count; ++i) {
210*6777b538SAndroid Build Coastguard Worker     const SymbolMap::Segment& segment = module_entry.segments[i];
211*6777b538SAndroid Build Coastguard Worker     const void* segment_end = reinterpret_cast<const void*>(
212*6777b538SAndroid Build Coastguard Worker         reinterpret_cast<const char*>(segment.addr) + segment.size - 1);
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker     if (address >= segment.addr && address <= segment_end) {
215*6777b538SAndroid Build Coastguard Worker       return true;
216*6777b538SAndroid Build Coastguard Worker     }
217*6777b538SAndroid Build Coastguard Worker   }
218*6777b538SAndroid Build Coastguard Worker   return false;
219*6777b538SAndroid Build Coastguard Worker }
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker }  // namespace
222*6777b538SAndroid Build Coastguard Worker 
223*6777b538SAndroid Build Coastguard Worker // static
EnableInProcessStackDumping()224*6777b538SAndroid Build Coastguard Worker bool EnableInProcessStackDumping() {
225*6777b538SAndroid Build Coastguard Worker   // StackTrace works to capture the current stack (e.g. for diagnostics added
226*6777b538SAndroid Build Coastguard Worker   // to code), but for local capture and print of backtraces, we just let the
227*6777b538SAndroid Build Coastguard Worker   // system crashlogger take over. It handles printing out a nicely formatted
228*6777b538SAndroid Build Coastguard Worker   // backtrace with dso information, relative offsets, etc. that we can then
229*6777b538SAndroid Build Coastguard Worker   // filter with addr2line in the run script to get file/line info.
230*6777b538SAndroid Build Coastguard Worker   return true;
231*6777b538SAndroid Build Coastguard Worker }
232*6777b538SAndroid Build Coastguard Worker 
CollectStackTrace(const void ** trace,size_t count)233*6777b538SAndroid Build Coastguard Worker size_t CollectStackTrace(const void** trace, size_t count) {
234*6777b538SAndroid Build Coastguard Worker   size_t frame_count = 0;
235*6777b538SAndroid Build Coastguard Worker   BacktraceData data = {trace, &frame_count, count};
236*6777b538SAndroid Build Coastguard Worker   _Unwind_Backtrace(&UnwindStore, &data);
237*6777b538SAndroid Build Coastguard Worker   return frame_count;
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker 
240*6777b538SAndroid Build Coastguard Worker // static
PrintMessageWithPrefix(cstring_view prefix_string,cstring_view message)241*6777b538SAndroid Build Coastguard Worker void StackTrace::PrintMessageWithPrefix(cstring_view prefix_string,
242*6777b538SAndroid Build Coastguard Worker                                         cstring_view message) {
243*6777b538SAndroid Build Coastguard Worker   std::cerr << prefix_string << message;
244*6777b538SAndroid Build Coastguard Worker }
245*6777b538SAndroid Build Coastguard Worker 
PrintWithPrefixImpl(cstring_view prefix_string) const246*6777b538SAndroid Build Coastguard Worker void StackTrace::PrintWithPrefixImpl(cstring_view prefix_string) const {
247*6777b538SAndroid Build Coastguard Worker   OutputToStreamWithPrefixImpl(&std::cerr, prefix_string);
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker // Emits stack trace data using the symbolizer markup format specified at:
251*6777b538SAndroid Build Coastguard Worker // https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
OutputToStreamWithPrefixImpl(std::ostream * os,cstring_view prefix_string) const252*6777b538SAndroid Build Coastguard Worker void StackTrace::OutputToStreamWithPrefixImpl(
253*6777b538SAndroid Build Coastguard Worker     std::ostream* os,
254*6777b538SAndroid Build Coastguard Worker     cstring_view prefix_string) const {
255*6777b538SAndroid Build Coastguard Worker   SymbolMap map;
256*6777b538SAndroid Build Coastguard Worker 
257*6777b538SAndroid Build Coastguard Worker   int module_id = 0;
258*6777b538SAndroid Build Coastguard Worker   for (const SymbolMap::Module& module_entry : map.GetModules()) {
259*6777b538SAndroid Build Coastguard Worker     // Don't emit information on modules that aren't useful for the actual
260*6777b538SAndroid Build Coastguard Worker     // stack trace, so as to reduce the load on the symbolizer and syslog.
261*6777b538SAndroid Build Coastguard Worker     bool should_emit_module = false;
262*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < count_ && !should_emit_module; ++i) {
263*6777b538SAndroid Build Coastguard Worker       should_emit_module = ModuleContainsFrameAddress(trace_[i], module_entry);
264*6777b538SAndroid Build Coastguard Worker     }
265*6777b538SAndroid Build Coastguard Worker     if (!should_emit_module) {
266*6777b538SAndroid Build Coastguard Worker       continue;
267*6777b538SAndroid Build Coastguard Worker     }
268*6777b538SAndroid Build Coastguard Worker 
269*6777b538SAndroid Build Coastguard Worker     *os << "{{{module:" << module_id << ":" << module_entry.name
270*6777b538SAndroid Build Coastguard Worker         << ":elf:" << module_entry.build_id << "}}}\n";
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < module_entry.segment_count; ++i) {
273*6777b538SAndroid Build Coastguard Worker       const SymbolMap::Segment& segment = module_entry.segments[i];
274*6777b538SAndroid Build Coastguard Worker 
275*6777b538SAndroid Build Coastguard Worker       char permission_string[4] = {};
276*6777b538SAndroid Build Coastguard Worker       *os << "{{{mmap:" << segment.addr << ":0x" << std::hex << segment.size
277*6777b538SAndroid Build Coastguard Worker           << std::dec << ":load:" << module_id << ":"
278*6777b538SAndroid Build Coastguard Worker           << PermissionFlagsToString(segment.permission_flags,
279*6777b538SAndroid Build Coastguard Worker                                      permission_string)
280*6777b538SAndroid Build Coastguard Worker           << ":"
281*6777b538SAndroid Build Coastguard Worker           << "0x" << std::hex << segment.relative_addr << std::dec << "}}}\n";
282*6777b538SAndroid Build Coastguard Worker     }
283*6777b538SAndroid Build Coastguard Worker 
284*6777b538SAndroid Build Coastguard Worker     ++module_id;
285*6777b538SAndroid Build Coastguard Worker   }
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < count_; ++i)
288*6777b538SAndroid Build Coastguard Worker     *os << "{{{bt:" << i << ":" << trace_[i] << "}}}\n";
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker   *os << "{{{reset}}}\n";
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker 
293*6777b538SAndroid Build Coastguard Worker }  // namespace debug
294*6777b538SAndroid Build Coastguard Worker }  // namespace base
295