Skip to content

Commit e9b758d

Browse files
authored
Merge pull request #4128 from medismailben/stable/20211026
2 parents e3a4cf9 + e01f2b1 commit e9b758d

File tree

6 files changed

+81
-47
lines changed

6 files changed

+81
-47
lines changed

lldb/examples/python/crashlog.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ class Thread:
7676

7777
def __init__(self, index, app_specific_backtrace):
7878
self.index = index
79+
self.id = index
7980
self.frames = list()
8081
self.idents = list()
8182
self.registers = dict()
8283
self.reason = None
84+
self.name = None
8385
self.queue = None
8486
self.crashed = False
8587
self.app_specific_backtrace = app_specific_backtrace
@@ -521,14 +523,18 @@ def parse_threads(self, json_threads):
521523
for json_thread in json_threads:
522524
thread = self.crashlog.Thread(idx, False)
523525
if 'name' in json_thread:
526+
thread.name = json_thread['name']
524527
thread.reason = json_thread['name']
528+
if 'id' in json_thread:
529+
thread.id = int(json_thread['id'])
525530
if json_thread.get('triggered', False):
526531
self.crashlog.crashed_thread_idx = idx
527532
thread.crashed = True
528533
if 'threadState' in json_thread:
529534
thread.registers = self.parse_thread_registers(
530535
json_thread['threadState'])
531-
thread.queue = json_thread.get('queue')
536+
if 'queue' in json_thread:
537+
thread.queue = json_thread.get('queue')
532538
self.parse_frames(thread, json_thread.get('frames', []))
533539
self.crashlog.threads.append(thread)
534540
idx += 1

lldb/examples/python/scripted_process/crashlog_scripted_process.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,12 @@ def __init__(self, process, args, crashlog_thread):
135135

136136
self.backing_thread = crashlog_thread
137137
self.idx = self.backing_thread.index
138+
self.tid = self.backing_thread.id
139+
self.name = self.backing_thread.name
140+
self.queue = self.backing_thread.queue
138141
self.has_crashed = (self.scripted_process.crashed_thread_idx == self.idx)
139142
self.create_stackframes()
140143

141-
def get_thread_id(self) -> int:
142-
return self.idx
143-
144-
def get_name(self) -> str:
145-
return CrashLogScriptedThread.__name__ + ".thread-" + str(self.idx)
146-
147144
def get_state(self):
148145
if not self.has_crashed:
149146
return lldb.eStateStopped

lldb/examples/python/scripted_process/scripted_process.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ def __init__(self, scripted_process, args):
219219
self.scripted_process = None
220220
self.process = None
221221
self.args = None
222-
223-
self.id = None
222+
self.idx = 0
223+
self.tid = 0
224224
self.idx = None
225225
self.name = None
226226
self.queue = None
@@ -236,24 +236,29 @@ def __init__(self, scripted_process, args):
236236
self.process = self.target.GetProcess()
237237
self.get_register_info()
238238

239+
def get_thread_idx(self):
240+
""" Get the scripted thread index.
241+
242+
Returns:
243+
int: The index of the scripted thread in the scripted process.
244+
"""
245+
return self.idx
239246

240-
@abstractmethod
241247
def get_thread_id(self):
242248
""" Get the scripted thread identifier.
243249
244250
Returns:
245251
int: The identifier of the scripted thread.
246252
"""
247-
pass
253+
return self.tid
248254

249-
@abstractmethod
250255
def get_name(self):
251256
""" Get the scripted thread name.
252257
253258
Returns:
254259
str: The name of the scripted thread.
255260
"""
256-
pass
261+
return self.name
257262

258263
def get_state(self):
259264
""" Get the scripted thread state type.
@@ -277,7 +282,7 @@ def get_queue(self):
277282
Returns:
278283
str: The queue name associated with the scripted thread.
279284
"""
280-
pass
285+
return self.queue
281286

282287
@abstractmethod
283288
def get_stop_reason(self):

lldb/include/lldb/Utility/StructuredData.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,15 +376,15 @@ class StructuredData {
376376
}
377377
}
378378

379-
ObjectSP GetKeys() const {
380-
auto object_sp = std::make_shared<Array>();
379+
ArraySP GetKeys() const {
380+
auto array_sp = std::make_shared<Array>();
381381
collection::const_iterator iter;
382382
for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
383383
auto key_object_sp = std::make_shared<String>();
384384
key_object_sp->SetValue(iter->first.AsCString());
385-
object_sp->Push(key_object_sp);
385+
array_sp->Push(key_object_sp);
386386
}
387-
return object_sp;
387+
return array_sp;
388388
}
389389

