forked from OSchip/llvm-project
[lldb] Consider binary as module of last resort
When setting an address breakpoint using a non-section address in lldb before having ever run the program, the binary itself is not considered a module. As a result, the breakpoint is unresolved (and never gets resolved subsequently). This patch changes that behavior: as a last resort, the binary is considered as a module when resolving a non-section address breakpoint. Differential revision: https://reviews.llvm.org/D124731
This commit is contained in:
parent
bd62b70b51
commit
a3c3482ceb
|
@ -121,16 +121,27 @@ Searcher::CallbackReturn BreakpointResolverAddress::SearchCallback(
|
|||
|
||||
if (filter.AddressPasses(m_addr)) {
|
||||
if (breakpoint.GetNumLocations() == 0) {
|
||||
// If the address is just an offset, and we're given a module, see if we
|
||||
// can find the appropriate module loaded in the binary, and fix up
|
||||
// m_addr to use that.
|
||||
if (!m_addr.IsSectionOffset() && m_module_filespec) {
|
||||
// If the address is just an offset ...
|
||||
if (!m_addr.IsSectionOffset()) {
|
||||
ModuleSP containing_module_sp = nullptr;
|
||||
Target &target = breakpoint.GetTarget();
|
||||
ModuleSpec module_spec(m_module_filespec);
|
||||
ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec);
|
||||
if (module_sp) {
|
||||
if (m_module_filespec) {
|
||||
// ... and we're given a module, see if we can find the
|
||||
// appropriate module loaded in the binary, and fix up
|
||||
// m_addr to use that.
|
||||
ModuleSpec module_spec(m_module_filespec);
|
||||
containing_module_sp =
|
||||
target.GetImages().FindFirstModule(module_spec);
|
||||
} else {
|
||||
// ... and we're not given a module, see if the offset is
|
||||
// somewhere in the executable module. If it is, then we'll
|
||||
// fix up m_addr to use that.
|
||||
containing_module_sp = target.GetExecutableModule();
|
||||
}
|
||||
if (containing_module_sp) {
|
||||
Address tmp_address;
|
||||
if (module_sp->ResolveFileAddress(m_addr.GetOffset(), tmp_address))
|
||||
if (containing_module_sp->ResolveFileAddress(m_addr.GetOffset(),
|
||||
tmp_address))
|
||||
m_addr = tmp_address;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,13 +128,15 @@ let Command = "breakpoint set" in {
|
|||
Arg<"AddressOrExpression">, Required,
|
||||
Desc<"Set the breakpoint at the specified address. If the address maps "
|
||||
"uniquely to a particular binary, then the address will be converted to "
|
||||
"a \"file\"address, so that the breakpoint will track that binary+offset "
|
||||
"a \"file\" address, so that the breakpoint will track that binary+offset "
|
||||
"no matter where the binary eventually loads. Alternately, if you also "
|
||||
"specify the module - with the -s option - then the address will be "
|
||||
"treated as a file address in that module, and resolved accordingly. "
|
||||
"Again, this will allow lldb to track that offset on subsequent reloads. "
|
||||
"The module need not have been loaded at the time you specify this "
|
||||
"breakpoint, and will get resolved when the module is loaded.">;
|
||||
"breakpoint, and will get resolved when the module is loaded. If no "
|
||||
"module is specified, the binary being debugged is considered as a "
|
||||
"fallback.">;
|
||||
def breakpoint_set_name : Option<"name", "n">, Group<3>, Arg<"FunctionName">,
|
||||
Completion<"Symbol">, Required,
|
||||
Desc<"Set the breakpoint by function name. Can be repeated multiple times "
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
C_SOURCES := inferior.c
|
||||
|
||||
include Makefile.rules
|
|
@ -0,0 +1,36 @@
|
|||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
class TestCase(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
def get_address_from_symbol(self, symbol):
|
||||
target = lldbutil.run_to_breakpoint_make_target(self, "a.out", True)
|
||||
bp = target.BreakpointCreateByName(symbol, None)
|
||||
address = bp.GetLocationAtIndex(0).GetAddress().GetFileAddress()
|
||||
return address
|
||||
|
||||
def test_set_address_no_module(self):
|
||||
self.build()
|
||||
|
||||
main_address = self.get_address_from_symbol("main")
|
||||
|
||||
target = lldbutil.run_to_breakpoint_make_target(self)
|
||||
debugger = target.GetDebugger()
|
||||
|
||||
debugger.HandleCommand(f"break set -a {main_address:#x}")
|
||||
self.assertEquals(target.GetNumBreakpoints(), 1)
|
||||
|
||||
bp = target.GetBreakpointAtIndex(0)
|
||||
self.assertIsNotNone(bp)
|
||||
|
||||
_, _, thread, _ = lldbutil.run_to_breakpoint_do_run(self, target, bp)
|
||||
self.assertGreaterEqual(thread.GetNumFrames(), 1)
|
||||
|
||||
thread_pc = thread.GetFrameAtIndex(0).GetPCAddress()
|
||||
self.assertNotEqual(thread_pc, None)
|
||||
|
||||
self.assertEquals(main_address, thread_pc.GetFileAddress())
|
|
@ -0,0 +1,6 @@
|
|||
int function(int a) { return a; }
|
||||
|
||||
int main() {
|
||||
int f = function(10);
|
||||
return f;
|
||||
}
|
Loading…
Reference in New Issue