1 //===-- LLDBServerUtilities.cpp ---------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "LLDBServerUtilities.h" 10 11 #include "lldb/Utility/Args.h" 12 #include "lldb/Utility/Log.h" 13 #include "lldb/Utility/StreamString.h" 14 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Support/FileSystem.h" 18 19 using namespace lldb; 20 using namespace lldb_private::lldb_server; 21 using namespace lldb_private; 22 using namespace llvm; 23 24 class TestLogHandler : public LogHandler { 25 public: 26 TestLogHandler(std::shared_ptr<llvm::raw_ostream> stream_sp) 27 : m_stream_sp(stream_sp) {} 28 29 void Emit(llvm::StringRef message) override { 30 (*m_stream_sp) << message; 31 m_stream_sp->flush(); 32 } 33 34 private: 35 std::shared_ptr<raw_ostream> m_stream_sp; 36 }; 37 38 static std::shared_ptr<TestLogHandler> GetLogStream(StringRef log_file) { 39 if (!log_file.empty()) { 40 std::error_code EC; 41 auto stream_sp = std::make_shared<raw_fd_ostream>( 42 log_file, EC, sys::fs::OF_TextWithCRLF | sys::fs::OF_Append); 43 if (!EC) 44 return std::make_shared<TestLogHandler>(stream_sp); 45 errs() << llvm::formatv( 46 "Failed to open log file `{0}`: {1}\nWill log to stderr instead.\n", 47 log_file, EC.message()); 48 } 49 // No need to delete the stderr stream. 50 return std::make_shared<TestLogHandler>( 51 std::shared_ptr<raw_ostream>(&errs(), [](raw_ostream *) {})); 52 } 53 54 bool LLDBServerUtilities::SetupLogging(const std::string &log_file, 55 const StringRef &log_channels, 56 uint32_t log_options) { 57 58 auto log_stream_sp = GetLogStream(log_file); 59 60 SmallVector<StringRef, 32> channel_array; 61 log_channels.split(channel_array, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false); 62 for (auto channel_with_categories : channel_array) { 63 std::string error; 64 llvm::raw_string_ostream error_stream(error); 65 Args channel_then_categories(channel_with_categories); 66 std::string channel(channel_then_categories.GetArgumentAtIndex(0)); 67 channel_then_categories.Shift(); // Shift off the channel 68 69 bool success = Log::EnableLogChannel( 70 log_stream_sp, log_options, channel, 71 channel_then_categories.GetArgumentArrayRef(), error_stream); 72 if (!success) { 73 errs() << formatv("Unable to setup logging for channel \"{0}\": {1}", 74 channel, error_stream.str()); 75 return false; 76 } 77 } 78 return true; 79 } 80