Skip to content

Commit 83f8b20

Browse files
authored
Merge pull request #3638 from medismailben/stable/20210726
[lldb/plugins] Add arm64(e) support to ScriptedProcess
2 parents 5b63b49 + 0c0be33 commit 83f8b20

File tree

5 files changed

+181
-13
lines changed

5 files changed

+181
-13
lines changed

lldb/examples/python/scripted_process/scripted_process.py

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,14 @@ def get_register_info(self):
298298
self.register_info['registers'] = [
299299
{'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0},
300300
{'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3},
301-
{'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4', },
302-
{'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3', },
303-
{'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1', },
304-
{'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2', },
305-
{'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp', },
306-
{'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp', },
307-
{'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5', },
308-
{'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6', },
301+
{'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4'},
302+
{'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3'},
303+
{'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1'},
304+
{'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2'},
305+
{'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp'},
306+
{'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp'},
307+
{'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5'},
308+
{'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6'},
309309
{'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10},
310310
{'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11},
311311
{'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12},
@@ -316,8 +316,47 @@ def get_register_info(self):
316316
{'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'},
317317
{'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0},
318318
{'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0},
319-
{'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0},
319+
{'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0}
320320
]
321+
elif 'arm64' in arch:
322+
self.register_info['sets'] = ['General Purpose Registers']
323+
self.register_info['registers'] = [
324+
{'name': 'x0', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0, 'generic': 'arg0', 'alt-name': 'arg0'},
325+
{'name': 'x1', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg1', 'alt-name': 'arg1'},
326+
{'name': 'x2', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg2', 'alt-name': 'arg2'},
327+
{'name': 'x3', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3, 'generic': 'arg3', 'alt-name': 'arg3'},
328+
{'name': 'x4', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg4', 'alt-name': 'arg4'},
329+
{'name': 'x5', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg5', 'alt-name': 'arg5'},
330+
{'name': 'x6', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'arg6', 'alt-name': 'arg6'},
331+
{'name': 'x7', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'arg7', 'alt-name': 'arg7'},
332+
{'name': 'x8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8 },
333+
{'name': 'x9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9 },
334+
{'name': 'x10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10},
335+
{'name': 'x11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11},
336+
{'name': 'x12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12},
337+
{'name': 'x13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13},
338+
{'name': 'x14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14},
339+
{'name': 'x15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15},
340+
{'name': 'x16', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16},
341+
{'name': 'x17', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 17, 'dwarf': 17},
342+
{'name': 'x18', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 18, 'dwarf': 18},
343+
{'name': 'x19', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 19, 'dwarf': 19},
344+
{'name': 'x20', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 20, 'dwarf': 20},
345+
{'name': 'x21', 'bitsize': 64, 'offset': 168, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 21, 'dwarf': 21},
346+
{'name': 'x22', 'bitsize': 64, 'offset': 176, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 22, 'dwarf': 22},
347+
{'name': 'x23', 'bitsize': 64, 'offset': 184, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 23, 'dwarf': 23},
348+
{'name': 'x24', 'bitsize': 64, 'offset': 192, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 24, 'dwarf': 24},
349+
{'name': 'x25', 'bitsize': 64, 'offset': 200, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 25, 'dwarf': 25},
350+
{'name': 'x26', 'bitsize': 64, 'offset': 208, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 26, 'dwarf': 26},
351+
{'name': 'x27', 'bitsize': 64, 'offset': 216, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 27, 'dwarf': 27},
352+
{'name': 'x28', 'bitsize': 64, 'offset': 224, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 28, 'dwarf': 28},
353+
{'name': 'x29', 'bitsize': 64, 'offset': 232, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 29, 'dwarf': 29, 'generic': 'fp', 'alt-name': 'fp'},
354+
{'name': 'x30', 'bitsize': 64, 'offset': 240, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 30, 'dwarf': 30, 'generic': 'lr', 'alt-name': 'lr'},
355+
{'name': 'sp', 'bitsize': 64, 'offset': 248, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 31, 'dwarf': 31, 'generic': 'sp', 'alt-name': 'sp'},
356+
{'name': 'pc', 'bitsize': 64, 'offset': 256, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 32, 'dwarf': 32, 'generic': 'pc', 'alt-name': 'pc'},
357+
{'name': 'cpsr', 'bitsize': 32, 'offset': 264, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 33, 'dwarf': 33}
358+
]
359+
else: raise ValueError('Unknown architecture', arch)
321360
return self.register_info
322361

323362
@abstractmethod

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,11 @@ bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
320320
return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
321321
error.AsCString(), error);
322322

323+
RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
324+
if (!reg_ctx_sp)
325+
return GetInterface().ErrorWithMessage<bool>(
326+
LLVM_PRETTY_FUNCTION, "Invalid Register Context", error);
327+
323328
new_thread_list.AddThread(thread_sp);
324329

325330
return new_thread_list.GetSize(false) > 0;

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,17 @@ std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() {
198198

199199
if (!m_register_info_sp) {
200200
StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
201+
202+
Status error;
201203
if (!reg_info)
202-
return nullptr;
204+
return GetInterface()
205+
->ErrorWithMessage<std::shared_ptr<DynamicRegisterInfo>>(
206+
LLVM_PRETTY_FUNCTION,
207+
"Failed to get scripted thread registers info.", error,
208+
LIBLLDB_LOG_THREAD);
203209

204210
m_register_info_sp = std::make_shared<DynamicRegisterInfo>(
205211
*reg_info, m_scripted_process.GetTarget().GetArchitecture());
206-
assert(m_register_info_sp->GetNumRegisters() > 0);
207-
assert(m_register_info_sp->GetNumRegisterSets() > 0);
208212
}
209213

210214
return m_register_info_sp;

lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,42 @@ def test_python_plugin_package(self):
4141
self.expect('script dir(ScriptedProcess)',
4242
substrs=["launch"])
4343

44+
def test_invalid_scripted_register_context(self):
45+
"""Test that we can launch an lldb scripted process with an invalid
46+
Scripted Thread, with invalid register context."""
47+
self.build()
48+
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
49+
self.assertTrue(target, VALID_TARGET)
50+
log_file = self.getBuildArtifact('thread.log')
51+
self.runCmd("log enable lldb thread -f " + log_file)
52+
self.assertTrue(os.path.isfile(log_file))
53+
54+
os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
55+
def cleanup():
56+
del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
57+
self.addTearDownHook(cleanup)
58+
59+
scripted_process_example_relpath = 'invalid_scripted_process.py'
60+
self.runCmd("command script import " + os.path.join(self.getSourceDir(),
61+
scripted_process_example_relpath))
62+
63+
launch_info = lldb.SBLaunchInfo(None)
64+
launch_info.SetProcessPluginName("ScriptedProcess")
65+
launch_info.SetScriptedProcessClassName("invalid_scripted_process.InvalidScriptedProcess")
66+
error = lldb.SBError()
67+
68+
process = target.Launch(launch_info, error)
69+
70+
self.assertTrue(error.Success(), error.GetCString())
71+
self.assertTrue(process, PROCESS_IS_VALID)
72+
self.assertEqual(process.GetProcessID(), 666)
73+
self.assertEqual(process.GetNumThreads(), 0)
74+
75+
with open(log_file, 'r') as f:
76+
log = f.read()
77+
78+
self.assertIn("Failed to get scripted thread registers data.", log)
79+
4480
@skipIf(archs=no_match(['x86_64']))
4581
def test_scripted_process_and_scripted_thread(self):
4682
"""Test that we can launch an lldb scripted process using the SBAPI,
@@ -103,7 +139,7 @@ def create_stack_skinny_corefile(self, file):
103139

104140
@skipUnlessDarwin
105141
@skipIfOutOfTreeDebugserver
106-
@skipIf(archs=no_match(['x86_64']))
142+
@skipIfAsan # rdar://85954489
107143
def test_launch_scripted_process_stack_frames(self):
108144
"""Test that we can launch an lldb scripted process from the command
109145
line, check its process ID and read string from memory."""
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import os,struct, signal
2+
3+
from typing import Any, Dict
4+
5+
import lldb
6+
from lldb.plugins.scripted_process import ScriptedProcess
7+
from lldb.plugins.scripted_process import ScriptedThread
8+
9+
class InvalidScriptedProcess(ScriptedProcess):
10+
def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
11+
super().__init__(target, args)
12+
13+
def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
14+
return None
15+
16+
def get_thread_with_id(self, tid: int):
17+
return {}
18+
19+
def get_registers_for_thread(self, tid: int):
20+
return {}
21+
22+
def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData:
23+
return None
24+
25+
def get_loaded_images(self):
26+
return self.loaded_images
27+
28+
def get_process_id(self) -> int:
29+
return 666
30+
31+
def should_stop(self) -> bool:
32+
return True
33+
34+
def is_alive(self) -> bool:
35+
return True
36+
37+
def get_scripted_thread_plugin(self):
38+
return InvalidScriptedThread.__module__ + "." + InvalidScriptedThread.__name__
39+
40+
41+
class InvalidScriptedThread(ScriptedThread):
42+
def __init__(self, process, args):
43+
super().__init__(process, args)
44+
45+
def get_thread_id(self) -> int:
46+
return 0x19
47+
48+
def get_name(self) -> str:
49+
return InvalidScriptedThread.__name__ + ".thread-1"
50+
51+
def get_state(self) -> int:
52+
return lldb.eStateInvalid
53+
54+
def get_stop_reason(self) -> Dict[str, Any]:
55+
return { "type": lldb.eStopReasonSignal, "data": {
56+
"signal": signal.SIGINT
57+
} }
58+
59+
def get_stackframes(self):
60+
class ScriptedStackFrame:
61+
def __init__(idx, cfa, pc, symbol_ctx):
62+
self.idx = idx
63+
self.cfa = cfa
64+
self.pc = pc
65+
self.symbol_ctx = symbol_ctx
66+
67+
68+
symbol_ctx = lldb.SBSymbolContext()
69+
frame_zero = ScriptedStackFrame(0, 0x42424242, 0x5000000, symbol_ctx)
70+
self.frames.append(frame_zero)
71+
72+
return self.frame_zero[0:0]
73+
74+
def get_register_context(self) -> str:
75+
return None
76+
77+
def __lldb_init_module(debugger, dict):
78+
if not 'SKIP_SCRIPTED_PROCESS_LAUNCH' in os.environ:
79+
debugger.HandleCommand(
80+
"process launch -C %s.%s" % (__name__,
81+
InvalidScriptedProcess.__name__))
82+
else:
83+
print("Name of the class that will manage the scripted process: '%s.%s'"
84+
% (__name__, InvalidScriptedProcess.__name__))

0 commit comments

Comments
 (0)