|  | // Copyright 2024 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/developer/debug/debug_agent/backtrace_utils.h" | 
|  |  | 
|  | #include <stdio.h>  // For fmemopen | 
|  |  | 
|  | #include "src/developer/debug/debug_agent/process_handle.h" | 
|  | #include "src/developer/debug/debug_agent/thread_handle.h" | 
|  | #include "zircon/system/ulib/inspector/include/inspector/inspector.h" | 
|  |  | 
|  | namespace debug_agent { | 
|  |  | 
|  | std::string GetBacktraceMarkupForThread(const ProcessHandle &process, const ThreadHandle &thread) { | 
|  | // Large binaries with lots of modules and deep stacks can produce quite a lot of markup text. 32k | 
|  | // should be more than enough and leaves plenty of room in the rest of the FIDL message. Once the | 
|  | // markup has been written to the string, we trim off the unused bytes below. | 
|  | constexpr size_t kMarkupBufferMaxSize = 32768; | 
|  | std::string backtrace_markup(kMarkupBufferMaxSize, 0); | 
|  |  | 
|  | FILE *out = fmemopen(backtrace_markup.data(), backtrace_markup.size(), "w"); | 
|  | fprintf(out, "{{{reset:begin}}}"); | 
|  | inspector_print_markup_context(out, process.GetNativeHandle().get()); | 
|  | inspector_print_backtrace_markup(out, process.GetNativeHandle().get(), | 
|  | thread.GetNativeHandle().get()); | 
|  | fprintf(out, "{{{reset:end}}}"); | 
|  |  | 
|  | // The current position of the stream will tell us how large the string really needs to be. If | 
|  | // we end up needing to pack multiple backtrace markups in a single response message, this will | 
|  | // make sure there's no wasted space. | 
|  | auto final_pos = ftell(out); | 
|  |  | 
|  | fclose(out); | 
|  |  | 
|  | backtrace_markup.resize(final_pos); | 
|  | backtrace_markup.push_back('\0'); | 
|  |  | 
|  | return backtrace_markup; | 
|  | } | 
|  |  | 
|  | }  // namespace debug_agent |