forked from OSchip/llvm-project
First tests for serializing breakpoints.
Plus a few bug fixes I found along the way. llvm-svn: 281690
This commit is contained in:
parent
6c7a0bc3d9
commit
6d1e4696a2
|
@ -104,6 +104,8 @@ public:
|
|||
|
||||
bool GetDescription(lldb::SBStream &description);
|
||||
|
||||
bool GetDescription(lldb::SBStream &description, bool include_locations);
|
||||
|
||||
static bool EventIsBreakpointEvent(const lldb::SBEvent &event);
|
||||
|
||||
static lldb::BreakpointEventType
|
||||
|
@ -152,6 +154,8 @@ public:
|
|||
|
||||
SBBreakpoint GetBreakpointAtIndex(size_t idx);
|
||||
|
||||
SBBreakpoint FindBreakpointByID(lldb::break_id_t);
|
||||
|
||||
void Append(const SBBreakpoint &sb_file);
|
||||
|
||||
bool AppendIfUnique(const SBBreakpoint &sb_file);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../../make
|
||||
|
||||
C_SOURCES := main.c
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,147 @@
|
|||
"""
|
||||
Test breakpoint ignore count features.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class BreakpointSerialization(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@add_test_categories(['pyapi'])
|
||||
def test_resolvers(self):
|
||||
"""Use Python APIs to test that we serialize resolvers."""
|
||||
self.build()
|
||||
self.setup_targets_and_cleanup()
|
||||
self.do_check_resolvers()
|
||||
|
||||
def not_test_filters(self):
|
||||
"""Use Python APIs to test that we serialize search filters correctly."""
|
||||
self.build()
|
||||
self.setup_targets_and_cleanup()
|
||||
self.check_filters()
|
||||
|
||||
def not_test_options(self):
|
||||
"""Use Python APIs to test that we serialize breakpoint options correctly."""
|
||||
self.build()
|
||||
self.setup_targets_and_cleanup()
|
||||
self.check_filters()
|
||||
|
||||
def not_test_complex(self):
|
||||
"""Use Python APIs to test that we serialize complex breakpoints correctly."""
|
||||
self.build()
|
||||
self.setup_targets_and_cleanup()
|
||||
self.check_filters()
|
||||
|
||||
def setup_targets_and_cleanup(self):
|
||||
def cleanup ():
|
||||
#self.RemoveTempFile(self.bkpts_file_path)
|
||||
|
||||
if self.orig_target.IsValid():
|
||||
self.dbg.DeleteTarget(self.orig_target)
|
||||
self.dbg.DeleteTarget(self.copy_target)
|
||||
|
||||
self.addTearDownHook(cleanup)
|
||||
#self.RemoveTempFile(self.bkpts_file_path)
|
||||
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
|
||||
# Create a targets we are making breakpoint in and copying to:
|
||||
self.orig_target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(self.orig_target, VALID_TARGET)
|
||||
|
||||
self.copy_target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(self.copy_target, VALID_TARGET)
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
|
||||
self.bkpts_file_path = os.path.join(os.getcwd(), "breakpoints.json")
|
||||
self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path)
|
||||
|
||||
def do_check_resolvers(self):
|
||||
"""Use Python APIs to check serialization of breakpoint resolvers"""
|
||||
|
||||
empty_module_list = lldb.SBFileSpecList()
|
||||
empty_cu_list = lldb.SBFileSpecList()
|
||||
blubby_file_spec = lldb.SBFileSpec(os.path.join(os.getcwd(), "blubby.c"))
|
||||
|
||||
# It isn't actually important for these purposes that these breakpoint
|
||||
# actually have locations.
|
||||
source_bps = lldb.SBBreakpointList(self.orig_target)
|
||||
source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666))
|
||||
source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list))
|
||||
source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list))
|
||||
source_bps.Append(self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec))
|
||||
|
||||
error = lldb.SBError()
|
||||
error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec)
|
||||
self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString()))
|
||||
|
||||
copy_bps = lldb.SBBreakpointList(self.copy_target)
|
||||
error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps)
|
||||
self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString()))
|
||||
|
||||
num_source_bps = source_bps.GetSize()
|
||||
num_copy_bps = copy_bps.GetSize()
|
||||
self.assertTrue(num_source_bps == num_copy_bps, "Didn't get same number of input and output breakpoints - orig: %d copy: %d"%(num_source_bps, num_copy_bps))
|
||||
|
||||
for i in range(0, num_source_bps):
|
||||
source_bp = source_bps.GetBreakpointAtIndex(i)
|
||||
source_desc = lldb.SBStream()
|
||||
source_bp.GetDescription(source_desc, False)
|
||||
source_text = source_desc.GetData()
|
||||
|
||||
# I am assuming here that the breakpoints will get written out in breakpoint ID order, and
|
||||
# read back in ditto. That is true right now, and I can't see any reason to do it differently
|
||||
# but if we do we can go to writing the breakpoints one by one, or sniffing the descriptions to
|
||||
# see which one is which.
|
||||
copy_id = source_bp.GetID()
|
||||
copy_bp = copy_bps.FindBreakpointByID(copy_id)
|
||||
self.assertTrue(copy_bp.IsValid(), "Could not find copy breakpoint %d."%(copy_id))
|
||||
|
||||
copy_desc = lldb.SBStream()
|
||||
copy_bp.GetDescription(copy_desc, False)
|
||||
copy_text = copy_desc.GetData()
|
||||
|
||||
# These two should be identical.
|
||||
print ("Source test for %d is %s."%(i, source_text))
|
||||
self.assertTrue (source_text == copy_text, "Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"%(source_text, copy_text))
|
||||
|
||||
def check_filters(self):
|
||||
"""Use Python APIs to check serialization of breakpoint filters."""
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
|
||||
# Create a target by the debugger.
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
def check_options(self):
|
||||
"""Use Python APIs to check serialization of breakpoint options."""
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
|
||||
# Create a target by the debugger.
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
def check_resolvers(self):
|
||||
"""Use Python APIs to check serialization of breakpoint resolvers."""
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
|
||||
# Create a target by the debugger.
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
//===-- main.c --------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include <stdio.h>
|
||||
|
||||
// This simple program is to demonstrate the capability of the lldb command
|
||||
// "breakpoint modify -i <count> breakpt-id" to set the number of times a
|
||||
// breakpoint is skipped before stopping. Ignore count can also be set upon
|
||||
// breakpoint creation by 'breakpoint set ... -i <count>'.
|
||||
|
||||
int a(int);
|
||||
int b(int);
|
||||
int c(int);
|
||||
|
||||
int a(int val)
|
||||
{
|
||||
if (val <= 1)
|
||||
return b(val);
|
||||
else if (val >= 3)
|
||||
return c(val); // a(3) -> c(3) Find the call site of c(3).
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int b(int val)
|
||||
{
|
||||
return c(val);
|
||||
}
|
||||
|
||||
int c(int val)
|
||||
{
|
||||
return val + 3; // Find the line number of function "c" here.
|
||||
}
|
||||
|
||||
int main (int argc, char const *argv[])
|
||||
{
|
||||
int A1 = a(1); // a(1) -> b(1) -> c(1)
|
||||
printf("a(1) returns %d\n", A1);
|
||||
|
||||
int B2 = b(2); // b(2) -> c(2) Find the call site of b(2).
|
||||
printf("b(2) returns %d\n", B2);
|
||||
|
||||
int A3 = a(3); // a(3) -> c(3) Find the call site of a(3).
|
||||
printf("a(3) returns %d\n", A3);
|
||||
|
||||
int C1 = c(5); // Find the call site of c in main.
|
||||
printf ("c(5) returns %d\n", C1);
|
||||
return 0;
|
||||
}
|
|
@ -221,6 +221,9 @@ public:
|
|||
bool
|
||||
GetDescription (lldb::SBStream &description);
|
||||
|
||||
bool
|
||||
GetDescription(lldb::SBStream &description, bool include_locations);
|
||||
|
||||
bool
|
||||
operator == (const lldb::SBBreakpoint& rhs);
|
||||
|
||||
|
@ -276,6 +279,9 @@ public:
|
|||
|
||||
SBBreakpoint
|
||||
GetBreakpointAtIndex(size_t idx);
|
||||
|
||||
SBBreakpoint
|
||||
FindBreakpointByID(lldb::break_id_t);
|
||||
|
||||
void Append(const SBBreakpoint &sb_bkpt);
|
||||
|
||||
|
|
|
@ -449,14 +449,20 @@ size_t SBBreakpoint::GetNumLocations() const {
|
|||
}
|
||||
|
||||
bool SBBreakpoint::GetDescription(SBStream &s) {
|
||||
return GetDescription(s, true);
|
||||
}
|
||||
|
||||
bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) {
|
||||
if (m_opaque_sp) {
|
||||
std::lock_guard<std::recursive_mutex> guard(
|
||||
m_opaque_sp->GetTarget().GetAPIMutex());
|
||||
s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
|
||||
m_opaque_sp->GetResolverDescription(s.get());
|
||||
m_opaque_sp->GetFilterDescription(s.get());
|
||||
const size_t num_locations = m_opaque_sp->GetNumLocations();
|
||||
s.Printf(", locations = %" PRIu64, (uint64_t)num_locations);
|
||||
if (include_locations) {
|
||||
const size_t num_locations = m_opaque_sp->GetNumLocations();
|
||||
s.Printf(", locations = %" PRIu64, (uint64_t)num_locations);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
s.Printf("No value");
|
||||
|
@ -702,6 +708,18 @@ public:
|
|||
return target_sp->GetBreakpointList().FindBreakpointByID(bp_id);
|
||||
}
|
||||
|
||||
BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) {
|
||||
TargetSP target_sp = m_target_wp.lock();
|
||||
if (!target_sp)
|
||||
return BreakpointSP();
|
||||
|
||||
for (lldb::break_id_t &break_id : m_break_ids) {
|
||||
if (break_id == desired_id)
|
||||
return target_sp->GetBreakpointList().FindBreakpointByID(break_id);
|
||||
}
|
||||
return BreakpointSP();
|
||||
}
|
||||
|
||||
bool Append(Breakpoint &bkpt) {
|
||||
TargetSP target_sp = m_target_wp.lock();
|
||||
if (!target_sp)
|
||||
|
@ -772,6 +790,13 @@ SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) {
|
|||
return SBBreakpoint(bkpt_sp);
|
||||
}
|
||||
|
||||
SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) {
|
||||
if (!m_opaque_sp)
|
||||
return SBBreakpoint();
|
||||
BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id);
|
||||
return SBBreakpoint(bkpt_sp);
|
||||
}
|
||||
|
||||
void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) {
|
||||
if (!sb_bkpt.IsValid())
|
||||
return;
|
||||
|
|
|
@ -30,7 +30,7 @@ using namespace lldb_private;
|
|||
BreakpointResolverFileRegex::BreakpointResolverFileRegex(
|
||||
Breakpoint *bkpt, RegularExpression ®ex,
|
||||
const std::unordered_set<std::string> &func_names, bool exact_match)
|
||||
: BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver),
|
||||
: BreakpointResolver(bkpt, BreakpointResolver::FileRegexResolver),
|
||||
m_regex(regex), m_exact_match(exact_match), m_function_names(func_names) {
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ const char *SearchFilter::FilterTyToName(enum FilterTy type) {
|
|||
}
|
||||
|
||||
SearchFilter::FilterTy SearchFilter::NameToFilterTy(const char *name) {
|
||||
for (size_t i = 0; i < LastKnownFilterType; i++) {
|
||||
for (size_t i = 0; i <= LastKnownFilterType; i++) {
|
||||
if (strcmp(name, g_ty_to_name[i]) == 0)
|
||||
return (FilterTy)i;
|
||||
}
|
||||
|
@ -163,8 +163,13 @@ SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) {
|
|||
void SearchFilter::SerializeFileSpecList(
|
||||
StructuredData::DictionarySP &options_dict_sp, OptionNames name,
|
||||
FileSpecList &file_list) {
|
||||
StructuredData::ArraySP module_array_sp(new StructuredData::Array());
|
||||
size_t num_modules = file_list.GetSize();
|
||||
|
||||
// Don't serialize empty lists.
|
||||
if (num_modules == 0)
|
||||
return;
|
||||
|
||||
StructuredData::ArraySP module_array_sp(new StructuredData::Array());
|
||||
for (size_t i = 0; i < num_modules; i++) {
|
||||
module_array_sp->AddItem(StructuredData::StringSP(
|
||||
new StructuredData::String(file_list.GetFileSpecAtIndex(i).GetPath())));
|
||||
|
@ -630,22 +635,19 @@ SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
|
|||
StructuredData::Array *modules_array;
|
||||
bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
|
||||
modules_array);
|
||||
if (!success) {
|
||||
error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t num_modules = modules_array->GetSize();
|
||||
FileSpecList modules;
|
||||
for (size_t i = 0; i < num_modules; i++) {
|
||||
std::string module;
|
||||
success = modules_array->GetItemAtIndexAsString(i, module);
|
||||
if (!success) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"SFBM::CFSD: filter module item %zu not a string.", i);
|
||||
return nullptr;
|
||||
if (success) {
|
||||
size_t num_modules = modules_array->GetSize();
|
||||
for (size_t i = 0; i < num_modules; i++) {
|
||||
std::string module;
|
||||
success = modules_array->GetItemAtIndexAsString(i, module);
|
||||
if (!success) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"SFBM::CFSD: filter module item %zu not a string.", i);
|
||||
return nullptr;
|
||||
}
|
||||
modules.Append(FileSpec(module.c_str(), false));
|
||||
}
|
||||
modules.Append(FileSpec(module.c_str(), false));
|
||||
}
|
||||
|
||||
return SearchFilterSP(
|
||||
|
@ -694,29 +696,26 @@ SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;
|
|||
|
||||
lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
|
||||
Target &target, const StructuredData::Dictionary &data_dict, Error &error) {
|
||||
StructuredData::Array *modules_array;
|
||||
StructuredData::Array *modules_array = nullptr;
|
||||
SearchFilterSP result_sp;
|
||||
bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
|
||||
modules_array);
|
||||
if (!success) {
|
||||
error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
|
||||
return result_sp;
|
||||
}
|
||||
|
||||
size_t num_modules = modules_array->GetSize();
|
||||
FileSpecList modules;
|
||||
for (size_t i = 0; i < num_modules; i++) {
|
||||
std::string module;
|
||||
success = modules_array->GetItemAtIndexAsString(i, module);
|
||||
if (!success) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"SFBM::CFSD: filter module item %zu not a string.", i);
|
||||
return result_sp;
|
||||
if (success) {
|
||||
size_t num_modules = modules_array->GetSize();
|
||||
for (size_t i = 0; i < num_modules; i++) {
|
||||
std::string module;
|
||||
success = modules_array->GetItemAtIndexAsString(i, module);
|
||||
if (!success) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"SFBM::CFSD: filter module item %zu not a string.", i);
|
||||
return result_sp;
|
||||
}
|
||||
modules.Append(FileSpec(module.c_str(), false));
|
||||
}
|
||||
modules.Append(FileSpec(module.c_str(), false));
|
||||
}
|
||||
|
||||
StructuredData::Array *cus_array;
|
||||
StructuredData::Array *cus_array = nullptr;
|
||||
success =
|
||||
data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array);
|
||||
if (!success) {
|
||||
|
@ -728,7 +727,7 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
|
|||
FileSpecList cus;
|
||||
for (size_t i = 0; i < num_cus; i++) {
|
||||
std::string cu;
|
||||
success = modules_array->GetItemAtIndexAsString(i, cu);
|
||||
success = cus_array->GetItemAtIndexAsString(i, cu);
|
||||
if (!success) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"SFBM::CFSD: filter cu item %zu not a string.", i);
|
||||
|
|
Loading…
Reference in New Issue