390390
ObjectSP GetValueForKey(llvm::StringRef key) const {

lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -309,35 +309,55 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
309309

310310
StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
311311

312-
// FIXME: Need to sort the dictionary otherwise the thread ids won't match the
313-
// thread indices.
314-
315312
if (!thread_info_sp)
316313
return ScriptedInterface::ErrorWithMessage<bool>(
317314
LLVM_PRETTY_FUNCTION,
318315
"Couldn't fetch thread list from Scripted Process.", error);
319316

317+
// Because `StructuredData::Dictionary` uses a `std::map<ConstString,
318+
// ObjectSP>` for storage, each item is sorted based on the key alphabetical
319+
// order. Since `GetThreadsInfo` provides thread indices as the key element,
320+
// thread info comes ordered alphabetically, instead of numerically, so we
321+
// need to sort the thread indices before creating thread.
322+
323+
StructuredData::ArraySP keys = thread_info_sp->GetKeys();
324+
325+
std::map<size_t, StructuredData::ObjectSP> sorted_threads;
326+
auto sort_keys = [&sorted_threads,
327+
&thread_info_sp](StructuredData::Object *item) -> bool {
328+
if (!item)
329+
return false;
330+
331+
llvm::StringRef key = item->GetStringValue();
332+
size_t idx = 0;
333+
334+
// Make sure the provided index is actually an integer
335+
if (!llvm::to_integer(key, idx))
336+
return false;
337+
338+
sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
339+
return true;
340+
};
341+
342+
size_t thread_count = thread_info_sp->GetSize();
343+
344+
if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
345+
// Might be worth showing the unsorted thread list instead of return early.
346+
return ScriptedInterface::ErrorWithMessage<bool>(
347+
LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);
348+
320349
auto create_scripted_thread =
321-
[this, &old_thread_list, &error,
322-
&new_thread_list](ConstString key, StructuredData::Object *val) -> bool {
323-
if (!val)
324-
return ScriptedInterface::ErrorWithMessage<bool>(
325-
LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
350+
[this, &error, &new_thread_list](
351+
const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
352+
size_t idx = pair.first;
353+
StructuredData::ObjectSP object_sp = pair.second;
326354

327-
lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
328-
if (!llvm::to_integer(key.AsCString(), tid))
355+
if (!object_sp)
329356
return ScriptedInterface::ErrorWithMessage<bool>(
330-
LLVM_PRETTY_FUNCTION, "Invalid thread id", error);
331-
332-
if (ThreadSP thread_sp =
333-
old_thread_list.FindThreadByID(tid, false /*=can_update*/)) {
334-
// If the thread was already in the old_thread_list,
335-
// just add it back to the new_thread_list.
336-
new_thread_list.AddThread(thread_sp);
337-
return true;
338-
}
357+
LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
339358

340-
auto thread_or_error = ScriptedThread::Create(*this, val->GetAsGeneric());
359+
auto thread_or_error =
360+
ScriptedThread::Create(*this, object_sp->GetAsGeneric());
341361

342362
if (!thread_or_error)
343363
return ScriptedInterface::ErrorWithMessage<bool>(
@@ -350,8 +370,7 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
350370
if (!reg_ctx_sp)
351371
return ScriptedInterface::ErrorWithMessage<bool>(
352372
LLVM_PRETTY_FUNCTION,
353-
llvm::Twine("Invalid Register Context for thread " +
354-
llvm::Twine(key.AsCString()))
373+
llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
355374
.str(),
356375
error);
357376

@@ -360,7 +379,7 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
360379
return true;
361380
};
362381

363-
thread_info_sp->ForEach(create_scripted_thread);
382+
llvm::for_each(sorted_threads, create_scripted_thread);
364383

365384
return new_thread_list.GetSize(false) > 0;
366385
}

lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44

55
# RUN: cp %S/Inputs/scripted_crashlog.ips %t.crash
66
# RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":160, "bar":20, "foo":24}' --json
7-
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -a -i %t.crash' 2>&1 -o "bt all" | FileCheck %s
7+
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -a -i %t.crash' 2>&1 -o "thread list" -o "bt all" | FileCheck %s
88

99
# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands
1010

1111
# CHECK: (lldb) process status
1212
# CHECK-NEXT: Process 24991 stopped
13-
# CHECK-NEXT: * thread #3, name = 'CrashLogScriptedThread.thread-2', stop reason = EXC_BAD_ACCESS
13+
# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS
1414
# CHECK-NEXT: frame #0: 0x00000001047f5970 scripted_crashlog_json.test.tmp.out`bar
1515

1616
# CHECK: (lldb) thread backtrace
17-
# CHECK-NEXT: * thread #3, name = 'CrashLogScriptedThread.thread-2', stop reason = EXC_BAD_ACCESS
17+
# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS
1818
# CHECK-NEXT: * frame #0: 0x00000001047f5970 scripted_crashlog_json.test.tmp.out`bar
1919
# CHECK-NEXT: frame #1: 0x00000001047f5998 scripted_crashlog_json.test.tmp.out`foo
2020
# CHECK-NEXT: frame #2: 0x00000001047f5b04 scripted_crashlog_json.test.tmp.out`compute_pow
@@ -24,22 +24,29 @@
2424
# CHECK-NEXT: frame #6: 0x000000018bf5326c libsystem_pthread.dylib`_pthread_start
2525
# CHECK-NEXT: frame #7: 0x000000018bf4e08c libsystem_pthread.dylib`thread_start
2626

27+
# CHECK: (lldb) thread list
28+
# CHECK-NEXT: Process 24991 stopped
29+
# CHECK-NEXT: thread #1: tid = 0x4ea840, 0x000000018bf17854 libsystem_kernel.dylib`__ulock_wait{{.*}}, queue = 'com.apple.main-thread'
30+
# CHECK-NEXT: thread #2: tid = 0x4ea850, 0x00000001047f59e8 scripted_crashlog_json.test.tmp.out`call_and_wait
31+
# CHECK-NEXT: * thread #3: tid = 0x4ea851, 0x00000001047f5970 scripted_crashlog_json.test.tmp.out`bar{{.*}}, stop reason = EXC_BAD_ACCESS
32+
33+
2734
# CHECK: (lldb) bt all
28-
# CHECK-NEXT: thread #1, name = 'CrashLogScriptedThread.thread-0'
35+
# CHECK-NEXT: thread #1
2936
# CHECK-NEXT: frame #0: 0x000000018bf17854 libsystem_kernel.dylib`__ulock_wait
3037
# CHECK-NEXT: frame #1: 0x000000018bf555a0 libsystem_pthread.dylib`_pthread_join
3138
# CHECK-NEXT: frame #2: 0x000000018beae9c0 libc++.1.dylib`std::__1::thread::join
3239
# CHECK-NEXT: frame #3: 0x00000001047f5bb8 scripted_crashlog_json.test.tmp.out`main
3340
# CHECK-NEXT: frame #4: 0x0000000104ae5088 dyld`start
34-
# CHECK-NEXT: thread #2, name = 'CrashLogScriptedThread.thread-1'
41+
# CHECK-NEXT: thread #2
3542
# CHECK-NEXT: frame #0: 0x00000001047f59e8 scripted_crashlog_json.test.tmp.out`call_and_wait
3643
# CHECK-NEXT: frame #1: 0x00000001047f59d4 scripted_crashlog_json.test.tmp.out`call_and_wait
3744
# CHECK-NEXT: frame #2: 0x00000001047f7690 scripted_crashlog_json.test.tmp.out`decltype
3845
# CHECK-NEXT: frame #3: 0x00000001047f7614 scripted_crashlog_json.test.tmp.out`void std::__1::__thread_execute
3946
# CHECK-NEXT: frame #4: 0x00000001047f6d58 scripted_crashlog_json.test.tmp.out`void* std::__1::__thread_proxy
4047
# CHECK-NEXT: frame #5: 0x000000018bf5326c libsystem_pthread.dylib`_pthread_start
4148
# CHECK-NEXT: frame #6: 0x000000018bf4e08c libsystem_pthread.dylib`thread_start
42-
# CHECK-NEXT: * thread #3, name = 'CrashLogScriptedThread.thread-2', stop reason = EXC_BAD_ACCESS
49+
# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS
4350
# CHECK-NEXT: * frame #0: 0x00000001047f5970 scripted_crashlog_json.test.tmp.out`bar
4451
# CHECK-NEXT: frame #1: 0x00000001047f5998 scripted_crashlog_json.test.tmp.out`foo
4552
# CHECK-NEXT: frame #2: 0x00000001047f5b04 scripted_crashlog_json.test.tmp.out`compute_pow

0 commit comments

Comments
 (0)