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
This commit is contained in:
Michael Sartain 2013-07-30 16:44:36 +00:00
parent 788d126ca1
commit 0769b2b1f3
2 changed files with 169 additions and 111 deletions

View File

@ -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 <typename T>
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("<error: %s>",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("<error: %s>",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("<error: %s>",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("<error: %s>",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("<error: %s>",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)

View File

@ -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;