Skip to content

[lldb] Handle an empty SBMemoryRegionInfo from scripted process #115963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion lldb/source/Target/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6184,7 +6184,12 @@ Status Process::GetMemoryRegionInfo(lldb::addr_t load_addr,
MemoryRegionInfo &range_info) {
if (const lldb::ABISP &abi = GetABI())
load_addr = abi->FixAnyAddress(load_addr);
return DoGetMemoryRegionInfo(load_addr, range_info);
Status error = DoGetMemoryRegionInfo(load_addr, range_info);
// Reject a region that does not contain the requested address.
if (error.Success() && !range_info.GetRange().Contains(load_addr))
error = Status::FromErrorString("Invalid memory region");

return error;
}

Status Process::GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
C_SOURCES := main.c

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
Test python scripted process which returns an empty SBMemoryRegionInfo
"""

import os, shutil

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
from lldbsuite.test import lldbtest


class ScriptedProcessEmptyMemoryRegion(TestBase):
NO_DEBUG_INFO_TESTCASE = True

def test_scripted_process_empty_memory_region(self):
"""Test that lldb handles an empty SBMemoryRegionInfo object from
a scripted process plugin."""
self.build()

target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
self.assertTrue(target, VALID_TARGET)

scripted_process_example_relpath = "dummy_scripted_process.py"
self.runCmd(
"command script import "
+ os.path.join(self.getSourceDir(), scripted_process_example_relpath)
)

self.expect("memory region 0", error=True, substrs=["Invalid memory region"])

self.expect("expr -- 5", substrs=["5"])
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import os, struct, signal

from typing import Any, Dict

import lldb
from lldb.plugins.scripted_process import ScriptedProcess
from lldb.plugins.scripted_process import ScriptedThread


class DummyScriptedProcess(ScriptedProcess):
memory = None

def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData):
super().__init__(exe_ctx, args)
self.threads[0] = DummyScriptedThread(self, None)
self.memory = {}
addr = 0x500000000
debugger = self.target.GetDebugger()
index = debugger.GetIndexOfTarget(self.target)
self.memory[addr] = "Hello, target " + str(index)
self.handled_stop = False

def read_memory_at_address(
self, addr: int, size: int, error: lldb.SBError
) -> lldb.SBData:
data = lldb.SBData().CreateDataFromCString(
self.target.GetByteOrder(), self.target.GetCodeByteSize(), self.memory[addr]
)

return data

def get_memory_region_containing_address(
self, addr: int
) -> lldb.SBMemoryRegionInfo:
return lldb.SBMemoryRegionInfo()

def write_memory_at_address(self, addr, data, error):
self.memory[addr] = data.GetString(error, 0)
return len(self.memory[addr]) + 1

def get_loaded_images(self):
return self.loaded_images

def get_process_id(self) -> int:
return 42

def should_stop(self) -> bool:
return True

def is_alive(self) -> bool:
return True

def get_scripted_thread_plugin(self):
return DummyScriptedThread.__module__ + "." + DummyScriptedThread.__name__

def my_super_secret_method(self):
if hasattr(self, "my_super_secret_member"):
return self.my_super_secret_member
else:
return None


class DummyScriptedThread(ScriptedThread):
def __init__(self, process, args):
super().__init__(process, args)
self.frames.append({"pc": 0x0100001B00})

def get_thread_id(self) -> int:
return 0x19

def get_name(self) -> str:
return DummyScriptedThread.__name__ + ".thread-1"

def get_state(self) -> int:
return lldb.eStateStopped

def get_stop_reason(self) -> Dict[str, Any]:
return {"type": lldb.eStopReasonTrace, "data": {}}

def get_register_context(self) -> str:
return struct.pack(
"21Q",
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
)


def __lldb_init_module(debugger, dict):
debugger.HandleCommand(
"process launch -C %s.%s" % (__name__, DummyScriptedProcess.__name__)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int main() {}
Loading