[Lldb-commits] [PATCH] D48596: [SymbolFile] Implement GetCompleteObjCClass for .debug_names
labath added a comment. How are you planning on testing this? Most of the DWARFIndex functionality is tested in terms of lldb-test, but I think this function is not reachable from there. Maybe you could write a specific dotest-test which targets this? https://reviews.llvm.org/D48596 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48596: [SymbolFile] Implement GetCompleteObjCClass for .debug_names
JDevlieghere updated this revision to Diff 153027. JDevlieghere added a comment. - Add test case for debug_names variant. https://reviews.llvm.org/D48596 Files: packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h Index: source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h === --- source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -31,7 +31,7 @@ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override; void GetObjCMethods(ConstString class_name, DIEArray &offsets) override {} void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, -DIEArray &offsets) override {} +DIEArray &offsets) override; void GetTypes(ConstString name, DIEArray &offsets) override; void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override; void GetNamespaces(ConstString name, DIEArray &offsets) override; Index: source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp === --- source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -146,6 +146,49 @@ } } +void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name, +bool must_be_implementation, +DIEArray &offsets) { + m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets); + + // Keep a list of incomplete types as fallback for when we don't find the + // complete type. + DIEArray incomplete_types; + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(class_name.GetStringRef())) { +if (entry.tag() != DW_TAG_structure_type && +entry.tag() != DW_TAG_class_type) + continue; + +DIERef ref = ToDIERef(entry); +if (!ref) + continue; + +DWARFUnit *cu = m_debug_info.GetCompileUnit(ref.cu_offset); +if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) { + incomplete_types.push_back(ref); + continue; +} + +// FIXME: We should return DWARFDIEs so we don't have to resolve it twice. +DWARFDIE die = m_debug_info.GetDIE(ref); +if (!die) + continue; + +if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) { + // If we find the complete version we're done. + offsets.push_back(ref); + return; +} else { + incomplete_types.push_back(ref); +} + } + + offsets.insert(offsets.end(), incomplete_types.begin(), + incomplete_types.end()); +} + void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { m_fallback.GetTypes(name, offsets); Index: packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py === --- packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py +++ packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py @@ -23,9 +23,8 @@ self.line = line_number(self.source, '// Set breakpoint 0 here.') self.shlib_names = ["Container"] -@skipUnlessDarwin -def test_expr(self): -self.build() +def do_test(self, dictionary=None): +self.build(dictionary=dictionary) # Create a target by the debugger. target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) @@ -57,3 +56,17 @@ # This should display correctly. self.expect("expression [j getMember]", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 0x"]) + +@skipUnlessDarwin +def test_expr(self): +self.do_test() + +@no_debug_info_test +@skipUnlessDarwin +@skipIf(compiler=no_match("clang")) +@skipIf(compiler_version=["<", "7.0"]) +def test_debug_names(self): +"""Test that we are able to find complete types when using DWARF v5 +accelerator tables""" +self.do_test( +dict(CFLAGS_EXTRAS="-dwarf-version=5 -mllvm -accel-tables=Dwarf")) ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48596: [SymbolFile] Implement GetCompleteObjCClass for .debug_names
labath accepted this revision. labath added a comment. looks good to me https://reviews.llvm.org/D48596 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48633: UUID: Add support for arbitrary-sized module IDs
labath created this revision. labath added reviewers: clayborg, lemo, sas, davide. Herald added subscribers: arichardson, emaste. Herald added a reviewer: espindola. The data structure is optimized for the case where the UUID size is <= 20 bytes (standard length emitted by the GNU linkers), but larger sizes are also possible. I've modified the string conversion function to support the new sizes as well. For standard UUIDs it maintains the traditional formatting (4-2-2-2-6). If a UUID is shorter, we just cut this sequence short, and for longer UUIDs it will just repeat the last 6-byte block as long as necessary. I've also modified ObjectFileELF to take advantage of the new UUIDs and avoid manually padding the UUID to 16 bytes. While there, I also made sure the computed UUID does not depend on host endianness. https://reviews.llvm.org/D48633 Files: include/lldb/Utility/UUID.h source/Interpreter/OptionValueUUID.cpp source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp source/Utility/UUID.cpp unittests/Utility/UUIDTest.cpp Index: unittests/Utility/UUIDTest.cpp === --- unittests/Utility/UUIDTest.cpp +++ unittests/Utility/UUIDTest.cpp @@ -71,3 +71,15 @@ 32u, u.SetFromStringRef("404142434445464748494a4b4c4d4e4f-50515253", 16)); EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNO", 16), u); } + +TEST(UUIDTest, StringConverion) { + EXPECT_EQ("40414243", UUID::fromData("@ABC", 4).GetAsString()); + EXPECT_EQ("40414243-4445-4647", +UUID::fromData("@ABCDEFG", 8).GetAsString()); + EXPECT_EQ("40414243-4445-4647-4849-4A4B", +UUID::fromData("@ABCDEFGHIJK", 12).GetAsString()); + EXPECT_EQ("40414243-4445-4647-4849-4A4B4C4D4E4F", +UUID::fromData("@ABCDEFGHIJKLMNO", 16).GetAsString()); + EXPECT_EQ("40414243-4445-4647-4849-4A4B4C4D4E4F-50515253", +UUID::fromData("@ABCDEFGHIJKLMNOPQRS", 20).GetAsString()); +} Index: source/Utility/UUID.cpp === --- source/Utility/UUID.cpp +++ source/Utility/UUID.cpp @@ -13,43 +13,44 @@ // Project includes #include "lldb/Utility/Stream.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Format.h" // C Includes #include #include #include using namespace lldb_private; -UUID::UUID(llvm::ArrayRef bytes) { - if (bytes.size() != 20 && bytes.size() != 16) -bytes = {}; - - m_num_uuid_bytes = bytes.size(); - std::memcpy(m_uuid, bytes.data(), bytes.size()); +// Whether to put a separator after count uuid bytes. +// For the first 16 bytes we follow the traditional UUID format. After that, we +// simply put a dash after every 6 bytes. +static inline bool separate(size_t count) { + if (count >= 10) +return (count - 10) % 6 == 0; + + switch(count) { + case 4: + case 6: + case 8: +return true; + default: +return false; + } } -std::string UUID::GetAsString(const char *separator) const { +std::string UUID::GetAsString(llvm::StringRef separator) const { std::string result; - char buf[256]; - if (!separator) -separator = "-"; - const uint8_t *u = GetBytes().data(); - if (sizeof(buf) > - (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2." - "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%" - "2.2X%2.2X%2.2X", - u[0], u[1], u[2], u[3], separator, u[4], u[5], separator, - u[6], u[7], separator, u[8], u[9], separator, u[10], - u[11], u[12], u[13], u[14], u[15])) { -result.append(buf); -if (m_num_uuid_bytes == 20) { - if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf), - "%s%2.2X%2.2X%2.2X%2.2X", separator, - u[16], u[17], u[18], u[19])) -result.append(buf); -} + llvm::raw_string_ostream os(result); + + for(auto B: llvm::enumerate(GetBytes())) { +if (separate(B.index())) + os << separator; + +os << llvm::format_hex_no_prefix(B.value(), 2, true); } + os.flush(); + return result; } @@ -64,25 +65,24 @@ return ch - '0'; } -llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p, -ValueType &uuid_bytes, -uint32_t &bytes_decoded, -uint32_t num_uuid_bytes) { - ::memset(uuid_bytes, 0, sizeof(uuid_bytes)); - size_t uuid_byte_idx = 0; +llvm::StringRef +UUID::DecodeUUIDBytesFromString(llvm::StringRef p, +llvm::SmallVectorImpl &uuid_bytes, +uint32_t num_uuid_bytes) { + uuid_bytes.clear(); while (!p.empty()) { if (isxdigit(p[0]) && isxdigit(p[1])) { int hi_nibble = xdigit_to_int(p[0]); int lo_nibble = xdigit_to_int(p[1]); // Translate the t
[Lldb-commits] [PATCH] D48641: Skip core file tests on build configurations lacking necessary components
labath created this revision. labath added reviewers: clayborg, jingham. To successfully open a core file, we need to have LLVM built with support for the relevant target. Right now, if one does not have the appropriate targets configured, the tests will fail. This patch uses the GetBuildConfiguration SB API to inform the test (and anyone else who cares) about the list of supported LLVM targets. The test then uses this information to approriately skip the tests. https://reviews.llvm.org/D48641 Files: packages/Python/lldbsuite/test/decorators.py packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py source/API/SBDebugger.cpp Index: source/API/SBDebugger.cpp === --- source/API/SBDebugger.cpp +++ source/API/SBDebugger.cpp @@ -500,11 +500,23 @@ dict.AddItem(name, std::move(entry_up)); } +static void AddLLVMTargets(StructuredData::Dictionary &dict) { + auto array_up = llvm::make_unique(); +#define LLVM_TARGET(target)\ + array_up->AddItem(llvm::make_unique(#target)); +#include "llvm/Config/Targets.def" + auto entry_up = llvm::make_unique(); + entry_up->AddItem("value", std::move(array_up)); + entry_up->AddStringItem("description", "A list of configured LLVM targets."); + dict.AddItem("targets", std::move(entry_up)); +} + SBStructuredData SBDebugger::GetBuildConfiguration() { auto config_up = llvm::make_unique(); AddBoolConfigEntry( *config_up, "xml", XMLDocument::XMLEnabled(), "A boolean value that indicates if XML support is enabled in LLDB"); + AddLLVMTargets(*config_up); SBStructuredData data; data.m_impl_up->SetObjectSP(std::move(config_up)); Index: packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py === --- packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py +++ packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -42,51 +42,59 @@ @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) @skipIf(triple='^mips') +@skipIfLLVMTargetMissing("X86") def test_i386(self): """Test that lldb can read the process information from an i386 linux core file.""" self.do_test("linux-i386", self._i386_pid, self._i386_regions, "a.out") @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) +@skipIfLLVMTargetMissing("Mips") def test_mips_o32(self): """Test that lldb can read the process information from an MIPS O32 linux core file.""" self.do_test("linux-mipsel-gnuabio32", self._mips_o32_pid, self._mips_regions, "linux-mipsel-gn") @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) +@skipIfLLVMTargetMissing("Mips") def test_mips_n32(self): """Test that lldb can read the process information from an MIPS N32 linux core file """ self.do_test("linux-mips64el-gnuabin32", self._mips64_n32_pid, self._mips_regions, "linux-mips64el-") @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) +@skipIfLLVMTargetMissing("Mips") def test_mips_n64(self): """Test that lldb can read the process information from an MIPS N64 linux core file """ self.do_test("linux-mips64el-gnuabi64", self._mips64_n64_pid, self._mips_regions, "linux-mips64el-") @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) @skipIf(triple='^mips') +@skipIfLLVMTargetMissing("PowerPC") def test_ppc64le(self): """Test that lldb can read the process information from an ppc64le linux core file.""" self.do_test("linux-ppc64le", self._ppc64le_pid, self._ppc64le_regions, "linux-ppc64le.ou") @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) @skipIf(triple='^mips') +@skipIfLLVMTargetMissing("X86") def test_x86_64(self): """Test that lldb can read the process information from an x86_64 linux core file.""" self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions, "a.out") @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) @skipIf(triple='^mips') +@skipIfLLVMTargetMissing("SystemZ") def test_s390x(self): """Test that lldb can read the process information from an s390x linux core file.""" self.do_test("linux-s390x", self._s390x_pid, self._s390x_regions, "a.out") @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"]) @skipIf(triple='^mips') +@skipIfLLVMTargetMissing("X86") def test_same_pid_running(self): """Test that we read the information from the core correctly even if we have a running
[Lldb-commits] [PATCH] D48646: Add a test for reading lld-generated build-ids
labath created this revision. labath added reviewers: aprantl, zturner. This test makes sure we are able to read the shorter build-ids which are generated by lld. To make this work, I've extended lldb-test to print the UUID of the loaded object file. I've renamed the lldb-test subcommand from "module-sections" to "object-file" to reflect the fact it prints more than just the sections. I've also added the module Architecture to the output, so we could avoid printing the entire symbol file information just to get the ArchSpec details in the lc_version_min test (which was also the only test in it's folder not using the module-sections command). https://reviews.llvm.org/D48646 Files: lit/Modules/build-id-case.yaml lit/Modules/compressed-sections.yaml lit/Modules/elf-duplicate-section.yaml lit/Modules/elf-section-types.yaml lit/Modules/lc_version_min.yaml lit/Modules/short-build-id.yaml tools/lldb-test/lldb-test.cpp Index: tools/lldb-test/lldb-test.cpp === --- tools/lldb-test/lldb-test.cpp +++ tools/lldb-test/lldb-test.cpp @@ -51,14 +51,15 @@ namespace opts { static cl::SubCommand BreakpointSubcommand("breakpoints", "Test breakpoint resolution"); -cl::SubCommand ModuleSubcommand("module-sections", -"Display LLDB Module Information"); +cl::SubCommand ObjectFileSubcommand("object-file", +"Display LLDB object file information"); cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file"); cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap"); cl::opt Log("log", cl::desc("Path to a log file"), cl::init(""), cl::sub(BreakpointSubcommand), - cl::sub(ModuleSubcommand), cl::sub(SymbolsSubcommand), + cl::sub(ObjectFileSubcommand), + cl::sub(SymbolsSubcommand), cl::sub(IRMemoryMapSubcommand)); /// Create a target using the file pointed to by \p Filename, or abort. @@ -85,13 +86,14 @@ static int evaluateBreakpoints(Debugger &Dbg); } // namespace breakpoint -namespace module { +namespace object { cl::opt SectionContents("contents", cl::desc("Dump each section's contents"), - cl::sub(ModuleSubcommand)); + cl::sub(ObjectFileSubcommand)); cl::list InputFilenames(cl::Positional, cl::desc(""), - cl::OneOrMore, cl::sub(ModuleSubcommand)); -} // namespace module + cl::OneOrMore, + cl::sub(ObjectFileSubcommand)); +} // namespace object namespace symbols { static cl::list InputFilenames(cl::Positional, @@ -582,11 +584,11 @@ return HadErrors; } -static int dumpModules(Debugger &Dbg) { +static int dumpObjectFiles(Debugger &Dbg) { LinePrinter Printer(4, llvm::outs()); int HadErrors = 0; - for (const auto &File : opts::module::InputFilenames) { + for (const auto &File : opts::object::InputFilenames) { ModuleSpec Spec{FileSpec(File, false)}; auto ModulePtr = std::make_shared(Spec); @@ -600,6 +602,10 @@ continue; } +Printer.formatLine("Architecture: {0}", + ModulePtr->GetArchitecture().GetTriple().getTriple()); +Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString()); + size_t Count = Sections->GetNumSections(0); Printer.formatLine("Showing {0} sections", Count); for (size_t I = 0; I < Count; ++I) { @@ -612,7 +618,7 @@ Printer.formatLine("VM size: {0}", S->GetByteSize()); Printer.formatLine("File size: {0}", S->GetFileSize()); - if (opts::module::SectionContents) { + if (opts::object::SectionContents) { DataExtractor Data; S->GetSectionData(Data); ArrayRef Bytes = {Data.GetDataStart(), Data.GetDataEnd()}; @@ -807,8 +813,8 @@ if (opts::BreakpointSubcommand) return opts::breakpoint::evaluateBreakpoints(*Dbg); - if (opts::ModuleSubcommand) -return dumpModules(*Dbg); + if (opts::ObjectFileSubcommand) +return dumpObjectFiles(*Dbg); if (opts::SymbolsSubcommand) return opts::symbols::dumpSymbols(*Dbg); if (opts::IRMemoryMapSubcommand) Index: lit/Modules/short-build-id.yaml === --- /dev/null +++ lit/Modules/short-build-id.yaml @@ -0,0 +1,26 @@ +# RUN: yaml2obj %s >%t +# RUN: lldb-test object-file %t | FileCheck %s + +# CHECK: UUID: 333059A4-3CC3-D5F9 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data:ELFDATA2LSB + Type:ET_EXEC + Machine: EM_X86_64 + Entry: 0x00201000 +Sections: + - Name:.note.gnu.build-id +Type:SHT_NOTE +Flags
Re: [Lldb-commits] [lldb] r334978 - Fixed file completion for paths that start with '~'.
Ping. On Tue, 19 Jun 2018 at 16:04, Pavel Labath wrote: > > A test? > > It looks like it should be possible to test this in a similar way to > other CommandCompletion tests > (unittests/Interpreter/TestCompletion.cpp). > On Mon, 18 Jun 2018 at 21:16, Raphael Isemann via lldb-commits > wrote: > > > > Author: teemperor > > Date: Mon Jun 18 13:11:38 2018 > > New Revision: 334978 > > > > URL: http://llvm.org/viewvc/llvm-project?rev=334978&view=rev > > Log: > > Fixed file completion for paths that start with '~'. > > > > We didn't add the remaining path behind the '~' to the completion string, > > causing it to just complete directories inside the user home directory. This > > patch just adds the directory of the remaining path if there is one. > > > > Fixes rdar://problem/40147002 > > > > Modified: > > lldb/trunk/source/Commands/CommandCompletions.cpp > > > > Modified: lldb/trunk/source/Commands/CommandCompletions.cpp > > URL: > > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandCompletions.cpp?rev=334978&r1=334977&r2=334978&view=diff > > == > > --- lldb/trunk/source/Commands/CommandCompletions.cpp (original) > > +++ lldb/trunk/source/Commands/CommandCompletions.cpp Mon Jun 18 13:11:38 > > 2018 > > @@ -164,6 +164,12 @@ static int DiskFilesOrDirectories(const > > // search in the fully resolved directory, but CompletionBuffer keeps > > the > > // unmodified form that the user typed. > > Storage = Resolved; > > +llvm::StringRef RemainderDir = path::parent_path(Remainder.str()); > > +if (!RemainderDir.empty()) { > > + // Append the remaining path to the resolved directory. > > + Storage.append(path::get_separator()); > > + Storage.append(RemainderDir); > > +} > > SearchDir = Storage; > >} else { > > SearchDir = path::parent_path(CompletionBuffer); > > > > > > ___ > > lldb-commits mailing list > > lldb-commits@lists.llvm.org > > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48596: [SymbolFile] Implement GetCompleteObjCClass for .debug_names
clayborg accepted this revision. clayborg added a comment. This revision is now accepted and ready to land. Looks good. https://reviews.llvm.org/D48596 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48633: UUID: Add support for arbitrary-sized module IDs
clayborg added inline comments. Comment at: source/Interpreter/OptionValueUUID.cpp:82 + llvm::SmallVector uuid_bytes; + UUID::DecodeUUIDBytesFromString(s, uuid_bytes); for (size_t i = 0; i < num_modules; ++i) { Probably should have a return value that indicates success or not. What if the user enters "aab". The string must have an event number of hex digits. https://reviews.llvm.org/D48633 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D44603: [lldb] Introduce StackFrameRecognizer
kubamracek added a comment. friendly ping :) https://reviews.llvm.org/D44603 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48646: Add a test for reading lld-generated build-ids
aprantl added a comment. SGTM https://reviews.llvm.org/D48646 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48658: Fix and simplify lldb.command decorator
kastiglione created this revision. kastiglione added reviewers: clayborg, granata.enrico. This change fixes one issue with `lldb.command`, and also reduces the implementation. The fix: a command function's docstring was not shown when running `help `. This is because the docstring attached the source function is not propagated to the decorated function (`f.__call__`). By returning the original function, the docstring will be properly displayed by `help`. Additionally, the implementation was updated to: - Remove inner class - Remove use of `inspect` module - Remove `*args` and `**kwargs` https://reviews.llvm.org/D48658 Files: scripts/Python/python-extensions.swig Index: scripts/Python/python-extensions.swig === --- scripts/Python/python-extensions.swig +++ scripts/Python/python-extensions.swig @@ -839,29 +839,18 @@ %pythoncode %{ -def command(*args, **kwargs): +def command(command_name, doc=None): import lldb -import inspect """A decorator function that registers an LLDB command line command that is bound to the function it is attached to.""" -class obj(object): -"""The object that tracks adding the command to LLDB one time and handles -calling the function on subsequent calls.""" -def __init__(self, function, command_name, doc = None): -if doc: -function.__doc__ = doc -command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) -lldb.debugger.HandleCommand(command) -self.function = function -def __call__(self, debugger, command, exe_ctx, result, dict): -if len(inspect.getargspec(self.function).args) == 5: -self.function(debugger, command, exe_ctx, result, dict) -else: -self.function(debugger, command, result, dict) def callable(function): """Creates a callable object that gets used.""" -f = obj(function, *args, **kwargs) -return f.__call__ +command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) +lldb.debugger.HandleCommand(command) +if doc: +function.__doc__ = doc +return function + return callable class declaration(object): Index: scripts/Python/python-extensions.swig === --- scripts/Python/python-extensions.swig +++ scripts/Python/python-extensions.swig @@ -839,29 +839,18 @@ %pythoncode %{ -def command(*args, **kwargs): +def command(command_name, doc=None): import lldb -import inspect """A decorator function that registers an LLDB command line command that is bound to the function it is attached to.""" -class obj(object): -"""The object that tracks adding the command to LLDB one time and handles -calling the function on subsequent calls.""" -def __init__(self, function, command_name, doc = None): -if doc: -function.__doc__ = doc -command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) -lldb.debugger.HandleCommand(command) -self.function = function -def __call__(self, debugger, command, exe_ctx, result, dict): -if len(inspect.getargspec(self.function).args) == 5: -self.function(debugger, command, exe_ctx, result, dict) -else: -self.function(debugger, command, result, dict) def callable(function): """Creates a callable object that gets used.""" -f = obj(function, *args, **kwargs) -return f.__call__ +command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) +lldb.debugger.HandleCommand(command) +if doc: +function.__doc__ = doc +return function + return callable class declaration(object): ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48658: Fix and simplify lldb.command decorator
kastiglione updated this revision to Diff 153114. kastiglione added a comment. Update a comment https://reviews.llvm.org/D48658 Files: scripts/Python/python-extensions.swig Index: scripts/Python/python-extensions.swig === --- scripts/Python/python-extensions.swig +++ scripts/Python/python-extensions.swig @@ -839,29 +839,18 @@ %pythoncode %{ -def command(*args, **kwargs): +def command(command_name, doc=None): import lldb -import inspect """A decorator function that registers an LLDB command line command that is bound to the function it is attached to.""" -class obj(object): -"""The object that tracks adding the command to LLDB one time and handles -calling the function on subsequent calls.""" -def __init__(self, function, command_name, doc = None): -if doc: -function.__doc__ = doc -command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) -lldb.debugger.HandleCommand(command) -self.function = function -def __call__(self, debugger, command, exe_ctx, result, dict): -if len(inspect.getargspec(self.function).args) == 5: -self.function(debugger, command, exe_ctx, result, dict) -else: -self.function(debugger, command, result, dict) def callable(function): -"""Creates a callable object that gets used.""" -f = obj(function, *args, **kwargs) -return f.__call__ +"""Registers an lldb command for the decorated function.""" +command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) +lldb.debugger.HandleCommand(command) +if doc: +function.__doc__ = doc +return function + return callable class declaration(object): Index: scripts/Python/python-extensions.swig === --- scripts/Python/python-extensions.swig +++ scripts/Python/python-extensions.swig @@ -839,29 +839,18 @@ %pythoncode %{ -def command(*args, **kwargs): +def command(command_name, doc=None): import lldb -import inspect """A decorator function that registers an LLDB command line command that is bound to the function it is attached to.""" -class obj(object): -"""The object that tracks adding the command to LLDB one time and handles -calling the function on subsequent calls.""" -def __init__(self, function, command_name, doc = None): -if doc: -function.__doc__ = doc -command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) -lldb.debugger.HandleCommand(command) -self.function = function -def __call__(self, debugger, command, exe_ctx, result, dict): -if len(inspect.getargspec(self.function).args) == 5: -self.function(debugger, command, exe_ctx, result, dict) -else: -self.function(debugger, command, result, dict) def callable(function): -"""Creates a callable object that gets used.""" -f = obj(function, *args, **kwargs) -return f.__call__ +"""Registers an lldb command for the decorated function.""" +command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name) +lldb.debugger.HandleCommand(command) +if doc: +function.__doc__ = doc +return function + return callable class declaration(object): ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48658: Fix and simplify lldb.command decorator
granata.enrico added a comment. Thanks for doing this work. I stopped working on lldb a couple years ago, so I removed myself as a reviewer. Greg will take good care of you I'm sure. https://reviews.llvm.org/D48658 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48658: Fix and simplify lldb.command decorator
kastiglione added a subscriber: granata.enrico. kastiglione added a comment. Thanks @granata.enrico, sorry for the disruption, I noticed previous comments after I had submitted this. https://reviews.llvm.org/D48658 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48659: Allow specifying an exit code for the 'quit' command
teemperor created this revision. teemperor added a reviewer: davide. This patch adds the possibility to specify an exit code when calling quit. We accept any int, even though it depends on the user what happens if the int is out of the range of what the operating system supports as exit codes. Fixes rdar://problem/38452312 https://reviews.llvm.org/D48659 Files: include/lldb/API/SBDebugger.h include/lldb/Core/Debugger.h lit/Quit/TestQuitExitCode-30.test lit/Quit/TestQuitExitCode0.test lit/Quit/TestQuitExitCode30.test lit/Quit/TestQuitExitCodeHex0.test lit/Quit/TestQuitExitCodeHexA.test lit/Quit/TestQuitExitCodeImplicit0.test lit/Quit/TestQuitExitCodeNonInt.test lit/Quit/TestQuitExitCodeTooManyArgs.test lit/Quit/expect_exit_code.py lit/Quit/lit.local.cfg source/API/SBDebugger.cpp source/Commands/CommandObjectQuit.cpp tools/driver/Driver.cpp tools/driver/Driver.h Index: tools/driver/Driver.h === --- tools/driver/Driver.h +++ tools/driver/Driver.h @@ -37,7 +37,10 @@ virtual ~Driver(); - void MainLoop(); + /// Runs the main loop. + /// + /// @return The exit code that the process should return. + int MainLoop(); lldb::SBError ParseArgs(int argc, const char *argv[], FILE *out_fh, bool &do_exit); Index: tools/driver/Driver.cpp === --- tools/driver/Driver.cpp +++ tools/driver/Driver.cpp @@ -962,7 +962,7 @@ return '"' + arg + '"'; } -void Driver::MainLoop() { +int Driver::MainLoop() { if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { g_old_stdin_termios_is_valid = true; atexit(reset_stdin_termios); @@ -1159,7 +1159,9 @@ reset_stdin_termios(); fclose(stdin); + int exit_code = m_debugger.GetExitCode(); SBDebugger::Destroy(m_debugger); + return exit_code; } void Driver::ResizeWindow(unsigned short col) { @@ -1237,22 +1239,24 @@ signal(SIGCONT, sigcont_handler); #endif + int exit_code = 0; // Create a scope for driver so that the driver object will destroy itself // before SBDebugger::Terminate() is called. { Driver driver; bool exiting = false; SBError error(driver.ParseArgs(argc, argv, stdout, exiting)); if (error.Fail()) { + exit_code = 1; const char *error_cstr = error.GetCString(); if (error_cstr) ::fprintf(stderr, "error: %s\n", error_cstr); } else if (!exiting) { - driver.MainLoop(); + exit_code = driver.MainLoop(); } } SBDebugger::Terminate(); - return 0; + return exit_code; } Index: source/Commands/CommandObjectQuit.cpp === --- source/Commands/CommandObjectQuit.cpp +++ source/Commands/CommandObjectQuit.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; @@ -26,7 +27,7 @@ CommandObjectQuit::CommandObjectQuit(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "quit", "Quit the LLDB debugger.", - "quit") {} + "quit [exit-code]") {} CommandObjectQuit::~CommandObjectQuit() {} @@ -77,6 +78,29 @@ return false; } } + + if (command.GetArgumentCount() > 1) { +result.AppendError("Too many arguments for 'quit'. Only an optional exit " + "code is allowed"); +result.SetStatus(eReturnStatusFailed); +return false; + } + + // We parse the exit code argument if there is one. + if (command.GetArgumentCount() == 1) { +llvm::StringRef arg = command.GetArgumentAtIndex(0); +int exit_code; +if (arg.getAsInteger(/*autodetect radix*/ 0, exit_code)) { + lldb_private::StreamString s; + std::string arg_str = arg.str(); + s.Printf("Couldn't parse '%s' as integer for exit code.", arg_str.data()); + result.AppendError(s.GetString()); + result.SetStatus(eReturnStatusFailed); + return false; +} +m_interpreter.GetDebugger().SetExitCode(exit_code); + } + const uint32_t event_type = CommandInterpreter::eBroadcastBitQuitCommandReceived; m_interpreter.BroadcastEvent(event_type); Index: source/API/SBDebugger.cpp === --- source/API/SBDebugger.cpp +++ source/API/SBDebugger.cpp @@ -1081,6 +1081,10 @@ return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID); } +int SBDebugger::GetExitCode() { + return (m_opaque_sp ? m_opaque_sp->GetExitCode() : 0); +} + SBError SBDebugger::SetCurrentPlatform(const char *platform_name_cstr) { SBError sb_error; if (m_opaque_sp) { Index: lit/Quit/lit.local.cfg === --- /dev/null
[Lldb-commits] [PATCH] D48659: Allow specifying an exit code for the 'quit' command
jingham requested changes to this revision. jingham added a comment. This revision now requires changes to proceed. This won't at all do what users expect in cases where the driver program doesn't cooperate. For instance, when run under Xcode, the lldb process can have many debuggers running concurrently, so the exit value of a single Debugger doesn't make much sense there. I think we should require the client to say that it will obey the exit value, and have the command error out if the client has not told us it plans to respect our exit values. https://reviews.llvm.org/D48659 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48463: Prevent dead locking when calling PrintAsync
teemperor updated this revision to Diff 153126. teemperor added a comment. - We now also handle the case where a guarded mutex is manually unlocked from a nested call. - Refactoring based on review comments. https://reviews.llvm.org/D48463 Files: include/lldb/Core/Debugger.h include/lldb/Host/Editline.h source/Core/Debugger.cpp source/Core/IOHandler.cpp source/Host/common/Editline.cpp unittests/Editline/EditlineTest.cpp Index: unittests/Editline/EditlineTest.cpp === --- unittests/Editline/EditlineTest.cpp +++ unittests/Editline/EditlineTest.cpp @@ -123,9 +123,9 @@ return; // Create an Editline instance. - _editline_sp.reset(new lldb_private::Editline("gtest editor", *_el_slave_file, -*_el_slave_file, -*_el_slave_file, false)); + _editline_sp.reset(new lldb_private::Editline( + "gtest editor", *_el_slave_file, *_el_slave_file, *_el_slave_file, false, + nullptr)); _editline_sp->SetPrompt("> "); // Hookup our input complete callback. Index: source/Host/common/Editline.cpp === --- source/Host/common/Editline.cpp +++ source/Host/common/Editline.cpp @@ -11,6 +11,7 @@ #include #include +#include "lldb/Core/Debugger.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Editline.h" #include "lldb/Host/Host.h" @@ -507,9 +508,15 @@ // indefinitely. This gives a chance for someone to interrupt us. After // Read returns, immediately lock the mutex again and check if we were // interrupted. +int read_count; m_output_mutex.unlock(); -int read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); +{ + // We also disable the message delaying while we have the mutex unlocked. + lldb_private::Debugger::DisableMessageDelayScope guard(m_debugger); + read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); +} m_output_mutex.lock(); + if (m_editor_status == EditorStatus::Interrupted) { while (read_count > 0 && status == lldb::eConnectionStatusSuccess) read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); @@ -1128,10 +1135,12 @@ } Editline::Editline(const char *editline_name, FILE *input_file, - FILE *output_file, FILE *error_file, bool color_prompts) + FILE *output_file, FILE *error_file, bool color_prompts, + Debugger *debugger) : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts), m_input_file(input_file), m_output_file(output_file), - m_error_file(error_file), m_input_connection(fileno(input_file), false) { + m_error_file(error_file), m_input_connection(fileno(input_file), false), + m_debugger(debugger) { // Get a shared history instance m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; m_history_sp = EditlineHistory::GetHistory(m_editor_name); @@ -1264,6 +1273,12 @@ m_input_lines = std::vector(); m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); + // While we own the output mutex, we delay all messages that are printed via + // PrintAsync until we release the mutex again. This prevents dead locks that + // are caused when someone calls PrintAsync (which also needs to aquire + // the output mutex). Note that Editline::GetCharacter unlocks the guarded + // mutex from a nested call and also temporarily disables the message delay. + Debugger::MessageDelayScope msg_guard(m_debugger); std::lock_guard guard(m_output_mutex); lldbassert(m_editor_status != EditorStatus::Editing); @@ -1309,6 +1324,9 @@ m_input_lines = std::vector(); m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); + // We delay all message printing until we release the output mutex. See + // Editline::GetLine for a more detailed explanation. + Debugger::MessageDelayScope msg_guard(m_debugger); std::lock_guard guard(m_output_mutex); // Begin the line editing loop DisplayInput(); Index: source/Core/IOHandler.cpp === --- source/Core/IOHandler.cpp +++ source/Core/IOHandler.cpp @@ -313,7 +313,7 @@ if (use_editline) { m_editline_ap.reset(new Editline(editline_name, GetInputFILE(), GetOutputFILE(), GetErrorFILE(), - m_color_prompts)); + m_color_prompts, nullptr)); m_editline_ap->SetIsInputCompleteCallback(IsInputCompleteCallback, this); m_editline_ap->SetAutoCompleteCallback(AutoCompleteCallback, this); // See if the delegate supports fixing indentation Index: source/Core/Debugger.cpp === -
[Lldb-commits] [PATCH] D48463: Prevent dead locking when calling PrintAsync
teemperor updated this revision to Diff 153129. teemperor edited the summary of this revision. teemperor added a comment. - Fixed that we only pass a nullptr as a debugger to the real editline object (which now fixes the deadlock in the code completion patch). https://reviews.llvm.org/D48463 Files: include/lldb/Core/Debugger.h include/lldb/Host/Editline.h source/Core/Debugger.cpp source/Core/IOHandler.cpp source/Host/common/Editline.cpp unittests/Editline/EditlineTest.cpp Index: unittests/Editline/EditlineTest.cpp === --- unittests/Editline/EditlineTest.cpp +++ unittests/Editline/EditlineTest.cpp @@ -123,9 +123,9 @@ return; // Create an Editline instance. - _editline_sp.reset(new lldb_private::Editline("gtest editor", *_el_slave_file, -*_el_slave_file, -*_el_slave_file, false)); + _editline_sp.reset(new lldb_private::Editline( + "gtest editor", *_el_slave_file, *_el_slave_file, *_el_slave_file, false, + nullptr)); _editline_sp->SetPrompt("> "); // Hookup our input complete callback. Index: source/Host/common/Editline.cpp === --- source/Host/common/Editline.cpp +++ source/Host/common/Editline.cpp @@ -11,6 +11,7 @@ #include #include +#include "lldb/Core/Debugger.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Editline.h" #include "lldb/Host/Host.h" @@ -507,9 +508,15 @@ // indefinitely. This gives a chance for someone to interrupt us. After // Read returns, immediately lock the mutex again and check if we were // interrupted. +int read_count; m_output_mutex.unlock(); -int read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); +{ + // We also disable the message delaying while we have the mutex unlocked. + lldb_private::Debugger::DisableMessageDelayScope guard(m_debugger); + read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); +} m_output_mutex.lock(); + if (m_editor_status == EditorStatus::Interrupted) { while (read_count > 0 && status == lldb::eConnectionStatusSuccess) read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); @@ -1128,10 +1135,12 @@ } Editline::Editline(const char *editline_name, FILE *input_file, - FILE *output_file, FILE *error_file, bool color_prompts) + FILE *output_file, FILE *error_file, bool color_prompts, + Debugger *debugger) : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts), m_input_file(input_file), m_output_file(output_file), - m_error_file(error_file), m_input_connection(fileno(input_file), false) { + m_error_file(error_file), m_input_connection(fileno(input_file), false), + m_debugger(debugger) { // Get a shared history instance m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name; m_history_sp = EditlineHistory::GetHistory(m_editor_name); @@ -1264,6 +1273,12 @@ m_input_lines = std::vector(); m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); + // While we own the output mutex, we delay all messages that are printed via + // PrintAsync until we release the mutex again. This prevents dead locks that + // are caused when someone calls PrintAsync (which also needs to aquire + // the output mutex). Note that Editline::GetCharacter unlocks the guarded + // mutex from a nested call and also temporarily disables the message delay. + Debugger::MessageDelayScope msg_guard(m_debugger); std::lock_guard guard(m_output_mutex); lldbassert(m_editor_status != EditorStatus::Editing); @@ -1309,6 +1324,9 @@ m_input_lines = std::vector(); m_input_lines.insert(m_input_lines.begin(), EditLineConstString("")); + // We delay all message printing until we release the output mutex. See + // Editline::GetLine for a more detailed explanation. + Debugger::MessageDelayScope msg_guard(m_debugger); std::lock_guard guard(m_output_mutex); // Begin the line editing loop DisplayInput(); Index: source/Core/IOHandler.cpp === --- source/Core/IOHandler.cpp +++ source/Core/IOHandler.cpp @@ -313,7 +313,7 @@ if (use_editline) { m_editline_ap.reset(new Editline(editline_name, GetInputFILE(), GetOutputFILE(), GetErrorFILE(), - m_color_prompts)); + m_color_prompts, &m_debugger)); m_editline_ap->SetIsInputCompleteCallback(IsInputCompleteCallback, this); m_editline_ap->SetAutoCompleteCallback(AutoCompleteCallback, this); // See if the delegate supports fixing indentation Index: source/Core/Debugger.cpp
[Lldb-commits] [PATCH] D48463: Prevent dead locking when calling PrintAsync
teemperor marked 2 inline comments as done. teemperor added a comment. @labath Thanks for the explanation! Well in theory we could poke more holes in our guard from some nested function, but this only fixes the deadlock symptom. PrintAsync would still be blocking whenever the mutex is hold by someone. Comment at: source/Core/Debugger.cpp:988-1004 + bool should_forward = false; + { +// We check if any user requested to delay output to a later time +// (which is designated by m_delayed_output_counter being not 0). +std::lock_guard guard(m_delayed_output_mutex); +if (m_delayed_output_counter != 0) { + // We want to delay messages, so push them to the buffer. clayborg wrote: > Can this code become: > > ``` > // We check if any user requested to delay output to a later time > // (which is designated by m_delayed_output_counter being not 0). > { > std::lock_guard guard(m_delayed_output_mutex); > if (m_delayed_output_counter != 0) { > // We want to delay messages, so push them to the buffer. > m_delayed_output.emplace_back(std::string(s, len), is_stdout); > return; > } > } > lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile(); > m_input_reader_stack.PrintAsync(stream.get(), s, len); > ``` It can and did. Removed the same pattern from the TryFlushingDelayedMessages method. Comment at: source/Core/IOHandler.cpp:358 + // lldb code that will be called from here (possibly in another thread). + Debugger::MessageDelayScope buffer_scope(m_debugger); + clayborg wrote: > So anytime we have a "(lldb)" prompt we won't be able to output something? Yes, that was the unintended effect of this patch (which was caught by the test suite actually). I didn't see until after I submitted that we actually manually unlock the guarded mutex from a called function. This now has been fixed by doing something like the unlock/lock code with the DisableMessageDelayScope in `EditLine::GetCharacter`. https://reviews.llvm.org/D48463 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48665: Added test case for: r334978 - Fixed file completion for paths that start with '~'
teemperor created this revision. teemperor added a reviewer: labath. https://reviews.llvm.org/D48665 Files: unittests/Interpreter/TestCompletion.cpp Index: unittests/Interpreter/TestCompletion.cpp === --- unittests/Interpreter/TestCompletion.cpp +++ unittests/Interpreter/TestCompletion.cpp @@ -51,6 +51,7 @@ static SmallString<128> DirBar; static SmallString<128> DirBaz; static SmallString<128> DirTestFolder; + static SmallString<128> DirNested; static SmallString<128> FileAA; static SmallString<128> FileAB; @@ -65,17 +66,17 @@ llvm::sys::fs::current_path(OriginalWorkingDir); ASSERT_NO_ERROR(fs::createUniqueDirectory("FsCompletion", BaseDir)); -const char *DirNames[] = {"foo", "fooa", "foob", "fooc", - "bar", "baz", "test_folder"}; +const char *DirNames[] = {"foo", "fooa", "foob","fooc", + "bar", "baz", "test_folder", "foo/nested"}; const char *FileNames[] = {"aa1234.tmp", "ab1234.tmp", "ac1234.tmp", "foo1234.tmp", "bar1234.tmp", "baz1234.tmp"}; -SmallString<128> *Dirs[] = {&DirFoo, &DirFooA, &DirFooB, &DirFooC, -&DirBar, &DirBaz, &DirTestFolder}; +SmallString<128> *Dirs[] = {&DirFoo, &DirFooA, &DirFooB, &DirFooC, +&DirBar, &DirBaz, &DirTestFolder, &DirNested}; for (auto Dir : llvm::zip(DirNames, Dirs)) { auto &Path = *std::get<1>(Dir); Path = BaseDir; path::append(Path, std::get<0>(Dir)); - ASSERT_NO_ERROR(fs::create_directory(Path)); + ASSERT_NO_ERROR(fs::create_directories(Path)); } SmallString<128> *Files[] = {&FileAA, &FileAB, &FileAC, @@ -146,6 +147,7 @@ SmallString<128> CompletionTest::DirBar; SmallString<128> CompletionTest::DirBaz; SmallString<128> CompletionTest::DirTestFolder; +SmallString<128> CompletionTest::DirNested; SmallString<128> CompletionTest::FileAA; SmallString<128> CompletionTest::FileAB; @@ -280,6 +282,20 @@ EXPECT_TRUE(ContainsExactString( Twine("~/test_folder") + path::get_separator(), Results)); + // Check that we can complete directories in nested paths + Count = CommandCompletions::DiskDirectories("~/foo/", Results, Resolver); + ASSERT_EQ(1u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(ContainsExactString(Twine("~/foo") + path::get_separator() + + "nested" + path::get_separator(), + Results)); + Count = CommandCompletions::DiskDirectories("~/foo/nes", Results, Resolver); + ASSERT_EQ(1u, Count); + ASSERT_EQ(Count, Results.GetSize()); + EXPECT_TRUE(ContainsExactString(Twine("~/foo") + path::get_separator() + + "nested" + path::get_separator(), + Results)); + // With ~username syntax it should return one match if there is an exact // match. // It shouldn't translate to the actual directory, it should keep the form the Index: unittests/Interpreter/TestCompletion.cpp === --- unittests/Interpreter/TestCompletion.cpp +++ unittests/Interpreter/TestCompletion.cpp @@ -51,6 +51,7 @@ static SmallString<128> DirBar; static SmallString<128> DirBaz; static SmallString<128> DirTestFolder; + static SmallString<128> DirNested; static SmallString<128> FileAA; static SmallString<128> FileAB; @@ -65,17 +66,17 @@ llvm::sys::fs::current_path(OriginalWorkingDir); ASSERT_NO_ERROR(fs::createUniqueDirectory("FsCompletion", BaseDir)); -const char *DirNames[] = {"foo", "fooa", "foob", "fooc", - "bar", "baz", "test_folder"}; +const char *DirNames[] = {"foo", "fooa", "foob","fooc", + "bar", "baz", "test_folder", "foo/nested"}; const char *FileNames[] = {"aa1234.tmp", "ab1234.tmp", "ac1234.tmp", "foo1234.tmp", "bar1234.tmp", "baz1234.tmp"}; -SmallString<128> *Dirs[] = {&DirFoo, &DirFooA, &DirFooB, &DirFooC, -&DirBar, &DirBaz, &DirTestFolder}; +SmallString<128> *Dirs[] = {&DirFoo, &DirFooA, &DirFooB, &DirFooC, +&DirBar, &DirBaz, &DirTestFolder, &DirNested}; for (auto Dir : llvm::zip(DirNames, Dirs)) { auto &Path = *std::get<1>(Dir); Path = BaseDir; path::append(Path, std::get<0>(Dir)); - ASSERT_NO_ERROR(fs::create_directory(Path)); + ASSERT_NO_ERROR(fs::create_directories(Path)); } SmallString<128> *Files[] = {&FileAA, &FileAB, &FileAC, @@ -146,6 +147,7 @@ SmallString<128> CompletionTest::DirBar; SmallString<128> CompletionTest::DirBaz; SmallString<128> CompletionTest::DirTestFolder; +SmallString<128> CompletionTest::DirN
[Lldb-commits] [lldb] r335776 - [SymbolFile] Implement GetCompleteObjCClass for .debug_names
Author: jdevlieghere Date: Wed Jun 27 12:58:39 2018 New Revision: 335776 URL: http://llvm.org/viewvc/llvm-project?rev=335776&view=rev Log: [SymbolFile] Implement GetCompleteObjCClass for .debug_names When running the test suite with .debug_names a bunch of tests were failing because GetCompleteObjCClass was not yet implemented for DebugNamesDWARFIndex. This patch adds the required logic. We use the .debug_names to find the Objective-C class and then rely on DW_AT_APPLE_objc_complete_type to find the complete type. If we can't find it or the attribute is not supported, we return a list of potential complete types. Differential revision: https://reviews.llvm.org/D48596 Modified: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h Modified: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py?rev=335776&r1=335775&r2=335776&view=diff == --- lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py Wed Jun 27 12:58:39 2018 @@ -23,9 +23,8 @@ class ForwardDeclTestCase(TestBase): self.line = line_number(self.source, '// Set breakpoint 0 here.') self.shlib_names = ["Container"] -@skipUnlessDarwin -def test_expr(self): -self.build() +def do_test(self, dictionary=None): +self.build(dictionary=dictionary) # Create a target by the debugger. target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) @@ -57,3 +56,17 @@ class ForwardDeclTestCase(TestBase): # This should display correctly. self.expect("expression [j getMember]", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 0x"]) + +@skipUnlessDarwin +def test_expr(self): +self.do_test() + +@no_debug_info_test +@skipUnlessDarwin +@skipIf(compiler=no_match("clang")) +@skipIf(compiler_version=["<", "7.0"]) +def test_debug_names(self): +"""Test that we are able to find complete types when using DWARF v5 +accelerator tables""" +self.do_test( +dict(CFLAGS_EXTRAS="-dwarf-version=5 -mllvm -accel-tables=Dwarf")) Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp?rev=335776&r1=335775&r2=335776&view=diff == --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp Wed Jun 27 12:58:39 2018 @@ -146,6 +146,49 @@ void DebugNamesDWARFIndex::GetGlobalVari } } +void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name, +bool must_be_implementation, +DIEArray &offsets) { + m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets); + + // Keep a list of incomplete types as fallback for when we don't find the + // complete type. + DIEArray incomplete_types; + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(class_name.GetStringRef())) { +if (entry.tag() != DW_TAG_structure_type && +entry.tag() != DW_TAG_class_type) + continue; + +DIERef ref = ToDIERef(entry); +if (!ref) + continue; + +DWARFUnit *cu = m_debug_info.GetCompileUnit(ref.cu_offset); +if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) { + incomplete_types.push_back(ref); + continue; +} + +// FIXME: We should return DWARFDIEs so we don't have to resolve it twice. +DWARFDIE die = m_debug_info.GetDIE(ref); +if (!die) + continue; + +if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) { + // If we find the complete version we're done. + offsets.push_back(ref); + return; +} else { + incomplete_types.push_back(ref); +} + } + + offsets.insert(offsets.end(), incomplete_types.begin(), + incomplete_types.end()); +} + void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { m_fallback.GetTypes(name, offsets); Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h?rev=335776&r1=335775&r2=335776&view=diff =
[Lldb-commits] [PATCH] D48596: [SymbolFile] Implement GetCompleteObjCClass for .debug_names
This revision was automatically updated to reflect the committed changes. Closed by commit rL335776: [SymbolFile] Implement GetCompleteObjCClass for .debug_names (authored by JDevlieghere, committed by ). Changed prior to commit: https://reviews.llvm.org/D48596?vs=153027&id=153161#toc Repository: rL LLVM https://reviews.llvm.org/D48596 Files: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h Index: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py === --- lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py @@ -23,9 +23,8 @@ self.line = line_number(self.source, '// Set breakpoint 0 here.') self.shlib_names = ["Container"] -@skipUnlessDarwin -def test_expr(self): -self.build() +def do_test(self, dictionary=None): +self.build(dictionary=dictionary) # Create a target by the debugger. target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) @@ -57,3 +56,17 @@ # This should display correctly. self.expect("expression [j getMember]", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 0x"]) + +@skipUnlessDarwin +def test_expr(self): +self.do_test() + +@no_debug_info_test +@skipUnlessDarwin +@skipIf(compiler=no_match("clang")) +@skipIf(compiler_version=["<", "7.0"]) +def test_debug_names(self): +"""Test that we are able to find complete types when using DWARF v5 +accelerator tables""" +self.do_test( +dict(CFLAGS_EXTRAS="-dwarf-version=5 -mllvm -accel-tables=Dwarf")) Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h === --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -31,7 +31,7 @@ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override; void GetObjCMethods(ConstString class_name, DIEArray &offsets) override {} void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, -DIEArray &offsets) override {} +DIEArray &offsets) override; void GetTypes(ConstString name, DIEArray &offsets) override; void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override; void GetNamespaces(ConstString name, DIEArray &offsets) override; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp === --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -146,6 +146,49 @@ } } +void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name, +bool must_be_implementation, +DIEArray &offsets) { + m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets); + + // Keep a list of incomplete types as fallback for when we don't find the + // complete type. + DIEArray incomplete_types; + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(class_name.GetStringRef())) { +if (entry.tag() != DW_TAG_structure_type && +entry.tag() != DW_TAG_class_type) + continue; + +DIERef ref = ToDIERef(entry); +if (!ref) + continue; + +DWARFUnit *cu = m_debug_info.GetCompileUnit(ref.cu_offset); +if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) { + incomplete_types.push_back(ref); + continue; +} + +// FIXME: We should return DWARFDIEs so we don't have to resolve it twice. +DWARFDIE die = m_debug_info.GetDIE(ref); +if (!die) + continue; + +if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) { + // If we find the complete version we're done. + offsets.push_back(ref); + return; +} else { + incomplete_types.push_back(ref); +} + } + + offsets.insert(offsets.end(), incomplete_types.begin(), + incomplete_types.end()); +} + void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { m_fallback.GetTypes(name, offsets); ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48620: Fix a single typo in SBSymbolContext
smeenai added a comment. This is definitely trivial enough to just go through post-commit review :) (As in, just commit it directly without going through Phabricator.) Repository: rL LLVM https://reviews.llvm.org/D48620 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48659: Allow specifying an exit code for the 'quit' command
clayborg requested changes to this revision. clayborg added a comment. This change seems fine to me. It allows each debugger to have a different exit status and each debugger can grab one. Seems like this should belong in lldb_private::CommandInterpreter and lldb::SBCommandInterpreter instead of in lldb_private::Debugger and lldb::SBDebugger Comment at: include/lldb/API/SBDebugger.h:225-226 + /// Returns the exit code that the user has set from the prompt. + int GetExitCode(); + How do you know if the quit command has been called? I mean, we can return zero when "quit" hasn't been called yet, but it might be nice to know by changing the signature a bit: ``` int GetExitCode(bool &exited); ``` **exited** would be set to true if the quit command has been called, false otherwise if the command interpreter is still running? Also "GetExitCode()" might be better and more clear as being named "GetQuitStatus()" or "GetQuitCommandStatus()" to be more clear this the result of the "quit" command? This seems like this belongs more on the SBCommandInterpreter since it is the result of the "quit" command. Maybe something like: ``` class SBCommandInterpreter { bool QuitHasBeenCalled(); int GetQuitStatus(); }; ``` Then the user can call "SBCommandInterpreter::QuitHasBeenCalled()" first and follow it with SBCommandInterpreter::GetQuitStatus() to get the status? So I this should be moved to SBCommandInterpreter.h Comment at: include/lldb/Core/Debugger.h:331-334 + void SetExitCode(int i) { m_exit_code = i; } + + int GetExitCode() const { return m_exit_code; } + move to command interpreter. Comment at: include/lldb/Core/Debugger.h:411-412 llvm::once_flag m_clear_once; + // The exit code the user has requested for the current debugger process. + int m_exit_code = 0; move to command interpreter Comment at: source/API/SBDebugger.cpp:1084-1087 +int SBDebugger::GetExitCode() { + return (m_opaque_sp ? m_opaque_sp->GetExitCode() : 0); +} + move to SBCommandInterpreter Comment at: source/Commands/CommandObjectQuit.cpp:101 +} +m_interpreter.GetDebugger().SetExitCode(exit_code); + } ``` m_interpreter.SetExitCode(exit_code); ``` Comment at: tools/driver/Driver.cpp:1162 + int exit_code = m_debugger.GetExitCode(); SBDebugger::Destroy(m_debugger); Get exit from command interpreter https://reviews.llvm.org/D48659 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48658: Fix and simplify lldb.command decorator
clayborg added a comment. Can we add a test for this to ensure all functionality that we want? I recently made changes to the cmdtemplate.py. Maybe we can integrate some more functionality that auto registers a class somehow? https://reviews.llvm.org/D48658 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48658: Fix and simplify lldb.command decorator
kastiglione added a comment. @clayborg I'll dig into how `python-extensions.swig` gets tested, and add something accordingly. I have only briefly looked at `cmdtemplate.py`. I can look into adding similar registration behavior to it. For what it's worth, I prefer functions to classes for defining commands. https://reviews.llvm.org/D48658 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48704: [LLDB] Fix for "Bug 37950: ExecutionContext::GetByteOrder() always returns endian::InlHostByteOrder()"
ramana-nvr created this revision. ramana-nvr added reviewers: davide, lldb-commits. ramana-nvr added a project: LLDB. https://reviews.llvm.org/D48704 Files: source/Target/ExecutionContext.cpp Index: source/Target/ExecutionContext.cpp === --- source/Target/ExecutionContext.cpp +++ source/Target/ExecutionContext.cpp @@ -188,9 +188,9 @@ lldb::ByteOrder ExecutionContext::GetByteOrder() const { if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) -m_target_sp->GetArchitecture().GetByteOrder(); +return m_target_sp->GetArchitecture().GetByteOrder(); if (m_process_sp) -m_process_sp->GetByteOrder(); +return m_process_sp->GetByteOrder(); return endian::InlHostByteOrder(); } Index: source/Target/ExecutionContext.cpp === --- source/Target/ExecutionContext.cpp +++ source/Target/ExecutionContext.cpp @@ -188,9 +188,9 @@ lldb::ByteOrder ExecutionContext::GetByteOrder() const { if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) -m_target_sp->GetArchitecture().GetByteOrder(); +return m_target_sp->GetArchitecture().GetByteOrder(); if (m_process_sp) -m_process_sp->GetByteOrder(); +return m_process_sp->GetByteOrder(); return endian::InlHostByteOrder(); } ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D48704: [LLDB] Fix for "Bug 37950: ExecutionContext::GetByteOrder() always returns endian::InlHostByteOrder()"
ramana-nvr updated this revision to Diff 153258. ramana-nvr added a comment. Created the patch with more context. https://reviews.llvm.org/D48704 Files: source/Target/ExecutionContext.cpp Index: source/Target/ExecutionContext.cpp === --- source/Target/ExecutionContext.cpp +++ source/Target/ExecutionContext.cpp @@ -188,9 +188,9 @@ lldb::ByteOrder ExecutionContext::GetByteOrder() const { if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) -m_target_sp->GetArchitecture().GetByteOrder(); +return m_target_sp->GetArchitecture().GetByteOrder(); if (m_process_sp) -m_process_sp->GetByteOrder(); +return m_process_sp->GetByteOrder(); return endian::InlHostByteOrder(); } Index: source/Target/ExecutionContext.cpp === --- source/Target/ExecutionContext.cpp +++ source/Target/ExecutionContext.cpp @@ -188,9 +188,9 @@ lldb::ByteOrder ExecutionContext::GetByteOrder() const { if (m_target_sp && m_target_sp->GetArchitecture().IsValid()) -m_target_sp->GetArchitecture().GetByteOrder(); +return m_target_sp->GetArchitecture().GetByteOrder(); if (m_process_sp) -m_process_sp->GetByteOrder(); +return m_process_sp->GetByteOrder(); return endian::InlHostByteOrder(); } ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits