void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, llvm::StringRef function) { Flags options = GetOptions(); static uint32_t g_sequence_id = 0; // Add a sequence ID if requested if (options.Test(LLDB_LOG_OPTION_PREPEND_SEQUENCE)) OS << ++g_sequence_id << " "; // Timestamp if requested if (options.Test(LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) { auto now = std::chrono::duration<double>( std::chrono::system_clock::now().time_since_epoch()); OS << llvm::formatv("{0:f9} ", now.count()); } // Add the process and thread if requested if (options.Test(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD)) OS << llvm::formatv("[{0,0+4}/{1,0+4}] ", getpid(), llvm::get_threadid()); // Add the thread name if requested if (options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) { llvm::SmallString<32> thread_name; llvm::get_thread_name(thread_name); llvm::SmallString<12> format_str; llvm::raw_svector_ostream format_os(format_str); format_os << "{0,-" << llvm::alignTo<16>(thread_name.size()) << "} "; OS << llvm::formatv(format_str.c_str(), thread_name); } if (options.Test(LLDB_LOG_OPTION_BACKTRACE)) llvm::sys::PrintStackTrace(OS); if (options.Test(LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION) && (!file.empty() || !function.empty())) { file = llvm::sys::path::filename(file).take_front(40); function = function.take_front(40); OS << llvm::formatv("{0,-60:60} ", (file + ":" + function).str()); } }
lldb::OptionValueSP OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx, llvm::StringRef name, bool will_modify, Error &error) const { lldb::OptionValueSP value_sp; if (name.empty()) return OptionValueSP(); llvm::StringRef sub_name; ConstString key; size_t key_len = name.find_first_of(".[{"); if (key_len != llvm::StringRef::npos) { key.SetString(name.take_front(key_len)); sub_name = name.drop_front(key_len); } else key.SetString(name); value_sp = GetValueForKey(exe_ctx, key, will_modify); if (sub_name.empty() || !value_sp) return value_sp; switch (sub_name[0]) { case '.': { lldb::OptionValueSP return_val_sp; return_val_sp = value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), will_modify, error); if (!return_val_sp) { if (Properties::IsSettingExperimental(sub_name.drop_front())) { size_t experimental_len = strlen(Properties::GetExperimentalSettingsName()); if (sub_name[experimental_len + 1] == '.') return_val_sp = value_sp->GetSubValue( exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, error); // It isn't an error if an experimental setting is not present. if (!return_val_sp) error.Clear(); } } return return_val_sp; } case '{': // Predicate matching for predicates like // "<setting-name>{<predicate>}" // strings are parsed by the current OptionValueProperties subclass // to mean whatever they want to. For instance a subclass of // OptionValueProperties for a lldb_private::Target might implement: // "target.run-args{arch==i386}" -- only set run args if the arch is // i386 // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the // path matches // "target.run-args{basename==test&&arch==x86_64}" -- only set run args // if executable basename is "test" and arch is "x86_64" if (sub_name[1]) { llvm::StringRef predicate_start = sub_name.drop_front(); size_t pos = predicate_start.find_first_of('}'); if (pos != llvm::StringRef::npos) { auto predicate = predicate_start.take_front(pos); auto rest = predicate_start.drop_front(pos); if (PredicateMatches(exe_ctx, predicate)) { if (!rest.empty()) { // Still more subvalue string to evaluate return value_sp->GetSubValue(exe_ctx, rest, will_modify, error); } else { // We have a match! break; } } } } // Predicate didn't match or wasn't correctly formed value_sp.reset(); break; case '[': // Array or dictionary access for subvalues like: // "[12]" -- access 12th array element // "['hello']" -- dictionary access of key named hello return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error); default: value_sp.reset(); break; } return value_sp; }
static void demangle(llvm::raw_ostream &os, llvm::StringRef name, swift::Demangle::Context &DCtx, const swift::Demangle::DemangleOptions &options) { bool hadLeadingUnderscore = false; if (name.startswith("__")) { hadLeadingUnderscore = true; name = name.substr(1); } swift::Demangle::NodePointer pointer = DCtx.demangleSymbolAsNode(name); if (ExpandMode || TreeOnly) { llvm::outs() << "Demangling for " << name << '\n'; llvm::outs() << getNodeTreeAsString(pointer); } if (RemangleMode) { std::string remangled; if (!pointer || !(name.startswith(MANGLING_PREFIX_STR) || name.startswith("_S"))) { // Just reprint the original mangled name if it didn't demangle or is in // the old mangling scheme. // This makes it easier to share the same database between the // mangling and demangling tests. remangled = name; } else { remangled = swift::Demangle::mangleNode(pointer); unsigned prefixLen = swift::Demangle::getManglingPrefixLength(remangled); assert(prefixLen > 0); // Replace the prefix if we remangled with a different prefix. if (!name.startswith(remangled.substr(0, prefixLen))) { unsigned namePrefixLen = swift::Demangle::getManglingPrefixLength(name); assert(namePrefixLen > 0); remangled = name.take_front(namePrefixLen).str() + remangled.substr(prefixLen); } if (name != remangled) { llvm::errs() << "\nError: re-mangled name \n " << remangled << "\ndoes not match original name\n " << name << '\n'; exit(1); } } if (hadLeadingUnderscore) llvm::outs() << '_'; llvm::outs() << remangled; return; } else if (RemangleRtMode) { std::string remangled = name; if (pointer) { remangled = swift::Demangle::mangleNodeOld(pointer); } llvm::outs() << remangled; } if (!TreeOnly) { if (RemangleNew) { if (!pointer) { llvm::errs() << "Can't de-mangle " << name << '\n'; exit(1); } std::string remangled = swift::Demangle::mangleNode(pointer); llvm::outs() << remangled; return; } std::string string = swift::Demangle::nodeToString(pointer, options); if (!CompactMode) llvm::outs() << name << " ---> "; if (Classify) { std::string Classifications; if (!swift::Demangle::isSwiftSymbol(name)) Classifications += 'N'; if (DCtx.isThunkSymbol(name)) { if (!Classifications.empty()) Classifications += ','; Classifications += "T:"; Classifications += DCtx.getThunkTarget(name); } else { assert(DCtx.getThunkTarget(name).empty()); } if (pointer && !DCtx.hasSwiftCallingConvention(name)) { if (!Classifications.empty()) Classifications += ','; Classifications += 'C'; } if (!Classifications.empty()) llvm::outs() << '{' << Classifications << "} "; } llvm::outs() << (string.empty() ? name : llvm::StringRef(string)); } DCtx.clear(); }