15ffd83dbSDimitry Andric //===-- InstrumentationRuntimeTSan.cpp ------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "InstrumentationRuntimeTSan.h" 105ffd83dbSDimitry Andric 115ffd83dbSDimitry Andric #include "Plugins/Process/Utility/HistoryThread.h" 125ffd83dbSDimitry Andric #include "lldb/Breakpoint/StoppointCallbackContext.h" 135ffd83dbSDimitry Andric #include "lldb/Core/Debugger.h" 145ffd83dbSDimitry Andric #include "lldb/Core/Module.h" 155ffd83dbSDimitry Andric #include "lldb/Core/PluginInterface.h" 165ffd83dbSDimitry Andric #include "lldb/Core/PluginManager.h" 175ffd83dbSDimitry Andric #include "lldb/Core/StreamFile.h" 185ffd83dbSDimitry Andric #include "lldb/Core/ValueObject.h" 195ffd83dbSDimitry Andric #include "lldb/Expression/UserExpression.h" 205ffd83dbSDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 215ffd83dbSDimitry Andric #include "lldb/Symbol/Symbol.h" 225ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolContext.h" 235ffd83dbSDimitry Andric #include "lldb/Symbol/Variable.h" 245ffd83dbSDimitry Andric #include "lldb/Symbol/VariableList.h" 255ffd83dbSDimitry Andric #include "lldb/Target/InstrumentationRuntimeStopInfo.h" 265ffd83dbSDimitry Andric #include "lldb/Target/SectionLoadList.h" 275ffd83dbSDimitry Andric #include "lldb/Target/StopInfo.h" 285ffd83dbSDimitry Andric #include "lldb/Target/Target.h" 295ffd83dbSDimitry Andric #include "lldb/Target/Thread.h" 305ffd83dbSDimitry Andric #include "lldb/Utility/RegularExpression.h" 315ffd83dbSDimitry Andric #include "lldb/Utility/Stream.h" 325ffd83dbSDimitry Andric 335ffd83dbSDimitry Andric #include <memory> 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric using namespace lldb; 365ffd83dbSDimitry Andric using namespace lldb_private; 375ffd83dbSDimitry Andric 385ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(InstrumentationRuntimeTSan) 395ffd83dbSDimitry Andric 405ffd83dbSDimitry Andric lldb::InstrumentationRuntimeSP 415ffd83dbSDimitry Andric InstrumentationRuntimeTSan::CreateInstance(const lldb::ProcessSP &process_sp) { 425ffd83dbSDimitry Andric return InstrumentationRuntimeSP(new InstrumentationRuntimeTSan(process_sp)); 435ffd83dbSDimitry Andric } 445ffd83dbSDimitry Andric 455ffd83dbSDimitry Andric void InstrumentationRuntimeTSan::Initialize() { 465ffd83dbSDimitry Andric PluginManager::RegisterPlugin( 475ffd83dbSDimitry Andric GetPluginNameStatic(), "ThreadSanitizer instrumentation runtime plugin.", 485ffd83dbSDimitry Andric CreateInstance, GetTypeStatic); 495ffd83dbSDimitry Andric } 505ffd83dbSDimitry Andric 515ffd83dbSDimitry Andric void InstrumentationRuntimeTSan::Terminate() { 525ffd83dbSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 535ffd83dbSDimitry Andric } 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric lldb_private::ConstString InstrumentationRuntimeTSan::GetPluginNameStatic() { 565ffd83dbSDimitry Andric return ConstString("ThreadSanitizer"); 575ffd83dbSDimitry Andric } 585ffd83dbSDimitry Andric 595ffd83dbSDimitry Andric lldb::InstrumentationRuntimeType InstrumentationRuntimeTSan::GetTypeStatic() { 605ffd83dbSDimitry Andric return eInstrumentationRuntimeTypeThreadSanitizer; 615ffd83dbSDimitry Andric } 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric InstrumentationRuntimeTSan::~InstrumentationRuntimeTSan() { Deactivate(); } 645ffd83dbSDimitry Andric 655ffd83dbSDimitry Andric const char *thread_sanitizer_retrieve_report_data_prefix = R"( 665ffd83dbSDimitry Andric extern "C" 675ffd83dbSDimitry Andric { 685ffd83dbSDimitry Andric void *__tsan_get_current_report(); 695ffd83dbSDimitry Andric int __tsan_get_report_data(void *report, const char **description, int *count, 705ffd83dbSDimitry Andric int *stack_count, int *mop_count, int *loc_count, 715ffd83dbSDimitry Andric int *mutex_count, int *thread_count, 725ffd83dbSDimitry Andric int *unique_tid_count, void **sleep_trace, 735ffd83dbSDimitry Andric unsigned long trace_size); 745ffd83dbSDimitry Andric int __tsan_get_report_stack(void *report, unsigned long idx, void **trace, 755ffd83dbSDimitry Andric unsigned long trace_size); 765ffd83dbSDimitry Andric int __tsan_get_report_mop(void *report, unsigned long idx, int *tid, void **addr, 775ffd83dbSDimitry Andric int *size, int *write, int *atomic, void **trace, 785ffd83dbSDimitry Andric unsigned long trace_size); 795ffd83dbSDimitry Andric int __tsan_get_report_loc(void *report, unsigned long idx, const char **type, 805ffd83dbSDimitry Andric void **addr, unsigned long *start, unsigned long *size, int *tid, 815ffd83dbSDimitry Andric int *fd, int *suppressable, void **trace, 825ffd83dbSDimitry Andric unsigned long trace_size); 835ffd83dbSDimitry Andric int __tsan_get_report_mutex(void *report, unsigned long idx, unsigned long *mutex_id, void **addr, 845ffd83dbSDimitry Andric int *destroyed, void **trace, unsigned long trace_size); 855ffd83dbSDimitry Andric int __tsan_get_report_thread(void *report, unsigned long idx, int *tid, unsigned long *os_id, 865ffd83dbSDimitry Andric int *running, const char **name, int *parent_tid, 875ffd83dbSDimitry Andric void **trace, unsigned long trace_size); 885ffd83dbSDimitry Andric int __tsan_get_report_unique_tid(void *report, unsigned long idx, int *tid); 895ffd83dbSDimitry Andric 905ffd83dbSDimitry Andric // TODO: dlsym won't work on Windows. 915ffd83dbSDimitry Andric void *dlsym(void* handle, const char* symbol); 925ffd83dbSDimitry Andric int (*ptr__tsan_get_report_loc_object_type)(void *report, unsigned long idx, const char **object_type); 935ffd83dbSDimitry Andric } 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric const int REPORT_TRACE_SIZE = 128; 965ffd83dbSDimitry Andric const int REPORT_ARRAY_SIZE = 4; 975ffd83dbSDimitry Andric 985ffd83dbSDimitry Andric struct data { 995ffd83dbSDimitry Andric void *report; 1005ffd83dbSDimitry Andric const char *description; 1015ffd83dbSDimitry Andric int report_count; 1025ffd83dbSDimitry Andric 1035ffd83dbSDimitry Andric void *sleep_trace[REPORT_TRACE_SIZE]; 1045ffd83dbSDimitry Andric 1055ffd83dbSDimitry Andric int stack_count; 1065ffd83dbSDimitry Andric struct { 1075ffd83dbSDimitry Andric int idx; 1085ffd83dbSDimitry Andric void *trace[REPORT_TRACE_SIZE]; 1095ffd83dbSDimitry Andric } stacks[REPORT_ARRAY_SIZE]; 1105ffd83dbSDimitry Andric 1115ffd83dbSDimitry Andric int mop_count; 1125ffd83dbSDimitry Andric struct { 1135ffd83dbSDimitry Andric int idx; 1145ffd83dbSDimitry Andric int tid; 1155ffd83dbSDimitry Andric int size; 1165ffd83dbSDimitry Andric int write; 1175ffd83dbSDimitry Andric int atomic; 1185ffd83dbSDimitry Andric void *addr; 1195ffd83dbSDimitry Andric void *trace[REPORT_TRACE_SIZE]; 1205ffd83dbSDimitry Andric } mops[REPORT_ARRAY_SIZE]; 1215ffd83dbSDimitry Andric 1225ffd83dbSDimitry Andric int loc_count; 1235ffd83dbSDimitry Andric struct { 1245ffd83dbSDimitry Andric int idx; 1255ffd83dbSDimitry Andric const char *type; 1265ffd83dbSDimitry Andric void *addr; 1275ffd83dbSDimitry Andric unsigned long start; 1285ffd83dbSDimitry Andric unsigned long size; 1295ffd83dbSDimitry Andric int tid; 1305ffd83dbSDimitry Andric int fd; 1315ffd83dbSDimitry Andric int suppressable; 1325ffd83dbSDimitry Andric void *trace[REPORT_TRACE_SIZE]; 1335ffd83dbSDimitry Andric const char *object_type; 1345ffd83dbSDimitry Andric } locs[REPORT_ARRAY_SIZE]; 1355ffd83dbSDimitry Andric 1365ffd83dbSDimitry Andric int mutex_count; 1375ffd83dbSDimitry Andric struct { 1385ffd83dbSDimitry Andric int idx; 1395ffd83dbSDimitry Andric unsigned long mutex_id; 1405ffd83dbSDimitry Andric void *addr; 1415ffd83dbSDimitry Andric int destroyed; 1425ffd83dbSDimitry Andric void *trace[REPORT_TRACE_SIZE]; 1435ffd83dbSDimitry Andric } mutexes[REPORT_ARRAY_SIZE]; 1445ffd83dbSDimitry Andric 1455ffd83dbSDimitry Andric int thread_count; 1465ffd83dbSDimitry Andric struct { 1475ffd83dbSDimitry Andric int idx; 1485ffd83dbSDimitry Andric int tid; 1495ffd83dbSDimitry Andric unsigned long os_id; 1505ffd83dbSDimitry Andric int running; 1515ffd83dbSDimitry Andric const char *name; 1525ffd83dbSDimitry Andric int parent_tid; 1535ffd83dbSDimitry Andric void *trace[REPORT_TRACE_SIZE]; 1545ffd83dbSDimitry Andric } threads[REPORT_ARRAY_SIZE]; 1555ffd83dbSDimitry Andric 1565ffd83dbSDimitry Andric int unique_tid_count; 1575ffd83dbSDimitry Andric struct { 1585ffd83dbSDimitry Andric int idx; 1595ffd83dbSDimitry Andric int tid; 1605ffd83dbSDimitry Andric } unique_tids[REPORT_ARRAY_SIZE]; 1615ffd83dbSDimitry Andric }; 1625ffd83dbSDimitry Andric )"; 1635ffd83dbSDimitry Andric 1645ffd83dbSDimitry Andric const char *thread_sanitizer_retrieve_report_data_command = R"( 1655ffd83dbSDimitry Andric data t = {0}; 1665ffd83dbSDimitry Andric 1675ffd83dbSDimitry Andric ptr__tsan_get_report_loc_object_type = (typeof(ptr__tsan_get_report_loc_object_type))(void *)dlsym((void*)-2 /*RTLD_DEFAULT*/, "__tsan_get_report_loc_object_type"); 1685ffd83dbSDimitry Andric 1695ffd83dbSDimitry Andric t.report = __tsan_get_current_report(); 1705ffd83dbSDimitry Andric __tsan_get_report_data(t.report, &t.description, &t.report_count, &t.stack_count, &t.mop_count, &t.loc_count, &t.mutex_count, &t.thread_count, &t.unique_tid_count, t.sleep_trace, REPORT_TRACE_SIZE); 1715ffd83dbSDimitry Andric 1725ffd83dbSDimitry Andric if (t.stack_count > REPORT_ARRAY_SIZE) t.stack_count = REPORT_ARRAY_SIZE; 1735ffd83dbSDimitry Andric for (int i = 0; i < t.stack_count; i++) { 1745ffd83dbSDimitry Andric t.stacks[i].idx = i; 1755ffd83dbSDimitry Andric __tsan_get_report_stack(t.report, i, t.stacks[i].trace, REPORT_TRACE_SIZE); 1765ffd83dbSDimitry Andric } 1775ffd83dbSDimitry Andric 1785ffd83dbSDimitry Andric if (t.mop_count > REPORT_ARRAY_SIZE) t.mop_count = REPORT_ARRAY_SIZE; 1795ffd83dbSDimitry Andric for (int i = 0; i < t.mop_count; i++) { 1805ffd83dbSDimitry Andric t.mops[i].idx = i; 1815ffd83dbSDimitry Andric __tsan_get_report_mop(t.report, i, &t.mops[i].tid, &t.mops[i].addr, &t.mops[i].size, &t.mops[i].write, &t.mops[i].atomic, t.mops[i].trace, REPORT_TRACE_SIZE); 1825ffd83dbSDimitry Andric } 1835ffd83dbSDimitry Andric 1845ffd83dbSDimitry Andric if (t.loc_count > REPORT_ARRAY_SIZE) t.loc_count = REPORT_ARRAY_SIZE; 1855ffd83dbSDimitry Andric for (int i = 0; i < t.loc_count; i++) { 1865ffd83dbSDimitry Andric t.locs[i].idx = i; 1875ffd83dbSDimitry Andric __tsan_get_report_loc(t.report, i, &t.locs[i].type, &t.locs[i].addr, &t.locs[i].start, &t.locs[i].size, &t.locs[i].tid, &t.locs[i].fd, &t.locs[i].suppressable, t.locs[i].trace, REPORT_TRACE_SIZE); 1885ffd83dbSDimitry Andric if (ptr__tsan_get_report_loc_object_type) 1895ffd83dbSDimitry Andric ptr__tsan_get_report_loc_object_type(t.report, i, &t.locs[i].object_type); 1905ffd83dbSDimitry Andric } 1915ffd83dbSDimitry Andric 1925ffd83dbSDimitry Andric if (t.mutex_count > REPORT_ARRAY_SIZE) t.mutex_count = REPORT_ARRAY_SIZE; 1935ffd83dbSDimitry Andric for (int i = 0; i < t.mutex_count; i++) { 1945ffd83dbSDimitry Andric t.mutexes[i].idx = i; 1955ffd83dbSDimitry Andric __tsan_get_report_mutex(t.report, i, &t.mutexes[i].mutex_id, &t.mutexes[i].addr, &t.mutexes[i].destroyed, t.mutexes[i].trace, REPORT_TRACE_SIZE); 1965ffd83dbSDimitry Andric } 1975ffd83dbSDimitry Andric 1985ffd83dbSDimitry Andric if (t.thread_count > REPORT_ARRAY_SIZE) t.thread_count = REPORT_ARRAY_SIZE; 1995ffd83dbSDimitry Andric for (int i = 0; i < t.thread_count; i++) { 2005ffd83dbSDimitry Andric t.threads[i].idx = i; 2015ffd83dbSDimitry Andric __tsan_get_report_thread(t.report, i, &t.threads[i].tid, &t.threads[i].os_id, &t.threads[i].running, &t.threads[i].name, &t.threads[i].parent_tid, t.threads[i].trace, REPORT_TRACE_SIZE); 2025ffd83dbSDimitry Andric } 2035ffd83dbSDimitry Andric 2045ffd83dbSDimitry Andric if (t.unique_tid_count > REPORT_ARRAY_SIZE) t.unique_tid_count = REPORT_ARRAY_SIZE; 2055ffd83dbSDimitry Andric for (int i = 0; i < t.unique_tid_count; i++) { 2065ffd83dbSDimitry Andric t.unique_tids[i].idx = i; 2075ffd83dbSDimitry Andric __tsan_get_report_unique_tid(t.report, i, &t.unique_tids[i].tid); 2085ffd83dbSDimitry Andric } 2095ffd83dbSDimitry Andric 2105ffd83dbSDimitry Andric t; 2115ffd83dbSDimitry Andric )"; 2125ffd83dbSDimitry Andric 2135ffd83dbSDimitry Andric static StructuredData::Array * 2145ffd83dbSDimitry Andric CreateStackTrace(ValueObjectSP o, 2155ffd83dbSDimitry Andric const std::string &trace_item_name = ".trace") { 2165ffd83dbSDimitry Andric StructuredData::Array *trace = new StructuredData::Array(); 2175ffd83dbSDimitry Andric ValueObjectSP trace_value_object = 2185ffd83dbSDimitry Andric o->GetValueForExpressionPath(trace_item_name.c_str()); 2195ffd83dbSDimitry Andric size_t count = trace_value_object->GetNumChildren(); 2205ffd83dbSDimitry Andric for (size_t j = 0; j < count; j++) { 2215ffd83dbSDimitry Andric addr_t trace_addr = 2225ffd83dbSDimitry Andric trace_value_object->GetChildAtIndex(j, true)->GetValueAsUnsigned(0); 2235ffd83dbSDimitry Andric if (trace_addr == 0) 2245ffd83dbSDimitry Andric break; 2255ffd83dbSDimitry Andric trace->AddItem( 2265ffd83dbSDimitry Andric StructuredData::ObjectSP(new StructuredData::Integer(trace_addr))); 2275ffd83dbSDimitry Andric } 2285ffd83dbSDimitry Andric return trace; 2295ffd83dbSDimitry Andric } 2305ffd83dbSDimitry Andric 2315ffd83dbSDimitry Andric static StructuredData::Array *ConvertToStructuredArray( 2325ffd83dbSDimitry Andric ValueObjectSP return_value_sp, const std::string &items_name, 2335ffd83dbSDimitry Andric const std::string &count_name, 2345ffd83dbSDimitry Andric std::function<void(ValueObjectSP o, StructuredData::Dictionary *dict)> const 2355ffd83dbSDimitry Andric &callback) { 2365ffd83dbSDimitry Andric StructuredData::Array *array = new StructuredData::Array(); 2375ffd83dbSDimitry Andric unsigned int count = 2385ffd83dbSDimitry Andric return_value_sp->GetValueForExpressionPath(count_name.c_str()) 2395ffd83dbSDimitry Andric ->GetValueAsUnsigned(0); 2405ffd83dbSDimitry Andric ValueObjectSP objects = 2415ffd83dbSDimitry Andric return_value_sp->GetValueForExpressionPath(items_name.c_str()); 2425ffd83dbSDimitry Andric for (unsigned int i = 0; i < count; i++) { 2435ffd83dbSDimitry Andric ValueObjectSP o = objects->GetChildAtIndex(i, true); 2445ffd83dbSDimitry Andric StructuredData::Dictionary *dict = new StructuredData::Dictionary(); 2455ffd83dbSDimitry Andric 2465ffd83dbSDimitry Andric callback(o, dict); 2475ffd83dbSDimitry Andric 2485ffd83dbSDimitry Andric array->AddItem(StructuredData::ObjectSP(dict)); 2495ffd83dbSDimitry Andric } 2505ffd83dbSDimitry Andric return array; 2515ffd83dbSDimitry Andric } 2525ffd83dbSDimitry Andric 2535ffd83dbSDimitry Andric static std::string RetrieveString(ValueObjectSP return_value_sp, 2545ffd83dbSDimitry Andric ProcessSP process_sp, 2555ffd83dbSDimitry Andric const std::string &expression_path) { 2565ffd83dbSDimitry Andric addr_t ptr = 2575ffd83dbSDimitry Andric return_value_sp->GetValueForExpressionPath(expression_path.c_str()) 2585ffd83dbSDimitry Andric ->GetValueAsUnsigned(0); 2595ffd83dbSDimitry Andric std::string str; 2605ffd83dbSDimitry Andric Status error; 2615ffd83dbSDimitry Andric process_sp->ReadCStringFromMemory(ptr, str, error); 2625ffd83dbSDimitry Andric return str; 2635ffd83dbSDimitry Andric } 2645ffd83dbSDimitry Andric 2655ffd83dbSDimitry Andric static void 2665ffd83dbSDimitry Andric GetRenumberedThreadIds(ProcessSP process_sp, ValueObjectSP data, 2675ffd83dbSDimitry Andric std::map<uint64_t, user_id_t> &thread_id_map) { 2685ffd83dbSDimitry Andric ConvertToStructuredArray( 2695ffd83dbSDimitry Andric data, ".threads", ".thread_count", 2705ffd83dbSDimitry Andric [process_sp, &thread_id_map](ValueObjectSP o, 2715ffd83dbSDimitry Andric StructuredData::Dictionary *dict) { 2725ffd83dbSDimitry Andric uint64_t thread_id = 2735ffd83dbSDimitry Andric o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0); 2745ffd83dbSDimitry Andric uint64_t thread_os_id = 2755ffd83dbSDimitry Andric o->GetValueForExpressionPath(".os_id")->GetValueAsUnsigned(0); 2765ffd83dbSDimitry Andric user_id_t lldb_user_id = 0; 2775ffd83dbSDimitry Andric 2785ffd83dbSDimitry Andric bool can_update = true; 2795ffd83dbSDimitry Andric ThreadSP lldb_thread = process_sp->GetThreadList().FindThreadByID( 2805ffd83dbSDimitry Andric thread_os_id, can_update); 2815ffd83dbSDimitry Andric if (lldb_thread) { 2825ffd83dbSDimitry Andric lldb_user_id = lldb_thread->GetIndexID(); 2835ffd83dbSDimitry Andric } else { 2845ffd83dbSDimitry Andric // This isn't a live thread anymore. Ask process to assign a new 2855ffd83dbSDimitry Andric // Index ID (or return an old one if we've already seen this 2865ffd83dbSDimitry Andric // thread_os_id). It will also make sure that no new threads are 2875ffd83dbSDimitry Andric // assigned this Index ID. 2885ffd83dbSDimitry Andric lldb_user_id = process_sp->AssignIndexIDToThread(thread_os_id); 2895ffd83dbSDimitry Andric } 2905ffd83dbSDimitry Andric 2915ffd83dbSDimitry Andric thread_id_map[thread_id] = lldb_user_id; 2925ffd83dbSDimitry Andric }); 2935ffd83dbSDimitry Andric } 2945ffd83dbSDimitry Andric 2955ffd83dbSDimitry Andric static user_id_t Renumber(uint64_t id, 2965ffd83dbSDimitry Andric std::map<uint64_t, user_id_t> &thread_id_map) { 2975ffd83dbSDimitry Andric auto IT = thread_id_map.find(id); 2985ffd83dbSDimitry Andric if (IT == thread_id_map.end()) 2995ffd83dbSDimitry Andric return 0; 3005ffd83dbSDimitry Andric 3015ffd83dbSDimitry Andric return IT->second; 3025ffd83dbSDimitry Andric } 3035ffd83dbSDimitry Andric 3045ffd83dbSDimitry Andric StructuredData::ObjectSP InstrumentationRuntimeTSan::RetrieveReportData( 3055ffd83dbSDimitry Andric ExecutionContextRef exe_ctx_ref) { 3065ffd83dbSDimitry Andric ProcessSP process_sp = GetProcessSP(); 3075ffd83dbSDimitry Andric if (!process_sp) 3085ffd83dbSDimitry Andric return StructuredData::ObjectSP(); 3095ffd83dbSDimitry Andric 3105ffd83dbSDimitry Andric ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); 3115ffd83dbSDimitry Andric StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); 3125ffd83dbSDimitry Andric 3135ffd83dbSDimitry Andric if (!frame_sp) 3145ffd83dbSDimitry Andric return StructuredData::ObjectSP(); 3155ffd83dbSDimitry Andric 3165ffd83dbSDimitry Andric EvaluateExpressionOptions options; 3175ffd83dbSDimitry Andric options.SetUnwindOnError(true); 3185ffd83dbSDimitry Andric options.SetTryAllThreads(true); 3195ffd83dbSDimitry Andric options.SetStopOthers(true); 3205ffd83dbSDimitry Andric options.SetIgnoreBreakpoints(true); 3215ffd83dbSDimitry Andric options.SetTimeout(process_sp->GetUtilityExpressionTimeout()); 3225ffd83dbSDimitry Andric options.SetPrefix(thread_sanitizer_retrieve_report_data_prefix); 3235ffd83dbSDimitry Andric options.SetAutoApplyFixIts(false); 3245ffd83dbSDimitry Andric options.SetLanguage(eLanguageTypeObjC_plus_plus); 3255ffd83dbSDimitry Andric 3265ffd83dbSDimitry Andric ValueObjectSP main_value; 3275ffd83dbSDimitry Andric ExecutionContext exe_ctx; 3285ffd83dbSDimitry Andric Status eval_error; 3295ffd83dbSDimitry Andric frame_sp->CalculateExecutionContext(exe_ctx); 3305ffd83dbSDimitry Andric ExpressionResults result = UserExpression::Evaluate( 3315ffd83dbSDimitry Andric exe_ctx, options, thread_sanitizer_retrieve_report_data_command, "", 3325ffd83dbSDimitry Andric main_value, eval_error); 3335ffd83dbSDimitry Andric if (result != eExpressionCompleted) { 3345ffd83dbSDimitry Andric process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf( 3355ffd83dbSDimitry Andric "Warning: Cannot evaluate ThreadSanitizer expression:\n%s\n", 3365ffd83dbSDimitry Andric eval_error.AsCString()); 3375ffd83dbSDimitry Andric return StructuredData::ObjectSP(); 3385ffd83dbSDimitry Andric } 3395ffd83dbSDimitry Andric 3405ffd83dbSDimitry Andric std::map<uint64_t, user_id_t> thread_id_map; 3415ffd83dbSDimitry Andric GetRenumberedThreadIds(process_sp, main_value, thread_id_map); 3425ffd83dbSDimitry Andric 3435ffd83dbSDimitry Andric StructuredData::Dictionary *dict = new StructuredData::Dictionary(); 3445ffd83dbSDimitry Andric dict->AddStringItem("instrumentation_class", "ThreadSanitizer"); 3455ffd83dbSDimitry Andric dict->AddStringItem("issue_type", 3465ffd83dbSDimitry Andric RetrieveString(main_value, process_sp, ".description")); 3475ffd83dbSDimitry Andric dict->AddIntegerItem("report_count", 3485ffd83dbSDimitry Andric main_value->GetValueForExpressionPath(".report_count") 3495ffd83dbSDimitry Andric ->GetValueAsUnsigned(0)); 3505ffd83dbSDimitry Andric dict->AddItem("sleep_trace", StructuredData::ObjectSP(CreateStackTrace( 3515ffd83dbSDimitry Andric main_value, ".sleep_trace"))); 3525ffd83dbSDimitry Andric 3535ffd83dbSDimitry Andric StructuredData::Array *stacks = ConvertToStructuredArray( 3545ffd83dbSDimitry Andric main_value, ".stacks", ".stack_count", 3555ffd83dbSDimitry Andric [thread_sp](ValueObjectSP o, StructuredData::Dictionary *dict) { 3565ffd83dbSDimitry Andric dict->AddIntegerItem( 3575ffd83dbSDimitry Andric "index", 3585ffd83dbSDimitry Andric o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); 3595ffd83dbSDimitry Andric dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); 3605ffd83dbSDimitry Andric // "stacks" happen on the current thread 3615ffd83dbSDimitry Andric dict->AddIntegerItem("thread_id", thread_sp->GetIndexID()); 3625ffd83dbSDimitry Andric }); 3635ffd83dbSDimitry Andric dict->AddItem("stacks", StructuredData::ObjectSP(stacks)); 3645ffd83dbSDimitry Andric 3655ffd83dbSDimitry Andric StructuredData::Array *mops = ConvertToStructuredArray( 3665ffd83dbSDimitry Andric main_value, ".mops", ".mop_count", 3675ffd83dbSDimitry Andric [&thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { 3685ffd83dbSDimitry Andric dict->AddIntegerItem( 3695ffd83dbSDimitry Andric "index", 3705ffd83dbSDimitry Andric o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); 3715ffd83dbSDimitry Andric dict->AddIntegerItem( 3725ffd83dbSDimitry Andric "thread_id", 3735ffd83dbSDimitry Andric Renumber( 3745ffd83dbSDimitry Andric o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), 3755ffd83dbSDimitry Andric thread_id_map)); 3765ffd83dbSDimitry Andric dict->AddIntegerItem( 3775ffd83dbSDimitry Andric "size", 3785ffd83dbSDimitry Andric o->GetValueForExpressionPath(".size")->GetValueAsUnsigned(0)); 3795ffd83dbSDimitry Andric dict->AddBooleanItem( 3805ffd83dbSDimitry Andric "is_write", 3815ffd83dbSDimitry Andric o->GetValueForExpressionPath(".write")->GetValueAsUnsigned(0)); 3825ffd83dbSDimitry Andric dict->AddBooleanItem( 3835ffd83dbSDimitry Andric "is_atomic", 3845ffd83dbSDimitry Andric o->GetValueForExpressionPath(".atomic")->GetValueAsUnsigned(0)); 3855ffd83dbSDimitry Andric dict->AddIntegerItem( 3865ffd83dbSDimitry Andric "address", 3875ffd83dbSDimitry Andric o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); 3885ffd83dbSDimitry Andric dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); 3895ffd83dbSDimitry Andric }); 3905ffd83dbSDimitry Andric dict->AddItem("mops", StructuredData::ObjectSP(mops)); 3915ffd83dbSDimitry Andric 3925ffd83dbSDimitry Andric StructuredData::Array *locs = ConvertToStructuredArray( 3935ffd83dbSDimitry Andric main_value, ".locs", ".loc_count", 3945ffd83dbSDimitry Andric [process_sp, &thread_id_map](ValueObjectSP o, 3955ffd83dbSDimitry Andric StructuredData::Dictionary *dict) { 3965ffd83dbSDimitry Andric dict->AddIntegerItem( 3975ffd83dbSDimitry Andric "index", 3985ffd83dbSDimitry Andric o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); 3995ffd83dbSDimitry Andric dict->AddStringItem("type", RetrieveString(o, process_sp, ".type")); 4005ffd83dbSDimitry Andric dict->AddIntegerItem( 4015ffd83dbSDimitry Andric "address", 4025ffd83dbSDimitry Andric o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); 4035ffd83dbSDimitry Andric dict->AddIntegerItem( 4045ffd83dbSDimitry Andric "start", 4055ffd83dbSDimitry Andric o->GetValueForExpressionPath(".start")->GetValueAsUnsigned(0)); 4065ffd83dbSDimitry Andric dict->AddIntegerItem( 4075ffd83dbSDimitry Andric "size", 4085ffd83dbSDimitry Andric o->GetValueForExpressionPath(".size")->GetValueAsUnsigned(0)); 4095ffd83dbSDimitry Andric dict->AddIntegerItem( 4105ffd83dbSDimitry Andric "thread_id", 4115ffd83dbSDimitry Andric Renumber( 4125ffd83dbSDimitry Andric o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), 4135ffd83dbSDimitry Andric thread_id_map)); 4145ffd83dbSDimitry Andric dict->AddIntegerItem( 4155ffd83dbSDimitry Andric "file_descriptor", 4165ffd83dbSDimitry Andric o->GetValueForExpressionPath(".fd")->GetValueAsUnsigned(0)); 4175ffd83dbSDimitry Andric dict->AddIntegerItem("suppressable", 4185ffd83dbSDimitry Andric o->GetValueForExpressionPath(".suppressable") 4195ffd83dbSDimitry Andric ->GetValueAsUnsigned(0)); 4205ffd83dbSDimitry Andric dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); 4215ffd83dbSDimitry Andric dict->AddStringItem("object_type", 4225ffd83dbSDimitry Andric RetrieveString(o, process_sp, ".object_type")); 4235ffd83dbSDimitry Andric }); 4245ffd83dbSDimitry Andric dict->AddItem("locs", StructuredData::ObjectSP(locs)); 4255ffd83dbSDimitry Andric 4265ffd83dbSDimitry Andric StructuredData::Array *mutexes = ConvertToStructuredArray( 4275ffd83dbSDimitry Andric main_value, ".mutexes", ".mutex_count", 4285ffd83dbSDimitry Andric [](ValueObjectSP o, StructuredData::Dictionary *dict) { 4295ffd83dbSDimitry Andric dict->AddIntegerItem( 4305ffd83dbSDimitry Andric "index", 4315ffd83dbSDimitry Andric o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); 4325ffd83dbSDimitry Andric dict->AddIntegerItem( 4335ffd83dbSDimitry Andric "mutex_id", 4345ffd83dbSDimitry Andric o->GetValueForExpressionPath(".mutex_id")->GetValueAsUnsigned(0)); 4355ffd83dbSDimitry Andric dict->AddIntegerItem( 4365ffd83dbSDimitry Andric "address", 4375ffd83dbSDimitry Andric o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); 4385ffd83dbSDimitry Andric dict->AddIntegerItem( 4395ffd83dbSDimitry Andric "destroyed", 4405ffd83dbSDimitry Andric o->GetValueForExpressionPath(".destroyed")->GetValueAsUnsigned(0)); 4415ffd83dbSDimitry Andric dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); 4425ffd83dbSDimitry Andric }); 4435ffd83dbSDimitry Andric dict->AddItem("mutexes", StructuredData::ObjectSP(mutexes)); 4445ffd83dbSDimitry Andric 4455ffd83dbSDimitry Andric StructuredData::Array *threads = ConvertToStructuredArray( 4465ffd83dbSDimitry Andric main_value, ".threads", ".thread_count", 4475ffd83dbSDimitry Andric [process_sp, &thread_id_map](ValueObjectSP o, 4485ffd83dbSDimitry Andric StructuredData::Dictionary *dict) { 4495ffd83dbSDimitry Andric dict->AddIntegerItem( 4505ffd83dbSDimitry Andric "index", 4515ffd83dbSDimitry Andric o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); 4525ffd83dbSDimitry Andric dict->AddIntegerItem( 4535ffd83dbSDimitry Andric "thread_id", 4545ffd83dbSDimitry Andric Renumber( 4555ffd83dbSDimitry Andric o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), 4565ffd83dbSDimitry Andric thread_id_map)); 4575ffd83dbSDimitry Andric dict->AddIntegerItem( 4585ffd83dbSDimitry Andric "thread_os_id", 4595ffd83dbSDimitry Andric o->GetValueForExpressionPath(".os_id")->GetValueAsUnsigned(0)); 4605ffd83dbSDimitry Andric dict->AddIntegerItem( 4615ffd83dbSDimitry Andric "running", 4625ffd83dbSDimitry Andric o->GetValueForExpressionPath(".running")->GetValueAsUnsigned(0)); 4635ffd83dbSDimitry Andric dict->AddStringItem("name", RetrieveString(o, process_sp, ".name")); 4645ffd83dbSDimitry Andric dict->AddIntegerItem( 4655ffd83dbSDimitry Andric "parent_thread_id", 4665ffd83dbSDimitry Andric Renumber(o->GetValueForExpressionPath(".parent_tid") 4675ffd83dbSDimitry Andric ->GetValueAsUnsigned(0), 4685ffd83dbSDimitry Andric thread_id_map)); 4695ffd83dbSDimitry Andric dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); 4705ffd83dbSDimitry Andric }); 4715ffd83dbSDimitry Andric dict->AddItem("threads", StructuredData::ObjectSP(threads)); 4725ffd83dbSDimitry Andric 4735ffd83dbSDimitry Andric StructuredData::Array *unique_tids = ConvertToStructuredArray( 4745ffd83dbSDimitry Andric main_value, ".unique_tids", ".unique_tid_count", 4755ffd83dbSDimitry Andric [&thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { 4765ffd83dbSDimitry Andric dict->AddIntegerItem( 4775ffd83dbSDimitry Andric "index", 4785ffd83dbSDimitry Andric o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); 4795ffd83dbSDimitry Andric dict->AddIntegerItem( 4805ffd83dbSDimitry Andric "tid", 4815ffd83dbSDimitry Andric Renumber( 4825ffd83dbSDimitry Andric o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), 4835ffd83dbSDimitry Andric thread_id_map)); 4845ffd83dbSDimitry Andric }); 4855ffd83dbSDimitry Andric dict->AddItem("unique_tids", StructuredData::ObjectSP(unique_tids)); 4865ffd83dbSDimitry Andric 4875ffd83dbSDimitry Andric return StructuredData::ObjectSP(dict); 4885ffd83dbSDimitry Andric } 4895ffd83dbSDimitry Andric 4905ffd83dbSDimitry Andric std::string 4915ffd83dbSDimitry Andric InstrumentationRuntimeTSan::FormatDescription(StructuredData::ObjectSP report) { 4925ffd83dbSDimitry Andric std::string description = std::string(report->GetAsDictionary() 4935ffd83dbSDimitry Andric ->GetValueForKey("issue_type") 4945ffd83dbSDimitry Andric ->GetAsString() 4955ffd83dbSDimitry Andric ->GetValue()); 4965ffd83dbSDimitry Andric 4975ffd83dbSDimitry Andric if (description == "data-race") { 4985ffd83dbSDimitry Andric return "Data race"; 4995ffd83dbSDimitry Andric } else if (description == "data-race-vptr") { 5005ffd83dbSDimitry Andric return "Data race on C++ virtual pointer"; 5015ffd83dbSDimitry Andric } else if (description == "heap-use-after-free") { 5025ffd83dbSDimitry Andric return "Use of deallocated memory"; 5035ffd83dbSDimitry Andric } else if (description == "heap-use-after-free-vptr") { 5045ffd83dbSDimitry Andric return "Use of deallocated C++ virtual pointer"; 5055ffd83dbSDimitry Andric } else if (description == "thread-leak") { 5065ffd83dbSDimitry Andric return "Thread leak"; 5075ffd83dbSDimitry Andric } else if (description == "locked-mutex-destroy") { 5085ffd83dbSDimitry Andric return "Destruction of a locked mutex"; 5095ffd83dbSDimitry Andric } else if (description == "mutex-double-lock") { 5105ffd83dbSDimitry Andric return "Double lock of a mutex"; 5115ffd83dbSDimitry Andric } else if (description == "mutex-invalid-access") { 5125ffd83dbSDimitry Andric return "Use of an uninitialized or destroyed mutex"; 5135ffd83dbSDimitry Andric } else if (description == "mutex-bad-unlock") { 5145ffd83dbSDimitry Andric return "Unlock of an unlocked mutex (or by a wrong thread)"; 5155ffd83dbSDimitry Andric } else if (description == "mutex-bad-read-lock") { 5165ffd83dbSDimitry Andric return "Read lock of a write locked mutex"; 5175ffd83dbSDimitry Andric } else if (description == "mutex-bad-read-unlock") { 5185ffd83dbSDimitry Andric return "Read unlock of a write locked mutex"; 5195ffd83dbSDimitry Andric } else if (description == "signal-unsafe-call") { 5205ffd83dbSDimitry Andric return "Signal-unsafe call inside a signal handler"; 5215ffd83dbSDimitry Andric } else if (description == "errno-in-signal-handler") { 5225ffd83dbSDimitry Andric return "Overwrite of errno in a signal handler"; 5235ffd83dbSDimitry Andric } else if (description == "lock-order-inversion") { 5245ffd83dbSDimitry Andric return "Lock order inversion (potential deadlock)"; 5255ffd83dbSDimitry Andric } else if (description == "external-race") { 5265ffd83dbSDimitry Andric return "Race on a library object"; 5275ffd83dbSDimitry Andric } else if (description == "swift-access-race") { 5285ffd83dbSDimitry Andric return "Swift access race"; 5295ffd83dbSDimitry Andric } 5305ffd83dbSDimitry Andric 5315ffd83dbSDimitry Andric // for unknown report codes just show the code 5325ffd83dbSDimitry Andric return description; 5335ffd83dbSDimitry Andric } 5345ffd83dbSDimitry Andric 5355ffd83dbSDimitry Andric static std::string Sprintf(const char *format, ...) { 5365ffd83dbSDimitry Andric StreamString s; 5375ffd83dbSDimitry Andric va_list args; 5385ffd83dbSDimitry Andric va_start(args, format); 5395ffd83dbSDimitry Andric s.PrintfVarArg(format, args); 5405ffd83dbSDimitry Andric va_end(args); 5415ffd83dbSDimitry Andric return std::string(s.GetString()); 5425ffd83dbSDimitry Andric } 5435ffd83dbSDimitry Andric 5445ffd83dbSDimitry Andric static std::string GetSymbolNameFromAddress(ProcessSP process_sp, addr_t addr) { 5455ffd83dbSDimitry Andric lldb_private::Address so_addr; 5465ffd83dbSDimitry Andric if (!process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, 5475ffd83dbSDimitry Andric so_addr)) 5485ffd83dbSDimitry Andric return ""; 5495ffd83dbSDimitry Andric 5505ffd83dbSDimitry Andric lldb_private::Symbol *symbol = so_addr.CalculateSymbolContextSymbol(); 5515ffd83dbSDimitry Andric if (!symbol) 5525ffd83dbSDimitry Andric return ""; 5535ffd83dbSDimitry Andric 5545ffd83dbSDimitry Andric std::string sym_name = symbol->GetName().GetCString(); 5555ffd83dbSDimitry Andric return sym_name; 5565ffd83dbSDimitry Andric } 5575ffd83dbSDimitry Andric 5585ffd83dbSDimitry Andric static void GetSymbolDeclarationFromAddress(ProcessSP process_sp, addr_t addr, 5595ffd83dbSDimitry Andric Declaration &decl) { 5605ffd83dbSDimitry Andric lldb_private::Address so_addr; 5615ffd83dbSDimitry Andric if (!process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, 5625ffd83dbSDimitry Andric so_addr)) 5635ffd83dbSDimitry Andric return; 5645ffd83dbSDimitry Andric 5655ffd83dbSDimitry Andric lldb_private::Symbol *symbol = so_addr.CalculateSymbolContextSymbol(); 5665ffd83dbSDimitry Andric if (!symbol) 5675ffd83dbSDimitry Andric return; 5685ffd83dbSDimitry Andric 5695ffd83dbSDimitry Andric ConstString sym_name = symbol->GetMangled().GetName(Mangled::ePreferMangled); 5705ffd83dbSDimitry Andric 5715ffd83dbSDimitry Andric ModuleSP module = symbol->CalculateSymbolContextModule(); 5725ffd83dbSDimitry Andric if (!module) 5735ffd83dbSDimitry Andric return; 5745ffd83dbSDimitry Andric 5755ffd83dbSDimitry Andric VariableList var_list; 5765ffd83dbSDimitry Andric module->FindGlobalVariables(sym_name, CompilerDeclContext(), 1U, var_list); 5775ffd83dbSDimitry Andric if (var_list.GetSize() < 1) 5785ffd83dbSDimitry Andric return; 5795ffd83dbSDimitry Andric 5805ffd83dbSDimitry Andric VariableSP var = var_list.GetVariableAtIndex(0); 5815ffd83dbSDimitry Andric decl = var->GetDeclaration(); 5825ffd83dbSDimitry Andric } 5835ffd83dbSDimitry Andric 5845ffd83dbSDimitry Andric addr_t InstrumentationRuntimeTSan::GetFirstNonInternalFramePc( 5855ffd83dbSDimitry Andric StructuredData::ObjectSP trace, bool skip_one_frame) { 5865ffd83dbSDimitry Andric ProcessSP process_sp = GetProcessSP(); 5875ffd83dbSDimitry Andric ModuleSP runtime_module_sp = GetRuntimeModuleSP(); 5885ffd83dbSDimitry Andric 5895ffd83dbSDimitry Andric StructuredData::Array *trace_array = trace->GetAsArray(); 5905ffd83dbSDimitry Andric for (size_t i = 0; i < trace_array->GetSize(); i++) { 5915ffd83dbSDimitry Andric if (skip_one_frame && i == 0) 5925ffd83dbSDimitry Andric continue; 5935ffd83dbSDimitry Andric 5945ffd83dbSDimitry Andric addr_t addr; 5955ffd83dbSDimitry Andric if (!trace_array->GetItemAtIndexAsInteger(i, addr)) 5965ffd83dbSDimitry Andric continue; 5975ffd83dbSDimitry Andric 5985ffd83dbSDimitry Andric lldb_private::Address so_addr; 5995ffd83dbSDimitry Andric if (!process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress( 6005ffd83dbSDimitry Andric addr, so_addr)) 6015ffd83dbSDimitry Andric continue; 6025ffd83dbSDimitry Andric 6035ffd83dbSDimitry Andric if (so_addr.GetModule() == runtime_module_sp) 6045ffd83dbSDimitry Andric continue; 6055ffd83dbSDimitry Andric 6065ffd83dbSDimitry Andric return addr; 6075ffd83dbSDimitry Andric } 6085ffd83dbSDimitry Andric 6095ffd83dbSDimitry Andric return 0; 6105ffd83dbSDimitry Andric } 6115ffd83dbSDimitry Andric 6125ffd83dbSDimitry Andric std::string 6135ffd83dbSDimitry Andric InstrumentationRuntimeTSan::GenerateSummary(StructuredData::ObjectSP report) { 6145ffd83dbSDimitry Andric ProcessSP process_sp = GetProcessSP(); 6155ffd83dbSDimitry Andric 6165ffd83dbSDimitry Andric std::string summary = std::string(report->GetAsDictionary() 6175ffd83dbSDimitry Andric ->GetValueForKey("description") 6185ffd83dbSDimitry Andric ->GetAsString() 6195ffd83dbSDimitry Andric ->GetValue()); 6205ffd83dbSDimitry Andric bool skip_one_frame = 6215ffd83dbSDimitry Andric report->GetObjectForDotSeparatedPath("issue_type")->GetStringValue() == 6225ffd83dbSDimitry Andric "external-race"; 6235ffd83dbSDimitry Andric 6245ffd83dbSDimitry Andric addr_t pc = 0; 6255ffd83dbSDimitry Andric if (report->GetAsDictionary() 6265ffd83dbSDimitry Andric ->GetValueForKey("mops") 6275ffd83dbSDimitry Andric ->GetAsArray() 6285ffd83dbSDimitry Andric ->GetSize() > 0) 6295ffd83dbSDimitry Andric pc = GetFirstNonInternalFramePc(report->GetAsDictionary() 6305ffd83dbSDimitry Andric ->GetValueForKey("mops") 6315ffd83dbSDimitry Andric ->GetAsArray() 6325ffd83dbSDimitry Andric ->GetItemAtIndex(0) 6335ffd83dbSDimitry Andric ->GetAsDictionary() 6345ffd83dbSDimitry Andric ->GetValueForKey("trace"), 6355ffd83dbSDimitry Andric skip_one_frame); 6365ffd83dbSDimitry Andric 6375ffd83dbSDimitry Andric if (report->GetAsDictionary() 6385ffd83dbSDimitry Andric ->GetValueForKey("stacks") 6395ffd83dbSDimitry Andric ->GetAsArray() 6405ffd83dbSDimitry Andric ->GetSize() > 0) 6415ffd83dbSDimitry Andric pc = GetFirstNonInternalFramePc(report->GetAsDictionary() 6425ffd83dbSDimitry Andric ->GetValueForKey("stacks") 6435ffd83dbSDimitry Andric ->GetAsArray() 6445ffd83dbSDimitry Andric ->GetItemAtIndex(0) 6455ffd83dbSDimitry Andric ->GetAsDictionary() 6465ffd83dbSDimitry Andric ->GetValueForKey("trace"), 6475ffd83dbSDimitry Andric skip_one_frame); 6485ffd83dbSDimitry Andric 6495ffd83dbSDimitry Andric if (pc != 0) { 6505ffd83dbSDimitry Andric summary = summary + " in " + GetSymbolNameFromAddress(process_sp, pc); 6515ffd83dbSDimitry Andric } 6525ffd83dbSDimitry Andric 6535ffd83dbSDimitry Andric if (report->GetAsDictionary() 6545ffd83dbSDimitry Andric ->GetValueForKey("locs") 6555ffd83dbSDimitry Andric ->GetAsArray() 6565ffd83dbSDimitry Andric ->GetSize() > 0) { 6575ffd83dbSDimitry Andric StructuredData::ObjectSP loc = report->GetAsDictionary() 6585ffd83dbSDimitry Andric ->GetValueForKey("locs") 6595ffd83dbSDimitry Andric ->GetAsArray() 6605ffd83dbSDimitry Andric ->GetItemAtIndex(0); 6615ffd83dbSDimitry Andric std::string object_type = std::string(loc->GetAsDictionary() 6625ffd83dbSDimitry Andric ->GetValueForKey("object_type") 6635ffd83dbSDimitry Andric ->GetAsString() 6645ffd83dbSDimitry Andric ->GetValue()); 6655ffd83dbSDimitry Andric if (!object_type.empty()) { 6665ffd83dbSDimitry Andric summary = "Race on " + object_type + " object"; 6675ffd83dbSDimitry Andric } 6685ffd83dbSDimitry Andric addr_t addr = loc->GetAsDictionary() 6695ffd83dbSDimitry Andric ->GetValueForKey("address") 6705ffd83dbSDimitry Andric ->GetAsInteger() 6715ffd83dbSDimitry Andric ->GetValue(); 6725ffd83dbSDimitry Andric if (addr == 0) 6735ffd83dbSDimitry Andric addr = loc->GetAsDictionary() 6745ffd83dbSDimitry Andric ->GetValueForKey("start") 6755ffd83dbSDimitry Andric ->GetAsInteger() 6765ffd83dbSDimitry Andric ->GetValue(); 6775ffd83dbSDimitry Andric 6785ffd83dbSDimitry Andric if (addr != 0) { 6795ffd83dbSDimitry Andric std::string global_name = GetSymbolNameFromAddress(process_sp, addr); 6805ffd83dbSDimitry Andric if (!global_name.empty()) { 6815ffd83dbSDimitry Andric summary = summary + " at " + global_name; 6825ffd83dbSDimitry Andric } else { 6835ffd83dbSDimitry Andric summary = summary + " at " + Sprintf("0x%llx", addr); 6845ffd83dbSDimitry Andric } 6855ffd83dbSDimitry Andric } else { 6865ffd83dbSDimitry Andric int fd = loc->GetAsDictionary() 6875ffd83dbSDimitry Andric ->GetValueForKey("file_descriptor") 6885ffd83dbSDimitry Andric ->GetAsInteger() 6895ffd83dbSDimitry Andric ->GetValue(); 6905ffd83dbSDimitry Andric if (fd != 0) { 6915ffd83dbSDimitry Andric summary = summary + " on file descriptor " + Sprintf("%d", fd); 6925ffd83dbSDimitry Andric } 6935ffd83dbSDimitry Andric } 6945ffd83dbSDimitry Andric } 6955ffd83dbSDimitry Andric 6965ffd83dbSDimitry Andric return summary; 6975ffd83dbSDimitry Andric } 6985ffd83dbSDimitry Andric 6995ffd83dbSDimitry Andric addr_t InstrumentationRuntimeTSan::GetMainRacyAddress( 7005ffd83dbSDimitry Andric StructuredData::ObjectSP report) { 7015ffd83dbSDimitry Andric addr_t result = (addr_t)-1; 7025ffd83dbSDimitry Andric 7035ffd83dbSDimitry Andric report->GetObjectForDotSeparatedPath("mops")->GetAsArray()->ForEach( 7045ffd83dbSDimitry Andric [&result](StructuredData::Object *o) -> bool { 7055ffd83dbSDimitry Andric addr_t addr = 7065ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); 7075ffd83dbSDimitry Andric if (addr < result) 7085ffd83dbSDimitry Andric result = addr; 7095ffd83dbSDimitry Andric return true; 7105ffd83dbSDimitry Andric }); 7115ffd83dbSDimitry Andric 7125ffd83dbSDimitry Andric return (result == (addr_t)-1) ? 0 : result; 7135ffd83dbSDimitry Andric } 7145ffd83dbSDimitry Andric 7155ffd83dbSDimitry Andric std::string InstrumentationRuntimeTSan::GetLocationDescription( 7165ffd83dbSDimitry Andric StructuredData::ObjectSP report, addr_t &global_addr, 7175ffd83dbSDimitry Andric std::string &global_name, std::string &filename, uint32_t &line) { 7185ffd83dbSDimitry Andric std::string result = ""; 7195ffd83dbSDimitry Andric 7205ffd83dbSDimitry Andric ProcessSP process_sp = GetProcessSP(); 7215ffd83dbSDimitry Andric 7225ffd83dbSDimitry Andric if (report->GetAsDictionary() 7235ffd83dbSDimitry Andric ->GetValueForKey("locs") 7245ffd83dbSDimitry Andric ->GetAsArray() 7255ffd83dbSDimitry Andric ->GetSize() > 0) { 7265ffd83dbSDimitry Andric StructuredData::ObjectSP loc = report->GetAsDictionary() 7275ffd83dbSDimitry Andric ->GetValueForKey("locs") 7285ffd83dbSDimitry Andric ->GetAsArray() 7295ffd83dbSDimitry Andric ->GetItemAtIndex(0); 7305ffd83dbSDimitry Andric std::string type = std::string( 7315ffd83dbSDimitry Andric loc->GetAsDictionary()->GetValueForKey("type")->GetStringValue()); 7325ffd83dbSDimitry Andric if (type == "global") { 7335ffd83dbSDimitry Andric global_addr = loc->GetAsDictionary() 7345ffd83dbSDimitry Andric ->GetValueForKey("address") 7355ffd83dbSDimitry Andric ->GetAsInteger() 7365ffd83dbSDimitry Andric ->GetValue(); 7375ffd83dbSDimitry Andric global_name = GetSymbolNameFromAddress(process_sp, global_addr); 7385ffd83dbSDimitry Andric if (!global_name.empty()) { 7395ffd83dbSDimitry Andric result = Sprintf("'%s' is a global variable (0x%llx)", 7405ffd83dbSDimitry Andric global_name.c_str(), global_addr); 7415ffd83dbSDimitry Andric } else { 7425ffd83dbSDimitry Andric result = Sprintf("0x%llx is a global variable", global_addr); 7435ffd83dbSDimitry Andric } 7445ffd83dbSDimitry Andric 7455ffd83dbSDimitry Andric Declaration decl; 7465ffd83dbSDimitry Andric GetSymbolDeclarationFromAddress(process_sp, global_addr, decl); 7475ffd83dbSDimitry Andric if (decl.GetFile()) { 7485ffd83dbSDimitry Andric filename = decl.GetFile().GetPath(); 7495ffd83dbSDimitry Andric line = decl.GetLine(); 7505ffd83dbSDimitry Andric } 7515ffd83dbSDimitry Andric } else if (type == "heap") { 7525ffd83dbSDimitry Andric addr_t addr = loc->GetAsDictionary() 7535ffd83dbSDimitry Andric ->GetValueForKey("start") 7545ffd83dbSDimitry Andric ->GetAsInteger() 7555ffd83dbSDimitry Andric ->GetValue(); 7565ffd83dbSDimitry Andric long size = loc->GetAsDictionary() 7575ffd83dbSDimitry Andric ->GetValueForKey("size") 7585ffd83dbSDimitry Andric ->GetAsInteger() 7595ffd83dbSDimitry Andric ->GetValue(); 7605ffd83dbSDimitry Andric std::string object_type = std::string(loc->GetAsDictionary() 7615ffd83dbSDimitry Andric ->GetValueForKey("object_type") 7625ffd83dbSDimitry Andric ->GetAsString() 7635ffd83dbSDimitry Andric ->GetValue()); 7645ffd83dbSDimitry Andric if (!object_type.empty()) { 7655ffd83dbSDimitry Andric result = Sprintf("Location is a %ld-byte %s object at 0x%llx", size, 7665ffd83dbSDimitry Andric object_type.c_str(), addr); 7675ffd83dbSDimitry Andric } else { 7685ffd83dbSDimitry Andric result = 7695ffd83dbSDimitry Andric Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); 7705ffd83dbSDimitry Andric } 7715ffd83dbSDimitry Andric } else if (type == "stack") { 7725ffd83dbSDimitry Andric int tid = loc->GetAsDictionary() 7735ffd83dbSDimitry Andric ->GetValueForKey("thread_id") 7745ffd83dbSDimitry Andric ->GetAsInteger() 7755ffd83dbSDimitry Andric ->GetValue(); 7765ffd83dbSDimitry Andric result = Sprintf("Location is stack of thread %d", tid); 7775ffd83dbSDimitry Andric } else if (type == "tls") { 7785ffd83dbSDimitry Andric int tid = loc->GetAsDictionary() 7795ffd83dbSDimitry Andric ->GetValueForKey("thread_id") 7805ffd83dbSDimitry Andric ->GetAsInteger() 7815ffd83dbSDimitry Andric ->GetValue(); 7825ffd83dbSDimitry Andric result = Sprintf("Location is TLS of thread %d", tid); 7835ffd83dbSDimitry Andric } else if (type == "fd") { 7845ffd83dbSDimitry Andric int fd = loc->GetAsDictionary() 7855ffd83dbSDimitry Andric ->GetValueForKey("file_descriptor") 7865ffd83dbSDimitry Andric ->GetAsInteger() 7875ffd83dbSDimitry Andric ->GetValue(); 7885ffd83dbSDimitry Andric result = Sprintf("Location is file descriptor %d", fd); 7895ffd83dbSDimitry Andric } 7905ffd83dbSDimitry Andric } 7915ffd83dbSDimitry Andric 7925ffd83dbSDimitry Andric return result; 7935ffd83dbSDimitry Andric } 7945ffd83dbSDimitry Andric 7955ffd83dbSDimitry Andric bool InstrumentationRuntimeTSan::NotifyBreakpointHit( 7965ffd83dbSDimitry Andric void *baton, StoppointCallbackContext *context, user_id_t break_id, 7975ffd83dbSDimitry Andric user_id_t break_loc_id) { 7985ffd83dbSDimitry Andric assert(baton && "null baton"); 7995ffd83dbSDimitry Andric if (!baton) 8005ffd83dbSDimitry Andric return false; 8015ffd83dbSDimitry Andric 8025ffd83dbSDimitry Andric InstrumentationRuntimeTSan *const instance = 8035ffd83dbSDimitry Andric static_cast<InstrumentationRuntimeTSan *>(baton); 8045ffd83dbSDimitry Andric 8055ffd83dbSDimitry Andric ProcessSP process_sp = instance->GetProcessSP(); 8065ffd83dbSDimitry Andric 8075ffd83dbSDimitry Andric if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) 8085ffd83dbSDimitry Andric return false; 8095ffd83dbSDimitry Andric 8105ffd83dbSDimitry Andric StructuredData::ObjectSP report = 8115ffd83dbSDimitry Andric instance->RetrieveReportData(context->exe_ctx_ref); 812*e8d8bef9SDimitry Andric std::string stop_reason_description = 813*e8d8bef9SDimitry Andric "unknown thread sanitizer fault (unable to extract thread sanitizer " 814*e8d8bef9SDimitry Andric "report)"; 8155ffd83dbSDimitry Andric if (report) { 8165ffd83dbSDimitry Andric std::string issue_description = instance->FormatDescription(report); 8175ffd83dbSDimitry Andric report->GetAsDictionary()->AddStringItem("description", issue_description); 8185ffd83dbSDimitry Andric stop_reason_description = issue_description + " detected"; 8195ffd83dbSDimitry Andric report->GetAsDictionary()->AddStringItem("stop_description", 8205ffd83dbSDimitry Andric stop_reason_description); 8215ffd83dbSDimitry Andric std::string summary = instance->GenerateSummary(report); 8225ffd83dbSDimitry Andric report->GetAsDictionary()->AddStringItem("summary", summary); 8235ffd83dbSDimitry Andric addr_t main_address = instance->GetMainRacyAddress(report); 8245ffd83dbSDimitry Andric report->GetAsDictionary()->AddIntegerItem("memory_address", main_address); 8255ffd83dbSDimitry Andric 8265ffd83dbSDimitry Andric addr_t global_addr = 0; 8275ffd83dbSDimitry Andric std::string global_name = ""; 8285ffd83dbSDimitry Andric std::string location_filename = ""; 8295ffd83dbSDimitry Andric uint32_t location_line = 0; 8305ffd83dbSDimitry Andric std::string location_description = instance->GetLocationDescription( 8315ffd83dbSDimitry Andric report, global_addr, global_name, location_filename, location_line); 8325ffd83dbSDimitry Andric report->GetAsDictionary()->AddStringItem("location_description", 8335ffd83dbSDimitry Andric location_description); 8345ffd83dbSDimitry Andric if (global_addr != 0) { 8355ffd83dbSDimitry Andric report->GetAsDictionary()->AddIntegerItem("global_address", global_addr); 8365ffd83dbSDimitry Andric } 8375ffd83dbSDimitry Andric if (!global_name.empty()) { 8385ffd83dbSDimitry Andric report->GetAsDictionary()->AddStringItem("global_name", global_name); 8395ffd83dbSDimitry Andric } 8405ffd83dbSDimitry Andric if (location_filename != "") { 8415ffd83dbSDimitry Andric report->GetAsDictionary()->AddStringItem("location_filename", 8425ffd83dbSDimitry Andric location_filename); 8435ffd83dbSDimitry Andric report->GetAsDictionary()->AddIntegerItem("location_line", location_line); 8445ffd83dbSDimitry Andric } 8455ffd83dbSDimitry Andric 8465ffd83dbSDimitry Andric bool all_addresses_are_same = true; 8475ffd83dbSDimitry Andric report->GetObjectForDotSeparatedPath("mops")->GetAsArray()->ForEach( 8485ffd83dbSDimitry Andric [&all_addresses_are_same, 8495ffd83dbSDimitry Andric main_address](StructuredData::Object *o) -> bool { 8505ffd83dbSDimitry Andric addr_t addr = 8515ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); 8525ffd83dbSDimitry Andric if (main_address != addr) 8535ffd83dbSDimitry Andric all_addresses_are_same = false; 8545ffd83dbSDimitry Andric return true; 8555ffd83dbSDimitry Andric }); 8565ffd83dbSDimitry Andric report->GetAsDictionary()->AddBooleanItem("all_addresses_are_same", 8575ffd83dbSDimitry Andric all_addresses_are_same); 8585ffd83dbSDimitry Andric } 8595ffd83dbSDimitry Andric 8605ffd83dbSDimitry Andric // Make sure this is the right process 8615ffd83dbSDimitry Andric if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { 8625ffd83dbSDimitry Andric ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); 8635ffd83dbSDimitry Andric if (thread_sp) 8645ffd83dbSDimitry Andric thread_sp->SetStopInfo( 8655ffd83dbSDimitry Andric InstrumentationRuntimeStopInfo:: 8665ffd83dbSDimitry Andric CreateStopReasonWithInstrumentationData( 8675ffd83dbSDimitry Andric *thread_sp, stop_reason_description, report)); 8685ffd83dbSDimitry Andric 8695ffd83dbSDimitry Andric StreamFile &s = process_sp->GetTarget().GetDebugger().GetOutputStream(); 8705ffd83dbSDimitry Andric s.Printf("ThreadSanitizer report breakpoint hit. Use 'thread " 8715ffd83dbSDimitry Andric "info -s' to get extended information about the " 8725ffd83dbSDimitry Andric "report.\n"); 8735ffd83dbSDimitry Andric 8745ffd83dbSDimitry Andric return true; // Return true to stop the target 8755ffd83dbSDimitry Andric } else 8765ffd83dbSDimitry Andric return false; // Let target run 8775ffd83dbSDimitry Andric } 8785ffd83dbSDimitry Andric 8795ffd83dbSDimitry Andric const RegularExpression & 8805ffd83dbSDimitry Andric InstrumentationRuntimeTSan::GetPatternForRuntimeLibrary() { 8815ffd83dbSDimitry Andric static RegularExpression regex(llvm::StringRef("libclang_rt.tsan_")); 8825ffd83dbSDimitry Andric return regex; 8835ffd83dbSDimitry Andric } 8845ffd83dbSDimitry Andric 8855ffd83dbSDimitry Andric bool InstrumentationRuntimeTSan::CheckIfRuntimeIsValid( 8865ffd83dbSDimitry Andric const lldb::ModuleSP module_sp) { 8875ffd83dbSDimitry Andric static ConstString g_tsan_get_current_report("__tsan_get_current_report"); 8885ffd83dbSDimitry Andric const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType( 8895ffd83dbSDimitry Andric g_tsan_get_current_report, lldb::eSymbolTypeAny); 8905ffd83dbSDimitry Andric return symbol != nullptr; 8915ffd83dbSDimitry Andric } 8925ffd83dbSDimitry Andric 8935ffd83dbSDimitry Andric void InstrumentationRuntimeTSan::Activate() { 8945ffd83dbSDimitry Andric if (IsActive()) 8955ffd83dbSDimitry Andric return; 8965ffd83dbSDimitry Andric 8975ffd83dbSDimitry Andric ProcessSP process_sp = GetProcessSP(); 8985ffd83dbSDimitry Andric if (!process_sp) 8995ffd83dbSDimitry Andric return; 9005ffd83dbSDimitry Andric 9015ffd83dbSDimitry Andric ConstString symbol_name("__tsan_on_report"); 9025ffd83dbSDimitry Andric const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType( 9035ffd83dbSDimitry Andric symbol_name, eSymbolTypeCode); 9045ffd83dbSDimitry Andric 9055ffd83dbSDimitry Andric if (symbol == nullptr) 9065ffd83dbSDimitry Andric return; 9075ffd83dbSDimitry Andric 9085ffd83dbSDimitry Andric if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) 9095ffd83dbSDimitry Andric return; 9105ffd83dbSDimitry Andric 9115ffd83dbSDimitry Andric Target &target = process_sp->GetTarget(); 9125ffd83dbSDimitry Andric addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); 9135ffd83dbSDimitry Andric 9145ffd83dbSDimitry Andric if (symbol_address == LLDB_INVALID_ADDRESS) 9155ffd83dbSDimitry Andric return; 9165ffd83dbSDimitry Andric 9175ffd83dbSDimitry Andric bool internal = true; 9185ffd83dbSDimitry Andric bool hardware = false; 9195ffd83dbSDimitry Andric Breakpoint *breakpoint = 9205ffd83dbSDimitry Andric process_sp->GetTarget() 9215ffd83dbSDimitry Andric .CreateBreakpoint(symbol_address, internal, hardware) 9225ffd83dbSDimitry Andric .get(); 9235ffd83dbSDimitry Andric breakpoint->SetCallback(InstrumentationRuntimeTSan::NotifyBreakpointHit, this, 9245ffd83dbSDimitry Andric true); 9255ffd83dbSDimitry Andric breakpoint->SetBreakpointKind("thread-sanitizer-report"); 9265ffd83dbSDimitry Andric SetBreakpointID(breakpoint->GetID()); 9275ffd83dbSDimitry Andric 9285ffd83dbSDimitry Andric SetActive(true); 9295ffd83dbSDimitry Andric } 9305ffd83dbSDimitry Andric 9315ffd83dbSDimitry Andric void InstrumentationRuntimeTSan::Deactivate() { 9325ffd83dbSDimitry Andric if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 9335ffd83dbSDimitry Andric ProcessSP process_sp = GetProcessSP(); 9345ffd83dbSDimitry Andric if (process_sp) { 9355ffd83dbSDimitry Andric process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID()); 9365ffd83dbSDimitry Andric SetBreakpointID(LLDB_INVALID_BREAK_ID); 9375ffd83dbSDimitry Andric } 9385ffd83dbSDimitry Andric } 9395ffd83dbSDimitry Andric SetActive(false); 9405ffd83dbSDimitry Andric } 9415ffd83dbSDimitry Andric static std::string GenerateThreadName(const std::string &path, 9425ffd83dbSDimitry Andric StructuredData::Object *o, 9435ffd83dbSDimitry Andric StructuredData::ObjectSP main_info) { 9445ffd83dbSDimitry Andric std::string result = "additional information"; 9455ffd83dbSDimitry Andric 9465ffd83dbSDimitry Andric if (path == "mops") { 9475ffd83dbSDimitry Andric int size = o->GetObjectForDotSeparatedPath("size")->GetIntegerValue(); 9485ffd83dbSDimitry Andric int thread_id = 9495ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); 9505ffd83dbSDimitry Andric bool is_write = 9515ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("is_write")->GetBooleanValue(); 9525ffd83dbSDimitry Andric bool is_atomic = 9535ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("is_atomic")->GetBooleanValue(); 9545ffd83dbSDimitry Andric addr_t addr = o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); 9555ffd83dbSDimitry Andric 9565ffd83dbSDimitry Andric std::string addr_string = Sprintf(" at 0x%llx", addr); 9575ffd83dbSDimitry Andric 9585ffd83dbSDimitry Andric if (main_info->GetObjectForDotSeparatedPath("all_addresses_are_same") 9595ffd83dbSDimitry Andric ->GetBooleanValue()) { 9605ffd83dbSDimitry Andric addr_string = ""; 9615ffd83dbSDimitry Andric } 9625ffd83dbSDimitry Andric 9635ffd83dbSDimitry Andric if (main_info->GetObjectForDotSeparatedPath("issue_type") 9645ffd83dbSDimitry Andric ->GetStringValue() == "external-race") { 9655ffd83dbSDimitry Andric result = Sprintf("%s access by thread %d", 9665ffd83dbSDimitry Andric is_write ? "mutating" : "read-only", thread_id); 9675ffd83dbSDimitry Andric } else if (main_info->GetObjectForDotSeparatedPath("issue_type") 9685ffd83dbSDimitry Andric ->GetStringValue() == "swift-access-race") { 9695ffd83dbSDimitry Andric result = Sprintf("modifying access by thread %d", thread_id); 9705ffd83dbSDimitry Andric } else { 9715ffd83dbSDimitry Andric result = Sprintf("%s%s of size %d%s by thread %d", 9725ffd83dbSDimitry Andric is_atomic ? "atomic " : "", is_write ? "write" : "read", 9735ffd83dbSDimitry Andric size, addr_string.c_str(), thread_id); 9745ffd83dbSDimitry Andric } 9755ffd83dbSDimitry Andric } 9765ffd83dbSDimitry Andric 9775ffd83dbSDimitry Andric if (path == "threads") { 9785ffd83dbSDimitry Andric int thread_id = 9795ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); 9805ffd83dbSDimitry Andric result = Sprintf("Thread %d created", thread_id); 9815ffd83dbSDimitry Andric } 9825ffd83dbSDimitry Andric 9835ffd83dbSDimitry Andric if (path == "locs") { 9845ffd83dbSDimitry Andric std::string type = std::string( 9855ffd83dbSDimitry Andric o->GetAsDictionary()->GetValueForKey("type")->GetStringValue()); 9865ffd83dbSDimitry Andric int thread_id = 9875ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); 9885ffd83dbSDimitry Andric int fd = 9895ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("file_descriptor")->GetIntegerValue(); 9905ffd83dbSDimitry Andric if (type == "heap") { 9915ffd83dbSDimitry Andric result = Sprintf("Heap block allocated by thread %d", thread_id); 9925ffd83dbSDimitry Andric } else if (type == "fd") { 9935ffd83dbSDimitry Andric result = 9945ffd83dbSDimitry Andric Sprintf("File descriptor %d created by thread %t", fd, thread_id); 9955ffd83dbSDimitry Andric } 9965ffd83dbSDimitry Andric } 9975ffd83dbSDimitry Andric 9985ffd83dbSDimitry Andric if (path == "mutexes") { 9995ffd83dbSDimitry Andric int mutex_id = 10005ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("mutex_id")->GetIntegerValue(); 10015ffd83dbSDimitry Andric 10025ffd83dbSDimitry Andric result = Sprintf("Mutex M%d created", mutex_id); 10035ffd83dbSDimitry Andric } 10045ffd83dbSDimitry Andric 10055ffd83dbSDimitry Andric if (path == "stacks") { 10065ffd83dbSDimitry Andric int thread_id = 10075ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); 10085ffd83dbSDimitry Andric result = Sprintf("Thread %d", thread_id); 10095ffd83dbSDimitry Andric } 10105ffd83dbSDimitry Andric 10115ffd83dbSDimitry Andric result[0] = toupper(result[0]); 10125ffd83dbSDimitry Andric 10135ffd83dbSDimitry Andric return result; 10145ffd83dbSDimitry Andric } 10155ffd83dbSDimitry Andric 10165ffd83dbSDimitry Andric static void AddThreadsForPath(const std::string &path, 10175ffd83dbSDimitry Andric ThreadCollectionSP threads, ProcessSP process_sp, 10185ffd83dbSDimitry Andric StructuredData::ObjectSP info) { 10195ffd83dbSDimitry Andric info->GetObjectForDotSeparatedPath(path)->GetAsArray()->ForEach( 10205ffd83dbSDimitry Andric [process_sp, threads, path, info](StructuredData::Object *o) -> bool { 10215ffd83dbSDimitry Andric std::vector<lldb::addr_t> pcs; 10225ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("trace")->GetAsArray()->ForEach( 10235ffd83dbSDimitry Andric [&pcs](StructuredData::Object *pc) -> bool { 10245ffd83dbSDimitry Andric pcs.push_back(pc->GetAsInteger()->GetValue()); 10255ffd83dbSDimitry Andric return true; 10265ffd83dbSDimitry Andric }); 10275ffd83dbSDimitry Andric 10285ffd83dbSDimitry Andric if (pcs.size() == 0) 10295ffd83dbSDimitry Andric return true; 10305ffd83dbSDimitry Andric 10315ffd83dbSDimitry Andric StructuredData::ObjectSP thread_id_obj = 10325ffd83dbSDimitry Andric o->GetObjectForDotSeparatedPath("thread_os_id"); 10335ffd83dbSDimitry Andric tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; 10345ffd83dbSDimitry Andric 10355ffd83dbSDimitry Andric HistoryThread *history_thread = 10365ffd83dbSDimitry Andric new HistoryThread(*process_sp, tid, pcs); 10375ffd83dbSDimitry Andric ThreadSP new_thread_sp(history_thread); 10385ffd83dbSDimitry Andric new_thread_sp->SetName(GenerateThreadName(path, o, info).c_str()); 10395ffd83dbSDimitry Andric 10405ffd83dbSDimitry Andric // Save this in the Process' ExtendedThreadList so a strong pointer 10415ffd83dbSDimitry Andric // retains the object 10425ffd83dbSDimitry Andric process_sp->GetExtendedThreadList().AddThread(new_thread_sp); 10435ffd83dbSDimitry Andric threads->AddThread(new_thread_sp); 10445ffd83dbSDimitry Andric 10455ffd83dbSDimitry Andric return true; 10465ffd83dbSDimitry Andric }); 10475ffd83dbSDimitry Andric } 10485ffd83dbSDimitry Andric 10495ffd83dbSDimitry Andric lldb::ThreadCollectionSP 10505ffd83dbSDimitry Andric InstrumentationRuntimeTSan::GetBacktracesFromExtendedStopInfo( 10515ffd83dbSDimitry Andric StructuredData::ObjectSP info) { 10525ffd83dbSDimitry Andric ThreadCollectionSP threads; 10535ffd83dbSDimitry Andric threads = std::make_shared<ThreadCollection>(); 10545ffd83dbSDimitry Andric 10555ffd83dbSDimitry Andric if (info->GetObjectForDotSeparatedPath("instrumentation_class") 10565ffd83dbSDimitry Andric ->GetStringValue() != "ThreadSanitizer") 10575ffd83dbSDimitry Andric return threads; 10585ffd83dbSDimitry Andric 10595ffd83dbSDimitry Andric ProcessSP process_sp = GetProcessSP(); 10605ffd83dbSDimitry Andric 10615ffd83dbSDimitry Andric AddThreadsForPath("stacks", threads, process_sp, info); 10625ffd83dbSDimitry Andric AddThreadsForPath("mops", threads, process_sp, info); 10635ffd83dbSDimitry Andric AddThreadsForPath("locs", threads, process_sp, info); 10645ffd83dbSDimitry Andric AddThreadsForPath("mutexes", threads, process_sp, info); 10655ffd83dbSDimitry Andric AddThreadsForPath("threads", threads, process_sp, info); 10665ffd83dbSDimitry Andric 10675ffd83dbSDimitry Andric return threads; 10685ffd83dbSDimitry Andric } 1069