From 0769b2b1f35123482ef67abf9f926bb75504906a Mon Sep 17 00:00:00 2001 From: Michael Sartain Date: Tue, 30 Jul 2013 16:44:36 +0000 Subject: [PATCH] Add format specifiers to various format ids so we can print thread ids in decimal on Linux and FreeBSD. CC: emaste Differential Revision: http://llvm-reviews.chandlerc.com/D1234 llvm-svn: 187425 --- lldb/source/Core/Debugger.cpp | 276 +++++++++++++-------- .../source/Interpreter/ScriptInterpreterPython.cpp | 4 +- 2 files changed, 169 insertions(+), 111 deletions(-) diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index f3ee4a8..d1d2ebb 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -99,12 +99,12 @@ g_language_enumerators[] = #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" -#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\ +#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ "{, ${frame.pc}}"\ MODULE_WITH_FUNC\ FILE_AND_LINE\ - "{, name = '${thread.name}}"\ - "{, queue = '${thread.queue}}"\ + "{, name = '${thread.name}'}"\ + "{, queue = '${thread.queue}'}"\ "{, stop reason = ${thread.stop-reason}}"\ "{\\nReturn value: ${thread.return-value}}"\ "\\n" @@ -1326,6 +1326,27 @@ ScanBracketedRange (const char* var_name_begin, return true; } +template +static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) +{ + if (script_interpreter) + { + Error script_error; + std::string script_output; + + if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) + { + s.Printf("%s", script_output.c_str()); + return true; + } + else + { + s.Printf("",script_error.AsCString()); + } + } + return false; +} + static ValueObjectSP ExpandIndexedExpression (ValueObject* valobj, size_t index, @@ -1366,6 +1387,82 @@ ExpandIndexedExpression (ValueObject* valobj, return item; } +static inline bool +IsToken(const char *var_name_begin, const char *var) +{ + return (::strncmp (var_name_begin, var, strlen(var)) == 0); +} + +static bool +IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, + const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) +{ + int var_len = strlen(var); + if (::strncmp (var_name_begin, var, var_len) == 0) + { + var_name_begin += var_len; + if (*var_name_begin == '}') + { + format = default_format; + return true; + } + else if (*var_name_begin == '%') + { + // Allow format specifiers: x|X|u with optional width specifiers. + // ${thread.id%x} ; hex + // ${thread.id%X} ; uppercase hex + // ${thread.id%u} ; unsigned decimal + // ${thread.id%8.8X} ; width.precision + specifier + // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) + int dot_count = 0; + const char *specifier = NULL; + int width_precision_length = 0; + const char *width_precision = ++var_name_begin; + while (isdigit(*var_name_begin) || *var_name_begin == '.') + { + dot_count += (*var_name_begin == '.'); + if (dot_count > 1) + break; + var_name_begin++; + width_precision_length++; + } + + if (IsToken (var_name_begin, "tid}")) + { + Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); + if (target) + { + ArchSpec arch (target->GetArchitecture ()); + llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; + if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) + specifier = PRIu64; + } + if (!specifier) + { + format = default_format; + return true; + } + } + else if (IsToken (var_name_begin, "x}")) + specifier = PRIx64; + else if (IsToken (var_name_begin, "X}")) + specifier = PRIX64; + else if (IsToken (var_name_begin, "u}")) + specifier = PRIu64; + + if (specifier) + { + format = "%"; + if (width_precision_length) + format += std::string(width_precision, width_precision_length); + format += specifier; + return true; + } + } + } + return false; +} + static bool FormatPromptRecurse ( @@ -1449,6 +1546,7 @@ FormatPromptRecurse if (success) { const char *cstr = NULL; + std::string token_format; Address format_addr; bool calculate_format_addr_function_offset = false; // Set reg_kind and reg_num to invalid values @@ -1522,13 +1620,13 @@ FormatPromptRecurse if (!valobj) break; // simplest case ${var}, just print valobj's value - if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) + if (IsToken (var_name_begin, "var}")) { was_plain_var = true; target = valobj; val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; } - else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) + else if (IsToken (var_name_begin,"var%")) { was_var_format = true; // this is a variable with some custom format applied to it @@ -1543,9 +1641,9 @@ FormatPromptRecurse &val_obj_display); } // this is ${var.something} or multiple .something nested - else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) + else if (IsToken (var_name_begin, "var")) { - if (::strncmp(var_name_begin, "var[", strlen("var[")) == 0) + if (IsToken (var_name_begin, "var[")) was_var_indexed = true; const char* percent_position; ScanFormatDescriptor (var_name_begin, @@ -1770,7 +1868,7 @@ FormatPromptRecurse } break; case 'a': - if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) + if (IsToken (var_name_begin, "addr}")) { if (addr && addr->IsValid()) { @@ -1781,7 +1879,7 @@ FormatPromptRecurse break; case 'p': - if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0) + if (IsToken (var_name_begin, "process.")) { if (exe_ctx) { @@ -1789,14 +1887,14 @@ FormatPromptRecurse if (process) { var_name_begin += ::strlen ("process."); - if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) + if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) { - s.Printf("%" PRIu64, process->GetID()); + s.Printf(token_format.c_str(), process->GetID()); var_success = true; } - else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) || - (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) || - (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0)) + else if ((IsToken (var_name_begin, "name}")) || + (IsToken (var_name_begin, "file.basename}")) || + (IsToken (var_name_begin, "file.fullpath}"))) { Module *exe_module = process->GetTarget().GetExecutableModulePointer(); if (exe_module) @@ -1813,23 +1911,13 @@ FormatPromptRecurse } } } - else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0) + else if (IsToken (var_name_begin, "script:")) { var_name_begin += ::strlen("script:"); std::string script_name(var_name_begin,var_name_end); ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (script_interpreter) - { - std::string script_output; - Error script_error; - if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), process,script_output,script_error) && script_error.Success()) - { - s.Printf("%s", script_output.c_str()); - var_success = true; - } - else - s.Printf("",script_error.AsCString()); - } + if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) + var_success = true; } } } @@ -1837,7 +1925,7 @@ FormatPromptRecurse break; case 't': - if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0) + if (IsToken (var_name_begin, "thread.")) { if (exe_ctx) { @@ -1845,36 +1933,36 @@ FormatPromptRecurse if (thread) { var_name_begin += ::strlen ("thread."); - if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) + if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) { - s.Printf("0x%4.4" PRIx64, thread->GetID()); + s.Printf(token_format.c_str(), thread->GetID()); var_success = true; } - else if (::strncmp (var_name_begin, "protocol_id}", strlen("protocol_id}")) == 0) + else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) { - s.Printf("0x%4.4" PRIx64, thread->GetProtocolID()); + s.Printf(token_format.c_str(), thread->GetProtocolID()); var_success = true; } - else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) + else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) { - s.Printf("%u", thread->GetIndexID()); + s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); var_success = true; } - else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) + else if (IsToken (var_name_begin, "name}")) { cstr = thread->GetName(); var_success = cstr && cstr[0]; if (var_success) s.PutCString(cstr); } - else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0) + else if (IsToken (var_name_begin, "queue}")) { cstr = thread->GetQueueName(); var_success = cstr && cstr[0]; if (var_success) s.PutCString(cstr); } - else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0) + else if (IsToken (var_name_begin, "stop-reason}")) { StopInfoSP stop_info_sp = thread->GetStopInfo (); if (stop_info_sp && stop_info_sp->IsValid()) @@ -1887,7 +1975,7 @@ FormatPromptRecurse } } } - else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0) + else if (IsToken (var_name_begin, "return-value}")) { StopInfoSP stop_info_sp = thread->GetStopInfo (); if (stop_info_sp && stop_info_sp->IsValid()) @@ -1900,28 +1988,18 @@ FormatPromptRecurse } } } - else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0) + else if (IsToken (var_name_begin, "script:")) { var_name_begin += ::strlen("script:"); std::string script_name(var_name_begin,var_name_end); ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (script_interpreter) - { - std::string script_output; - Error script_error; - if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), thread,script_output,script_error) && script_error.Success()) - { - s.Printf("%s", script_output.c_str()); - var_success = true; - } - else - s.Printf("",script_error.AsCString()); - } + if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) + var_success = true; } } } } - else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0) + else if (IsToken (var_name_begin, "target.")) { // TODO: hookup properties // if (!target_properties_sp) @@ -1950,7 +2028,7 @@ FormatPromptRecurse if (target) { var_name_begin += ::strlen ("target."); - if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0) + if (IsToken (var_name_begin, "arch}")) { ArchSpec arch (target->GetArchitecture ()); if (arch.IsValid()) @@ -1959,23 +2037,13 @@ FormatPromptRecurse var_success = true; } } - else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0) + else if (IsToken (var_name_begin, "script:")) { var_name_begin += ::strlen("script:"); std::string script_name(var_name_begin,var_name_end); ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (script_interpreter) - { - std::string script_output; - Error script_error; - if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), target,script_output,script_error) && script_error.Success()) - { - s.Printf("%s", script_output.c_str()); - var_success = true; - } - else - s.Printf("",script_error.AsCString()); - } + if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) + var_success = true; } } } @@ -1983,25 +2051,25 @@ FormatPromptRecurse case 'm': - if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0) + if (IsToken (var_name_begin, "module.")) { if (sc && sc->module_sp.get()) { Module *module = sc->module_sp.get(); var_name_begin += ::strlen ("module."); - if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) + if (IsToken (var_name_begin, "file.")) { if (module->GetFileSpec()) { var_name_begin += ::strlen ("file."); - if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) + if (IsToken (var_name_begin, "basename}")) { format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); var_success = format_file_spec; } - else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) + else if (IsToken (var_name_begin, "fullpath}")) { format_file_spec = module->GetFileSpec(); var_success = format_file_spec; @@ -2014,25 +2082,25 @@ FormatPromptRecurse case 'f': - if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) + if (IsToken (var_name_begin, "file.")) { if (sc && sc->comp_unit != NULL) { var_name_begin += ::strlen ("file."); - if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) + if (IsToken (var_name_begin, "basename}")) { format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); var_success = format_file_spec; } - else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) + else if (IsToken (var_name_begin, "fullpath}")) { format_file_spec = *sc->comp_unit; var_success = format_file_spec; } } } - else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0) + else if (IsToken (var_name_begin, "frame.")) { if (exe_ctx) { @@ -2040,36 +2108,36 @@ FormatPromptRecurse if (frame) { var_name_begin += ::strlen ("frame."); - if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) + if (IsToken (var_name_begin, "index}")) { s.Printf("%u", frame->GetFrameIndex()); var_success = true; } - else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0) + else if (IsToken (var_name_begin, "pc}")) { reg_kind = eRegisterKindGeneric; reg_num = LLDB_REGNUM_GENERIC_PC; var_success = true; } - else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0) + else if (IsToken (var_name_begin, "sp}")) { reg_kind = eRegisterKindGeneric; reg_num = LLDB_REGNUM_GENERIC_SP; var_success = true; } - else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0) + else if (IsToken (var_name_begin, "fp}")) { reg_kind = eRegisterKindGeneric; reg_num = LLDB_REGNUM_GENERIC_FP; var_success = true; } - else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0) + else if (IsToken (var_name_begin, "flags}")) { reg_kind = eRegisterKindGeneric; reg_num = LLDB_REGNUM_GENERIC_FLAGS; var_success = true; } - else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0) + else if (IsToken (var_name_begin, "reg.")) { reg_ctx = frame->GetRegisterContext().get(); if (reg_ctx) @@ -2084,33 +2152,23 @@ FormatPromptRecurse } } } - else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0) + else if (IsToken (var_name_begin, "script:")) { var_name_begin += ::strlen("script:"); std::string script_name(var_name_begin,var_name_end); ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (script_interpreter) - { - std::string script_output; - Error script_error; - if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), frame,script_output,script_error) && script_error.Success()) - { - s.Printf("%s", script_output.c_str()); - var_success = true; - } - else - s.Printf("",script_error.AsCString()); - } + if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) + var_success = true; } } } } - else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0) + else if (IsToken (var_name_begin, "function.")) { if (sc && (sc->function != NULL || sc->symbol != NULL)) { var_name_begin += ::strlen ("function."); - if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) + if (IsToken (var_name_begin, "id}")) { if (sc->function) s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); @@ -2119,7 +2177,7 @@ FormatPromptRecurse var_success = true; } - else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) + else if (IsToken (var_name_begin, "name}")) { if (sc->function) cstr = sc->function->GetName().AsCString (NULL); @@ -2145,7 +2203,7 @@ FormatPromptRecurse var_success = true; } } - else if (::strncmp (var_name_begin, "name-with-args}", strlen("name-with-args}")) == 0) + else if (IsToken (var_name_begin, "name-with-args}")) { // Print the function name with arguments in it @@ -2193,7 +2251,7 @@ FormatPromptRecurse const char *close_paren = NULL; if (open_paren) { - if (strncmp(open_paren, "(anonymous namespace)", strlen("(anonymous namespace)")) == 0) + if (IsToken (open_paren, "(anonymous namespace)")) { open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); if (open_paren) @@ -2252,7 +2310,7 @@ FormatPromptRecurse } } } - else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0) + else if (IsToken (var_name_begin, "addr-offset}")) { var_success = addr != NULL; if (var_success) @@ -2261,7 +2319,7 @@ FormatPromptRecurse calculate_format_addr_function_offset = true; } } - else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0) + else if (IsToken (var_name_begin, "line-offset}")) { var_success = sc->line_entry.range.GetBaseAddress().IsValid(); if (var_success) @@ -2270,7 +2328,7 @@ FormatPromptRecurse calculate_format_addr_function_offset = true; } } - else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0) + else if (IsToken (var_name_begin, "pc-offset}")) { StackFrame *frame = exe_ctx->GetFramePtr(); var_success = frame != NULL; @@ -2285,33 +2343,33 @@ FormatPromptRecurse break; case 'l': - if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0) + if (IsToken (var_name_begin, "line.")) { if (sc && sc->line_entry.IsValid()) { var_name_begin += ::strlen ("line."); - if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) + if (IsToken (var_name_begin, "file.")) { var_name_begin += ::strlen ("file."); - if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) + if (IsToken (var_name_begin, "basename}")) { format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); var_success = format_file_spec; } - else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) + else if (IsToken (var_name_begin, "fullpath}")) { format_file_spec = sc->line_entry.file; var_success = format_file_spec; } } - else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0) + else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) { var_success = true; - s.Printf("%u", sc->line_entry.line); + s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); } - else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) || - (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0)) + else if ((IsToken (var_name_begin, "start-addr}")) || + (IsToken (var_name_begin, "end-addr}"))) { var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); if (var_success) diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 6841497..9d9b8d9 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -2685,7 +2685,7 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, error.SetErrorString("no function to execute"); return false; } - if (!g_swig_run_script_keyword_thread) + if (!g_swig_run_script_keyword_target) { error.SetErrorString("internal helper function missing"); return false; @@ -2717,7 +2717,7 @@ ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, error.SetErrorString("no function to execute"); return false; } - if (!g_swig_run_script_keyword_thread) + if (!g_swig_run_script_keyword_frame) { error.SetErrorString("internal helper function missing"); return false; -- 2.7.4