diff options
Diffstat (limited to 'lldb')
40 files changed, 370 insertions, 222 deletions
diff --git a/lldb/examples/python/performance.py b/lldb/examples/python/performance.py index b86b5a5..c3181b6 100755 --- a/lldb/examples/python/performance.py +++ b/lldb/examples/python/performance.py @@ -16,7 +16,6 @@ import resource import sys import subprocess import time -import types # ---------------------------------------------------------------------- # Code that auto imports LLDB @@ -121,19 +120,19 @@ class BreakpointAction(Action): self.breakpoints.append(breakpoint) else: if module: - if isinstance(module, types.ListType): + if isinstance(module, list): for module_path in module: self.modules.Append(lldb.SBFileSpec(module_path, False)) - elif isinstance(module, types.StringTypes): + elif isinstance(module, str): self.modules.Append(lldb.SBFileSpec(module, False)) if name: # "file" can be a list or a string if file: - if isinstance(file, types.ListType): + if isinstance(file, list): self.files = lldb.SBFileSpecList() for f in file: self.files.Append(lldb.SBFileSpec(f, False)) - elif isinstance(file, types.StringTypes): + elif isinstance(file, str): self.files.Append(lldb.SBFileSpec(file, False)) self.breakpoints.append( self.target.BreakpointCreateByName(name, self.modules, self.files) diff --git a/lldb/examples/summaries/cocoa/CFString.py b/lldb/examples/summaries/cocoa/CFString.py index 74bd927..02b6706 100644 --- a/lldb/examples/summaries/cocoa/CFString.py +++ b/lldb/examples/summaries/cocoa/CFString.py @@ -11,11 +11,6 @@ import lldb import lldb.runtime.objc.objc_runtime import lldb.formatters.Logger -try: - unichr -except NameError: - unichr = chr - def CFString_SummaryProvider(valobj, dict): logger = lldb.formatters.Logger.Logger() @@ -107,7 +102,7 @@ class CFStringSynthProvider: value = b1 * 256 + b0 else: value = b0 * 256 + b1 - pystr = pystr + unichr(value) + pystr = pystr + chr(value) # read max_len unicode values, not max_len bytes max_len = max_len - 1 return pystr diff --git a/lldb/include/lldb/Utility/AnsiTerminal.h b/lldb/include/lldb/Utility/AnsiTerminal.h index 41acac7..aaaf94c 100644 --- a/lldb/include/lldb/Utility/AnsiTerminal.h +++ b/lldb/include/lldb/Utility/AnsiTerminal.h @@ -72,6 +72,17 @@ #define ANSI_ESC_START_LEN 2 +// Cursor Position, set cursor to position [l, c] (default = [1, 1]). +#define ANSI_CSI_CUP(...) ANSI_ESC_START #__VA_ARGS__ "H" +// Reset cursor to position. +#define ANSI_CSI_RESET_CURSOR ANSI_CSI_CUP() +// Erase In Display. +#define ANSI_CSI_ED(opt) ANSI_ESC_START #opt "J" +// Erase complete viewport. +#define ANSI_CSI_ERASE_VIEWPORT ANSI_CSI_ED(2) +// Erase scrollback. +#define ANSI_CSI_ERASE_SCROLLBACK ANSI_CSI_ED(3) + // OSC (Operating System Commands) // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html #define OSC_ESCAPE_START "\033" diff --git a/lldb/include/lldb/Utility/DataExtractor.h b/lldb/include/lldb/Utility/DataExtractor.h index 0b7e771..b4960f5 100644 --- a/lldb/include/lldb/Utility/DataExtractor.h +++ b/lldb/include/lldb/Utility/DataExtractor.h @@ -994,7 +994,7 @@ protected: constexpr size_t src_size = sizeof(T); T val = fail_value; - const T *src = static_cast<const T *>(GetData(offset_ptr, src_size)); + const void *src = GetData(offset_ptr, src_size); if (!src) return val; diff --git a/lldb/include/lldb/Utility/XcodeSDK.h b/lldb/include/lldb/Utility/XcodeSDK.h index 5b345a4..5f89019 100644 --- a/lldb/include/lldb/Utility/XcodeSDK.h +++ b/lldb/include/lldb/Utility/XcodeSDK.h @@ -38,7 +38,7 @@ public: watchOS, XRSimulator, XROS, - bridgeOS, + BridgeOS, Linux, unknown = -1 }; diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 8eb64b4..a3d924d 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -27,6 +27,10 @@ from typing import ( Literal, ) +# set timeout based on whether ASAN was enabled or not. Increase +# timeout by a factor of 10 if ASAN is enabled. +DEFAULT_TIMEOUT = 10 * (10 if ("ASAN_OPTIONS" in os.environ) else 1) + ## DAP type references @@ -282,26 +286,24 @@ class DebugCommunication(object): def collect_output( self, category: str, - timeout: float, pattern: Optional[str] = None, clear=True, ) -> str: """Collect output from 'output' events. Args: category: The category to collect. - timeout: The max duration for collecting output. pattern: Optional, if set, return once this pattern is detected in the collected output. Returns: The collected output. """ - deadline = time.monotonic() + timeout + deadline = time.monotonic() + DEFAULT_TIMEOUT output = self.get_output(category, clear) while deadline >= time.monotonic() and ( pattern is None or pattern not in output ): - event = self.wait_for_event(["output"], timeout=deadline - time.monotonic()) + event = self.wait_for_event(["output"]) if not event: # Timeout or EOF break output += self.get_output(category, clear=clear) @@ -339,7 +341,7 @@ class DebugCommunication(object): self, *, predicate: Optional[Callable[[ProtocolMessage], bool]] = None, - timeout: Optional[float] = None, + timeout: Optional[float] = DEFAULT_TIMEOUT, ) -> Optional[ProtocolMessage]: """Processes received packets from the adapter. Updates the DebugCommunication stateful properties based on the received @@ -555,25 +557,20 @@ class DebugCommunication(object): return cast(Optional[Response], self._recv_packet(predicate=predicate)) - def wait_for_event( - self, filter: List[str] = [], timeout: Optional[float] = None - ) -> Optional[Event]: + def wait_for_event(self, filter: List[str] = []) -> Optional[Event]: """Wait for the first event that matches the filter.""" def predicate(p: ProtocolMessage): return p["type"] == "event" and p["event"] in filter return cast( - Optional[Event], self._recv_packet(predicate=predicate, timeout=timeout) + Optional[Event], + self._recv_packet(predicate=predicate), ) - def wait_for_stopped( - self, timeout: Optional[float] = None - ) -> Optional[List[Event]]: + def wait_for_stopped(self) -> Optional[List[Event]]: stopped_events = [] - stopped_event = self.wait_for_event( - filter=["stopped", "exited"], timeout=timeout - ) + stopped_event = self.wait_for_event(filter=["stopped", "exited"]) while stopped_event: stopped_events.append(stopped_event) # If we exited, then we are done @@ -582,26 +579,28 @@ class DebugCommunication(object): # Otherwise we stopped and there might be one or more 'stopped' # events for each thread that stopped with a reason, so keep # checking for more 'stopped' events and return all of them - stopped_event = self.wait_for_event( - filter=["stopped", "exited"], timeout=0.25 + # Use a shorter timeout for additional stopped events + def predicate(p: ProtocolMessage): + return p["type"] == "event" and p["event"] in ["stopped", "exited"] + + stopped_event = cast( + Optional[Event], self._recv_packet(predicate=predicate, timeout=0.25) ) return stopped_events - def wait_for_breakpoint_events(self, timeout: Optional[float] = None): + def wait_for_breakpoint_events(self): breakpoint_events: list[Event] = [] while True: - event = self.wait_for_event(["breakpoint"], timeout=timeout) + event = self.wait_for_event(["breakpoint"]) if not event: break breakpoint_events.append(event) return breakpoint_events - def wait_for_breakpoints_to_be_verified( - self, breakpoint_ids: list[str], timeout: Optional[float] = None - ): + def wait_for_breakpoints_to_be_verified(self, breakpoint_ids: list[str]): """Wait for all breakpoints to be verified. Return all unverified breakpoints.""" while any(id not in self.resolved_breakpoints for id in breakpoint_ids): - breakpoint_event = self.wait_for_event(["breakpoint"], timeout=timeout) + breakpoint_event = self.wait_for_event(["breakpoint"]) if breakpoint_event is None: break @@ -614,14 +613,14 @@ class DebugCommunication(object): ) ] - def wait_for_exited(self, timeout: Optional[float] = None): - event_dict = self.wait_for_event(["exited"], timeout=timeout) + def wait_for_exited(self): + event_dict = self.wait_for_event(["exited"]) if event_dict is None: raise ValueError("didn't get exited event") return event_dict - def wait_for_terminated(self, timeout: Optional[float] = None): - event_dict = self.wait_for_event(["terminated"], timeout) + def wait_for_terminated(self): + event_dict = self.wait_for_event(["terminated"]) if event_dict is None: raise ValueError("didn't get terminated event") return event_dict @@ -1610,7 +1609,7 @@ class DebugAdapterServer(DebugCommunication): # new messages will arrive and it should shutdown on its # own. process.stdin.close() - process.wait(timeout=20) + process.wait(timeout=DEFAULT_TIMEOUT) except subprocess.TimeoutExpired: process.kill() process.wait() diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py index f7b1ed8..29935bb 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py @@ -18,7 +18,7 @@ import base64 class DAPTestCaseBase(TestBase): # set timeout based on whether ASAN was enabled or not. Increase # timeout by a factor of 10 if ASAN is enabled. - DEFAULT_TIMEOUT = 10 * (10 if ("ASAN_OPTIONS" in os.environ) else 1) + DEFAULT_TIMEOUT = dap_server.DEFAULT_TIMEOUT NO_DEBUG_INFO_TESTCASE = True def create_debug_adapter( @@ -118,11 +118,9 @@ class DAPTestCaseBase(TestBase): self.wait_for_breakpoints_to_resolve(breakpoint_ids) return breakpoint_ids - def wait_for_breakpoints_to_resolve( - self, breakpoint_ids: list[str], timeout: Optional[float] = DEFAULT_TIMEOUT - ): + def wait_for_breakpoints_to_resolve(self, breakpoint_ids: list[str]): unresolved_breakpoints = self.dap_server.wait_for_breakpoints_to_be_verified( - breakpoint_ids, timeout + breakpoint_ids ) self.assertEqual( len(unresolved_breakpoints), @@ -134,11 +132,10 @@ class DAPTestCaseBase(TestBase): self, predicate: Callable[[], bool], delay: float = 0.5, - timeout: float = DEFAULT_TIMEOUT, ) -> bool: """Repeatedly run the predicate until either the predicate returns True or a timeout has occurred.""" - deadline = time.monotonic() + timeout + deadline = time.monotonic() + self.DEFAULT_TIMEOUT while deadline > time.monotonic(): if predicate(): return True @@ -155,15 +152,13 @@ class DAPTestCaseBase(TestBase): if key in self.dap_server.capabilities: self.assertEqual(self.dap_server.capabilities[key], False, msg) - def verify_breakpoint_hit( - self, breakpoint_ids: List[Union[int, str]], timeout: float = DEFAULT_TIMEOUT - ): + def verify_breakpoint_hit(self, breakpoint_ids: List[Union[int, str]]): """Wait for the process we are debugging to stop, and verify we hit any breakpoint location in the "breakpoint_ids" array. "breakpoint_ids" should be a list of breakpoint ID strings (["1", "2"]). The return value from self.set_source_breakpoints() or self.set_function_breakpoints() can be passed to this function""" - stopped_events = self.dap_server.wait_for_stopped(timeout) + stopped_events = self.dap_server.wait_for_stopped() normalized_bp_ids = [str(b) for b in breakpoint_ids] for stopped_event in stopped_events: if "body" in stopped_event: @@ -186,11 +181,11 @@ class DAPTestCaseBase(TestBase): f"breakpoint not hit, wanted breakpoint_ids {breakpoint_ids} in stopped_events {stopped_events}", ) - def verify_all_breakpoints_hit(self, breakpoint_ids, timeout=DEFAULT_TIMEOUT): + def verify_all_breakpoints_hit(self, breakpoint_ids): """Wait for the process we are debugging to stop, and verify we hit all of the breakpoint locations in the "breakpoint_ids" array. "breakpoint_ids" should be a list of int breakpoint IDs ([1, 2]).""" - stopped_events = self.dap_server.wait_for_stopped(timeout) + stopped_events = self.dap_server.wait_for_stopped() for stopped_event in stopped_events: if "body" in stopped_event: body = stopped_event["body"] @@ -208,12 +203,12 @@ class DAPTestCaseBase(TestBase): return self.assertTrue(False, f"breakpoints not hit, stopped_events={stopped_events}") - def verify_stop_exception_info(self, expected_description, timeout=DEFAULT_TIMEOUT): + def verify_stop_exception_info(self, expected_description): """Wait for the process we are debugging to stop, and verify the stop reason is 'exception' and that the description matches 'expected_description' """ - stopped_events = self.dap_server.wait_for_stopped(timeout) + stopped_events = self.dap_server.wait_for_stopped() for stopped_event in stopped_events: if "body" in stopped_event: body = stopped_event["body"] @@ -338,26 +333,14 @@ class DAPTestCaseBase(TestBase): def get_important(self): return self.dap_server.get_output("important") - def collect_stdout( - self, timeout: float = DEFAULT_TIMEOUT, pattern: Optional[str] = None - ) -> str: - return self.dap_server.collect_output( - "stdout", timeout=timeout, pattern=pattern - ) + def collect_stdout(self, pattern: Optional[str] = None) -> str: + return self.dap_server.collect_output("stdout", pattern=pattern) - def collect_console( - self, timeout: float = DEFAULT_TIMEOUT, pattern: Optional[str] = None - ) -> str: - return self.dap_server.collect_output( - "console", timeout=timeout, pattern=pattern - ) + def collect_console(self, pattern: Optional[str] = None) -> str: + return self.dap_server.collect_output("console", pattern=pattern) - def collect_important( - self, timeout: float = DEFAULT_TIMEOUT, pattern: Optional[str] = None - ) -> str: - return self.dap_server.collect_output( - "important", timeout=timeout, pattern=pattern - ) + def collect_important(self, pattern: Optional[str] = None) -> str: + return self.dap_server.collect_output("important", pattern=pattern) def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) @@ -393,14 +376,13 @@ class DAPTestCaseBase(TestBase): targetId=None, waitForStop=True, granularity="statement", - timeout=DEFAULT_TIMEOUT, ): response = self.dap_server.request_stepIn( threadId=threadId, targetId=targetId, granularity=granularity ) self.assertTrue(response["success"]) if waitForStop: - return self.dap_server.wait_for_stopped(timeout) + return self.dap_server.wait_for_stopped() return None def stepOver( @@ -408,7 +390,6 @@ class DAPTestCaseBase(TestBase): threadId=None, waitForStop=True, granularity="statement", - timeout=DEFAULT_TIMEOUT, ): response = self.dap_server.request_next( threadId=threadId, granularity=granularity @@ -417,40 +398,40 @@ class DAPTestCaseBase(TestBase): response["success"], f"next request failed: response {response}" ) if waitForStop: - return self.dap_server.wait_for_stopped(timeout) + return self.dap_server.wait_for_stopped() return None - def stepOut(self, threadId=None, waitForStop=True, timeout=DEFAULT_TIMEOUT): + def stepOut(self, threadId=None, waitForStop=True): self.dap_server.request_stepOut(threadId=threadId) if waitForStop: - return self.dap_server.wait_for_stopped(timeout) + return self.dap_server.wait_for_stopped() return None def do_continue(self): # `continue` is a keyword. resp = self.dap_server.request_continue() self.assertTrue(resp["success"], f"continue request failed: {resp}") - def continue_to_next_stop(self, timeout=DEFAULT_TIMEOUT): + def continue_to_next_stop(self): self.do_continue() - return self.dap_server.wait_for_stopped(timeout) + return self.dap_server.wait_for_stopped() - def continue_to_breakpoint(self, breakpoint_id: str, timeout=DEFAULT_TIMEOUT): - self.continue_to_breakpoints((breakpoint_id), timeout) + def continue_to_breakpoint(self, breakpoint_id: str): + self.continue_to_breakpoints((breakpoint_id)) - def continue_to_breakpoints(self, breakpoint_ids, timeout=DEFAULT_TIMEOUT): + def continue_to_breakpoints(self, breakpoint_ids): self.do_continue() - self.verify_breakpoint_hit(breakpoint_ids, timeout) + self.verify_breakpoint_hit(breakpoint_ids) - def continue_to_exception_breakpoint(self, filter_label, timeout=DEFAULT_TIMEOUT): + def continue_to_exception_breakpoint(self, filter_label): self.do_continue() self.assertTrue( - self.verify_stop_exception_info(filter_label, timeout), + self.verify_stop_exception_info(filter_label), 'verify we got "%s"' % (filter_label), ) - def continue_to_exit(self, exitCode=0, timeout=DEFAULT_TIMEOUT): + def continue_to_exit(self, exitCode=0): self.do_continue() - stopped_events = self.dap_server.wait_for_stopped(timeout) + stopped_events = self.dap_server.wait_for_stopped() self.assertEqual( len(stopped_events), 1, "stopped_events = {}".format(stopped_events) ) diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py index aea6b9f..5ba642b 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -931,6 +931,7 @@ class GdbRemoteTestCaseBase(Base, metaclass=GdbRemoteTestCaseFactory): "QNonStop", "SupportedWatchpointTypes", "SupportedCompressions", + "MultiMemRead", ] def parse_qSupported_response(self, context): diff --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm index 7120892..96a282c 100644 --- a/lldb/source/Host/macosx/objcxx/Host.mm +++ b/lldb/source/Host/macosx/objcxx/Host.mm @@ -1221,13 +1221,12 @@ static Status LaunchProcessPosixSpawn(const char *exe_path, // using posix_spawnattr_set_use_sec_transition_shims_np_t = int (*)(posix_spawnattr_t *attr, uint32_t flags); - auto posix_spawnattr_set_use_sec_transition_shims_np_fn = + auto posix_spawnattr_enable_memory_tagging_fn = (posix_spawnattr_set_use_sec_transition_shims_np_t)dlsym( RTLD_DEFAULT, "posix_spawnattr_set_use_sec_transition_shims_np"); - if (posix_spawnattr_set_use_sec_transition_shims_np_fn) { - error = - Status(posix_spawnattr_set_use_sec_transition_shims_np_fn(&attr, 0), - eErrorTypePOSIX); + if (posix_spawnattr_enable_memory_tagging_fn) { + error = Status(posix_spawnattr_enable_memory_tagging_fn(&attr, 0), + eErrorTypePOSIX); if (error.Fail()) { LLDB_LOG(log, "error: {0}, " diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index 92094c0..e3b6ff8 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -332,8 +332,7 @@ CompilerType ClangASTImporter::DeportType(TypeSystemClang &dst, DeclContextOverride decl_context_override; if (auto *t = ClangUtil::GetQualType(src_type)->getAs<TagType>()) - decl_context_override.OverrideAllDeclsFromContainingFunction( - t->getOriginalDecl()); + decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl()); CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(), &src_ctxt->getASTContext()); @@ -393,7 +392,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) { case clang::Type::Record: return CanImport(qual_type->getAsCXXRecordDecl()); case clang::Type::Enum: - return CanImport(llvm::cast<clang::EnumType>(qual_type)->getOriginalDecl()); + return CanImport(llvm::cast<clang::EnumType>(qual_type)->getDecl()); case clang::Type::ObjCObject: case clang::Type::ObjCInterface: { const clang::ObjCObjectType *objc_class_type = @@ -452,7 +451,7 @@ bool ClangASTImporter::Import(const CompilerType &type) { case clang::Type::Enum: { clang::EnumDecl *enum_decl = - llvm::cast<clang::EnumType>(qual_type)->getOriginalDecl(); + llvm::cast<clang::EnumType>(qual_type)->getDecl(); if (enum_decl) { if (GetDeclOrigin(enum_decl).Valid()) return CompleteAndFetchChildren(qual_type); @@ -591,7 +590,7 @@ bool ExtractBaseOffsets(const ASTRecordLayout &record_layout, return false; DeclFromUser<RecordDecl> origin_base_record( - origin_base_record_type->getOriginalDecl()); + origin_base_record_type->getDecl()); if (origin_base_record.IsInvalid()) return false; @@ -722,8 +721,7 @@ bool ClangASTImporter::importRecordLayoutFromOrigin( QualType base_type = bi->getType(); const RecordType *base_record_type = base_type->getAs<RecordType>(); - DeclFromParser<RecordDecl> base_record( - base_record_type->getOriginalDecl()); + DeclFromParser<RecordDecl> base_record(base_record_type->getDecl()); DeclFromParser<CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record); @@ -855,7 +853,7 @@ bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) { Log *log = GetLog(LLDBLog::Expressions); if (const TagType *tag_type = type->getAs<TagType>()) { - TagDecl *tag_decl = tag_type->getOriginalDecl(); + TagDecl *tag_decl = tag_type->getDecl(); DeclOrigin decl_origin = GetDeclOrigin(tag_decl); @@ -923,7 +921,7 @@ bool ClangASTImporter::RequireCompleteType(clang::QualType type) { return false; if (const TagType *tag_type = type->getAs<TagType>()) { - TagDecl *tag_decl = tag_type->getOriginalDecl(); + TagDecl *tag_decl = tag_type->getDecl(); if (tag_decl->getDefinition()) return true; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 21a9307..ebe7be4 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -223,7 +223,7 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { continue; TagDecl *candidate_tag_decl = - tag_type->getOriginalDecl()->getDefinitionOrSelf(); + tag_type->getDecl()->getDefinitionOrSelf(); if (TypeSystemClang::GetCompleteDecl( &candidate_tag_decl->getASTContext(), candidate_tag_decl)) @@ -250,8 +250,7 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { if (!tag_type) continue; - TagDecl *candidate_tag_decl = - tag_type->getOriginalDecl()->getDefinitionOrSelf(); + TagDecl *candidate_tag_decl = tag_type->getDecl()->getDefinitionOrSelf(); if (TypeSystemClang::GetCompleteDecl(&candidate_tag_decl->getASTContext(), candidate_tag_decl)) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 8a68282..833bc3b 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1561,7 +1561,7 @@ ClangExpressionDeclMap::AddExpressionVariable(NameSearchContext &context, if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) { if (const TagType *tag_type = dyn_cast<TagType>(parser_type)) - CompleteType(tag_type->getOriginalDecl()->getDefinitionOrSelf()); + CompleteType(tag_type->getDecl()->getDefinitionOrSelf()); if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast<ObjCObjectPointerType>(parser_type)) CompleteType(objc_object_ptr_type->getInterfaceDecl()); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp index 6f57c18..794b194 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp @@ -153,7 +153,7 @@ NameSearchContext::AddTypeDecl(const CompilerType &clang_type) { return (NamedDecl *)typedef_name_decl; } else if (const TagType *tag_type = qual_type->getAs<TagType>()) { - TagDecl *tag_decl = tag_type->getOriginalDecl()->getDefinitionOrSelf(); + TagDecl *tag_decl = tag_type->getDecl()->getDefinitionOrSelf(); m_decls.push_back(tag_decl); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 6d8f41a..460c503 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -260,6 +260,7 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process, uint32_t entsize = extractor.GetU32_unchecked(&cursor); m_is_small = (entsize & 0x80000000) != 0; m_has_direct_selector = (entsize & 0x40000000) != 0; + m_has_relative_types = (entsize & 0x20000000) != 0; m_entsize = entsize & 0xfffc; m_count = extractor.GetU32_unchecked(&cursor); m_first_ptr = addr + cursor; @@ -269,8 +270,9 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process, llvm::SmallVector<ClassDescriptorV2::method_t, 0> ClassDescriptorV2::ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses, - lldb::addr_t relative_selector_base_addr, - bool is_small, bool has_direct_sel) const { + lldb::addr_t relative_string_base_addr, + bool is_small, bool has_direct_sel, + bool has_relative_types) const { lldb_private::Process *process = m_runtime.GetProcess(); if (!process) return {}; @@ -297,8 +299,8 @@ ClassDescriptorV2::ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses, process->GetByteOrder(), process->GetAddressByteSize()); methods.push_back(method_t()); - methods.back().Read(extractor, process, addr, relative_selector_base_addr, - is_small, has_direct_sel); + methods.back().Read(extractor, process, addr, relative_string_base_addr, + is_small, has_direct_sel, has_relative_types); } return methods; @@ -306,8 +308,9 @@ ClassDescriptorV2::ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses, bool ClassDescriptorV2::method_t::Read(DataExtractor &extractor, Process *process, lldb::addr_t addr, - lldb::addr_t relative_selector_base_addr, - bool is_small, bool has_direct_sel) { + lldb::addr_t relative_string_base_addr, + bool is_small, bool has_direct_sel, + bool has_relative_types) { lldb::offset_t cursor = 0; if (is_small) { @@ -323,10 +326,13 @@ bool ClassDescriptorV2::method_t::Read(DataExtractor &extractor, m_name_ptr = process->ReadPointerFromMemory(m_name_ptr, error); if (error.Fail()) return false; - } else if (relative_selector_base_addr != LLDB_INVALID_ADDRESS) { - m_name_ptr = relative_selector_base_addr + nameref_offset; + } else if (relative_string_base_addr != LLDB_INVALID_ADDRESS) { + m_name_ptr = relative_string_base_addr + nameref_offset; } - m_types_ptr = addr + 4 + types_offset; + if (has_relative_types) + m_types_ptr = relative_string_base_addr + types_offset; + else + m_types_ptr = addr + 4 + types_offset; m_imp_ptr = addr + 8 + imp_offset; } else { m_name_ptr = extractor.GetAddress_unchecked(&cursor); @@ -481,7 +487,8 @@ bool ClassDescriptorV2::ProcessMethodList( llvm::SmallVector<method_t, 0> methods = ReadMethods(addresses, m_runtime.GetRelativeSelectorBaseAddr(), - method_list.m_is_small, method_list.m_has_direct_selector); + method_list.m_is_small, method_list.m_has_direct_selector, + method_list.m_has_relative_types); for (const auto &method : methods) if (instance_method_func(method.m_name.c_str(), method.m_types.c_str())) diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h index 78b3311..0fff9af 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h @@ -143,6 +143,7 @@ private: uint16_t m_entsize; bool m_is_small; bool m_has_direct_selector; + bool m_has_relative_types; uint32_t m_count; lldb::addr_t m_first_ptr; @@ -173,14 +174,14 @@ private: } bool Read(DataExtractor &extractor, Process *process, lldb::addr_t addr, - lldb::addr_t relative_selector_base_addr, bool is_small, - bool has_direct_sel); + lldb::addr_t relative_string_base_addr, bool is_small, + bool has_direct_sel, bool has_relative_types); }; llvm::SmallVector<method_t, 0> ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses, - lldb::addr_t relative_selector_base_addr, bool is_small, - bool has_direct_sel) const; + lldb::addr_t relative_string_base_addr, bool is_small, + bool has_direct_sel, bool has_relative_types) const; struct ivar_list_t { uint32_t m_entsize; diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index cd72454..5aad447 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -1150,7 +1150,7 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( case XcodeSDK::Type::XRSimulator: case XcodeSDK::Type::XROS: // FIXME: Pass the right argument once it exists. - case XcodeSDK::Type::bridgeOS: + case XcodeSDK::Type::BridgeOS: case XcodeSDK::Type::Linux: case XcodeSDK::Type::unknown: if (Log *log = GetLog(LLDBLog::Host)) { diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 12cabff..82dfe7e 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -2629,7 +2629,7 @@ TypeSystemClang::GetDeclContextForType(clang::QualType type) { case clang::Type::Enum: case clang::Type::Record: return llvm::cast<clang::TagType>(qual_type) - ->getOriginalDecl() + ->getDecl() ->getDefinitionOrSelf(); default: break; @@ -2879,8 +2879,7 @@ bool TypeSystemClang::IsAnonymousType(lldb::opaque_compiler_type_t type) { if (const clang::RecordType *record_type = llvm::dyn_cast_or_null<clang::RecordType>( qual_type.getTypePtrOrNull())) { - if (const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()) { + if (const clang::RecordDecl *record_decl = record_type->getDecl()) { return record_decl->isAnonymousStructOrUnion(); } } @@ -3121,7 +3120,7 @@ TypeSystemClang::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, llvm::cast<clang::RecordType>(qual_type.getTypePtr()); if (record_type) { if (const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinition()) { + record_type->getDecl()->getDefinition()) { // We are looking for a structure that contains only floating point // types clang::RecordDecl::field_iterator field_pos, @@ -3301,7 +3300,7 @@ bool TypeSystemClang::IsEnumerationType(lldb::opaque_compiler_type_t type, GetCanonicalQualType(type)->getCanonicalTypeInternal()); if (enum_type) { - IsIntegerType(enum_type->getOriginalDecl() + IsIntegerType(enum_type->getDecl() ->getDefinitionOrSelf() ->getIntegerType() .getAsOpaquePtr(), @@ -3529,7 +3528,7 @@ bool TypeSystemClang::IsDefined(lldb::opaque_compiler_type_t type) { const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); if (tag_type) { - if (clang::TagDecl *tag_decl = tag_type->getOriginalDecl()->getDefinition()) + if (clang::TagDecl *tag_decl = tag_type->getDecl()->getDefinition()) return tag_decl->isCompleteDefinition(); return false; } else { @@ -3782,7 +3781,7 @@ bool TypeSystemClang::IsBeingDefined(lldb::opaque_compiler_type_t type) { clang::QualType qual_type(GetCanonicalQualType(type)); const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type); if (tag_type) - return tag_type->getOriginalDecl()->isEntityBeingDefined(); + return tag_type->getDecl()->isEntityBeingDefined(); return false; } @@ -3988,7 +3987,7 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type, if (pointee_or_element_clang_type) pointee_or_element_clang_type->SetCompilerType( weak_from_this(), llvm::cast<clang::EnumType>(qual_type) - ->getOriginalDecl() + ->getDecl() ->getDefinitionOrSelf() ->getIntegerType() .getAsOpaquePtr()); @@ -4228,7 +4227,7 @@ TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) { case clang::Type::Record: { const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getOriginalDecl(); + const clang::RecordDecl *record_decl = record_type->getDecl(); if (record_decl->isUnion()) return lldb::eTypeClassUnion; else if (record_decl->isStruct()) @@ -4704,9 +4703,9 @@ CompilerType TypeSystemClang::CreateTypedef( clang::TagDecl *tdecl = nullptr; if (!qual_type.isNull()) { if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>()) - tdecl = rt->getOriginalDecl(); + tdecl = rt->getDecl(); if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>()) - tdecl = et->getOriginalDecl(); + tdecl = et->getDecl(); } // Check whether this declaration is an anonymous struct, union, or enum, @@ -5386,7 +5385,7 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); @@ -5583,7 +5582,7 @@ void TypeSystemClang::ForEachEnumerator( llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)); if (enum_type) { const clang::EnumDecl *enum_decl = - enum_type->getOriginalDecl()->getDefinitionOrSelf(); + enum_type->getDecl()->getDefinitionOrSelf(); if (enum_decl) { CompilerType integer_type = GetType(enum_decl->getIntegerType()); @@ -5615,7 +5614,7 @@ uint32_t TypeSystemClang::GetNumFields(lldb::opaque_compiler_type_t type) { llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr()); if (record_type) { clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinition(); + record_type->getDecl()->getDefinition(); if (record_decl) { count = std::distance(record_decl->field_begin(), record_decl->field_end()); @@ -5730,7 +5729,7 @@ CompilerType TypeSystemClang::GetFieldAtIndex(lldb::opaque_compiler_type_t type, const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); uint32_t field_idx = 0; clang::RecordDecl::field_iterator field, field_end; for (field = record_decl->field_begin(), @@ -5916,7 +5915,7 @@ CompilerType TypeSystemClang::GetDirectBaseClassAtIndex( llvm::cast<clang::CXXRecordDecl>( base_class->getType() ->castAs<clang::RecordType>() - ->getOriginalDecl()); + ->getDecl()); if (base_class->isVirtual()) *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl) @@ -6011,7 +6010,7 @@ CompilerType TypeSystemClang::GetVirtualBaseClassAtIndex( llvm::cast<clang::CXXRecordDecl>( base_class->getType() ->castAs<clang::RecordType>() - ->getOriginalDecl()); + ->getDecl()); *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl) .getQuantity() * @@ -6042,7 +6041,7 @@ TypeSystemClang::GetStaticFieldWithName(lldb::opaque_compiler_type_t type, const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); clang::DeclarationName decl_name(&getASTContext().Idents.get(name)); for (NamedDecl *decl : record_decl->lookup(decl_name)) { @@ -6271,7 +6270,7 @@ llvm::Expected<CompilerType> TypeSystemClang::GetChildCompilerTypeAtIndex( const clang::RecordType *record_type = llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr()); const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); const clang::ASTRecordLayout &record_layout = getASTContext().getASTRecordLayout(record_decl); uint32_t child_idx = 0; @@ -6292,7 +6291,7 @@ llvm::Expected<CompilerType> TypeSystemClang::GetChildCompilerTypeAtIndex( base_class_decl = llvm::cast<clang::CXXRecordDecl>( base_class->getType() ->getAs<clang::RecordType>() - ->getOriginalDecl()) + ->getDecl()) ->getDefinitionOrSelf(); if (!TypeSystemClang::RecordHasFields(base_class_decl)) continue; @@ -6303,7 +6302,7 @@ llvm::Expected<CompilerType> TypeSystemClang::GetChildCompilerTypeAtIndex( base_class_decl = llvm::cast<clang::CXXRecordDecl>( base_class->getType() ->getAs<clang::RecordType>() - ->getOriginalDecl()) + ->getDecl()) ->getDefinitionOrSelf(); if (base_class->isVirtual()) { @@ -6766,7 +6765,7 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName( const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); assert(record_decl); uint32_t child_idx = 0; @@ -6833,7 +6832,7 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName( child_indexes.push_back(child_idx); parent_record_decl = elem.Base->getType() ->castAs<clang::RecordType>() - ->getOriginalDecl() + ->getDecl() ->getDefinitionOrSelf(); } } @@ -6969,7 +6968,7 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); assert(record_decl); uint32_t child_idx = 0; @@ -6988,7 +6987,7 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, llvm::cast<clang::CXXRecordDecl>( base_class->getType() ->castAs<clang::RecordType>() - ->getOriginalDecl()) + ->getDecl()) ->getDefinitionOrSelf(); if (omit_empty_base_classes && !TypeSystemClang::RecordHasFields(base_class_decl)) @@ -7109,7 +7108,7 @@ TypeSystemClang::GetDirectNestedTypeWithName(lldb::opaque_compiler_type_t type, const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); clang::DeclarationName decl_name(&getASTContext().Idents.get(name)); for (NamedDecl *decl : record_decl->lookup(decl_name)) { @@ -7135,7 +7134,7 @@ bool TypeSystemClang::IsTemplateType(lldb::opaque_compiler_type_t type) { const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr(); if (auto *cxx_record_decl = dyn_cast<clang::TagType>(clang_type)) return isa<clang::ClassTemplateSpecializationDecl>( - cxx_record_decl->getOriginalDecl()); + cxx_record_decl->getDecl()); return false; } @@ -7338,7 +7337,7 @@ clang::EnumDecl *TypeSystemClang::GetAsEnumDecl(const CompilerType &type) { const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type)); if (enutype) - return enutype->getOriginalDecl()->getDefinitionOrSelf(); + return enutype->getDecl()->getDefinitionOrSelf(); return nullptr; } @@ -7346,7 +7345,7 @@ clang::RecordDecl *TypeSystemClang::GetAsRecordDecl(const CompilerType &type) { const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(ClangUtil::GetCanonicalQualType(type)); if (record_type) - return record_type->getOriginalDecl()->getDefinitionOrSelf(); + return record_type->getDecl()->getDefinitionOrSelf(); return nullptr; } @@ -7428,7 +7427,7 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType( if (const clang::TagType *TagT = field->getType()->getAs<clang::TagType>()) { if (clang::RecordDecl *Rec = - llvm::dyn_cast<clang::RecordDecl>(TagT->getOriginalDecl())) + llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl())) if (!Rec->getDeclName()) { Rec->setAnonymousStructOrUnion(true); field->setImplicit(); @@ -7514,7 +7513,7 @@ void TypeSystemClang::BuildIndirectFields(const CompilerType &type) { continue; clang::RecordDecl *field_record_decl = - field_record_type->getOriginalDecl()->getDefinition(); + field_record_type->getDecl()->getDefinition(); if (!field_record_decl) continue; @@ -7656,8 +7655,7 @@ void TypeSystemClang::SetIntegerInitializerForVariable( // If the variable is an enum type, take the underlying integer type as // the type of the integer literal. if (const EnumType *enum_type = qt->getAs<EnumType>()) { - const EnumDecl *enum_decl = - enum_type->getOriginalDecl()->getDefinitionOrSelf(); + const EnumDecl *enum_decl = enum_type->getDecl()->getDefinitionOrSelf(); qt = enum_decl->getIntegerType(); } // Bools are handled separately because the clang AST printer handles bools @@ -8317,7 +8315,7 @@ bool TypeSystemClang::SetHasExternalStorage(lldb::opaque_compiler_type_t type, case clang::Type::Enum: { clang::EnumDecl *enum_decl = - llvm::cast<clang::EnumType>(qual_type)->getOriginalDecl(); + llvm::cast<clang::EnumType>(qual_type)->getDecl(); if (enum_decl) { enum_decl->setHasExternalLexicalStorage(has_extern); enum_decl->setHasExternalVisibleStorage(has_extern); @@ -8355,7 +8353,7 @@ bool TypeSystemClang::StartTagDeclarationDefinition(const CompilerType &type) { if (!qual_type.isNull()) { const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); if (tag_type) { - clang::TagDecl *tag_decl = tag_type->getOriginalDecl(); + clang::TagDecl *tag_decl = tag_type->getDecl(); if (tag_decl) { tag_decl->startDefinition(); return true; @@ -8390,8 +8388,7 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition( // the definition. const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); if (tag_type) { - clang::TagDecl *tag_decl = - tag_type->getOriginalDecl()->getDefinitionOrSelf(); + clang::TagDecl *tag_decl = tag_type->getDecl()->getDefinitionOrSelf(); if (auto *cxx_record_decl = llvm::dyn_cast<CXXRecordDecl>(tag_decl)) { // If we have a move constructor declared but no copy constructor we @@ -8426,8 +8423,7 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition( if (!enutype) return false; - clang::EnumDecl *enum_decl = - enutype->getOriginalDecl()->getDefinitionOrSelf(); + clang::EnumDecl *enum_decl = enutype->getDecl()->getDefinitionOrSelf(); if (enum_decl->isCompleteDefinition()) return true; @@ -8485,8 +8481,7 @@ clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType( clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::CreateDeserialized(getASTContext(), GlobalDeclID()); - clang::EnumDecl *enum_decl = - enutype->getOriginalDecl()->getDefinitionOrSelf(); + clang::EnumDecl *enum_decl = enutype->getDecl()->getDefinitionOrSelf(); enumerator_decl->setDeclContext(enum_decl); if (name && name[0]) enumerator_decl->setDeclName(&getASTContext().Idents.get(name)); @@ -8521,8 +8516,7 @@ CompilerType TypeSystemClang::GetEnumerationIntegerType(CompilerType type) { if (!enum_type) return CompilerType(); - return GetType( - enum_type->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType()); + return GetType(enum_type->getDecl()->getDefinitionOrSelf()->getIntegerType()); } CompilerType @@ -8630,8 +8624,7 @@ static bool DumpEnumValue(const clang::QualType &qual_type, Stream &s, uint32_t bitfield_bit_size) { const clang::EnumType *enutype = llvm::cast<clang::EnumType>(qual_type.getTypePtr()); - const clang::EnumDecl *enum_decl = - enutype->getOriginalDecl()->getDefinitionOrSelf(); + const clang::EnumDecl *enum_decl = enutype->getDecl()->getDefinitionOrSelf(); lldb::offset_t offset = byte_offset; bool qual_type_is_signed = qual_type->isSignedIntegerOrEnumerationType(); const uint64_t enum_svalue = @@ -8907,7 +8900,7 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, GetCompleteType(type); auto *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getOriginalDecl(); + const clang::RecordDecl *record_decl = record_type->getDecl(); if (level == eDescriptionLevelVerbose) record_decl->dump(llvm_ostrm); else { @@ -8919,7 +8912,7 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, default: { if (auto *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr())) { - if (clang::TagDecl *tag_decl = tag_type->getOriginalDecl()) { + if (clang::TagDecl *tag_decl = tag_type->getDecl()) { if (level == eDescriptionLevelVerbose) tag_decl->dump(llvm_ostrm); else @@ -8959,7 +8952,7 @@ void TypeSystemClang::DumpTypeName(const CompilerType &type) { case clang::Type::Enum: { clang::EnumDecl *enum_decl = - llvm::cast<clang::EnumType>(qual_type)->getOriginalDecl(); + llvm::cast<clang::EnumType>(qual_type)->getDecl(); if (enum_decl) { printf("enum %s", enum_decl->getName().str().c_str()); } @@ -9825,7 +9818,7 @@ bool TypeSystemClang::IsForcefullyCompleted(lldb::opaque_compiler_type_t type) { llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr()); if (record_type) { const clang::RecordDecl *record_decl = - record_type->getOriginalDecl()->getDefinitionOrSelf(); + record_type->getDecl()->getDefinitionOrSelf(); if (std::optional<ClangASTMetadata> metadata = GetMetadata(record_decl)) return metadata->IsForcefullyCompleted(); } diff --git a/lldb/source/Utility/XcodeSDK.cpp b/lldb/source/Utility/XcodeSDK.cpp index 2040791..89e05de 100644 --- a/lldb/source/Utility/XcodeSDK.cpp +++ b/lldb/source/Utility/XcodeSDK.cpp @@ -38,8 +38,8 @@ static llvm::StringRef GetName(XcodeSDK::Type type) { return "XRSimulator"; case XcodeSDK::XROS: return "XROS"; - case XcodeSDK::bridgeOS: - return "bridgeOS"; + case XcodeSDK::BridgeOS: + return "BridgeOS"; case XcodeSDK::Linux: return "Linux"; case XcodeSDK::unknown: @@ -83,8 +83,8 @@ static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) { return XcodeSDK::XRSimulator; if (name.consume_front("XROS")) return XcodeSDK::XROS; - if (name.consume_front("bridgeOS")) - return XcodeSDK::bridgeOS; + if (name.consume_front("BridgeOS")) + return XcodeSDK::BridgeOS; if (name.consume_front("Linux")) return XcodeSDK::Linux; static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1, @@ -204,7 +204,7 @@ std::string XcodeSDK::GetCanonicalName(XcodeSDK::Info info) { case XROS: name = "xros"; break; - case bridgeOS: + case BridgeOS: name = "bridgeos"; break; case Linux: diff --git a/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py index ed028a1..4aea800 100644 --- a/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py @@ -11,6 +11,9 @@ class TestCase(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(macos_version=["<", "15.0"]) + @skipIf( + bugnumber="ASTImport of lambdas not supported: https://github.com/llvm/llvm-project/issues/149477" + ) def test(self): self.build() diff --git a/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py b/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py index ed373f2..9e29f07 100644 --- a/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py +++ b/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py @@ -71,7 +71,7 @@ class TestDAP_attachCommands(lldbdap_testcase.DAPTestCaseBase): breakpoint_ids = self.set_function_breakpoints(functions) self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint") self.continue_to_breakpoints(breakpoint_ids) - output = self.collect_console(timeout=10, pattern=stopCommands[-1]) + output = self.collect_console(pattern=stopCommands[-1]) self.verify_commands("stopCommands", output, stopCommands) # Continue after launch and hit the "pause()" call and stop the target. @@ -81,7 +81,7 @@ class TestDAP_attachCommands(lldbdap_testcase.DAPTestCaseBase): time.sleep(0.5) self.dap_server.request_pause() self.dap_server.wait_for_stopped() - output = self.collect_console(timeout=10, pattern=stopCommands[-1]) + output = self.collect_console(pattern=stopCommands[-1]) self.verify_commands("stopCommands", output, stopCommands) # Continue until the program exits @@ -90,7 +90,6 @@ class TestDAP_attachCommands(lldbdap_testcase.DAPTestCaseBase): # "exitCommands" that were run after the second breakpoint was hit # and the "terminateCommands" due to the debugging session ending output = self.collect_console( - timeout=10.0, pattern=terminateCommands[0], ) self.verify_commands("exitCommands", output, exitCommands) @@ -141,7 +140,6 @@ class TestDAP_attachCommands(lldbdap_testcase.DAPTestCaseBase): # "terminateCommands" self.dap_server.request_disconnect(terminateDebuggee=True) output = self.collect_console( - timeout=1.0, pattern=terminateCommands[0], ) self.verify_commands("terminateCommands", output, terminateCommands) diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py index 151ad76..beab4d6 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py @@ -82,14 +82,14 @@ class TestDAP_breakpointEvents(lldbdap_testcase.DAPTestCaseBase): ) # Flush the breakpoint events. - self.dap_server.wait_for_breakpoint_events(timeout=5) + self.dap_server.wait_for_breakpoint_events() # Continue to the breakpoint self.continue_to_breakpoints(dap_breakpoint_ids) verified_breakpoint_ids = [] unverified_breakpoint_ids = [] - for breakpoint_event in self.dap_server.wait_for_breakpoint_events(timeout=5): + for breakpoint_event in self.dap_server.wait_for_breakpoint_events(): breakpoint = breakpoint_event["body"]["breakpoint"] id = breakpoint["id"] if breakpoint["verified"]: diff --git a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py index e722fce..14789a6 100644 --- a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py +++ b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py @@ -46,7 +46,7 @@ class TestDAP_cancel(lldbdap_testcase.DAPTestCaseBase): # Use a relatively short timeout since this is only to ensure the # following request is queued. - blocking_seq = self.async_blocking_request(duration=1.0) + blocking_seq = self.async_blocking_request(duration=self.DEFAULT_TIMEOUT / 10) # Use a longer timeout to ensure we catch if the request was interrupted # properly. pending_seq = self.async_blocking_request(duration=self.DEFAULT_TIMEOUT / 2) diff --git a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py index e61d248..f53813a 100644 --- a/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py +++ b/lldb/test/API/tools/lldb-dap/commands/TestDAP_commands.py @@ -23,7 +23,6 @@ class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase): exitCommands=["?" + command_quiet, command_not_quiet], ) full_output = self.collect_console( - timeout=1.0, pattern=command_not_quiet, ) self.assertNotIn(command_quiet, full_output) @@ -51,7 +50,6 @@ class TestDAP_commands(lldbdap_testcase.DAPTestCaseBase): expectFailure=True, ) full_output = self.collect_console( - timeout=1.0, pattern=command_abort_on_error, ) self.assertNotIn(command_quiet, full_output) diff --git a/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py b/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py index af5c62a..9fbe9aa 100644 --- a/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py +++ b/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py @@ -44,7 +44,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): """ process = self.launch() process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_SUCCESS) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_SUCCESS) def test_invalid_header(self): """ @@ -54,7 +54,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"not the correct message header") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) def test_partial_header(self): """ @@ -64,7 +64,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"Content-Length: ") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) def test_incorrect_content_length(self): """ @@ -74,7 +74,7 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"Content-Length: abc") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) def test_partial_content_length(self): """ @@ -84,4 +84,4 @@ class TestDAP_io(lldbdap_testcase.DAPTestCaseBase): process = self.launch() process.stdin.write(b"Content-Length: 10\r\n\r\n{") process.stdin.close() - self.assertEqual(process.wait(timeout=5.0), EXIT_FAILURE) + self.assertEqual(process.wait(timeout=self.DEFAULT_TIMEOUT), EXIT_FAILURE) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py index ceef95df..8db2316 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py @@ -632,7 +632,27 @@ class TestDAP_launch(lldbdap_testcase.DAPTestCaseBase): program = self.getBuildArtifact("a.out") with tempfile.NamedTemporaryFile("rt") as f: - self.launch(program, stdio=[None, f.name, None]) + self.launch(program, stdio=[None, f.name]) + self.continue_to_exit() + lines = f.readlines() + self.assertIn( + program, lines[0], "make sure program path is in first argument" + ) + + @skipIfAsan + @skipIfWindows + @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) + def test_stdio_redirection_and_console(self): + """ + Test stdio redirection and console. + """ + self.build_and_create_debug_adapter() + program = self.getBuildArtifact("a.out") + + with tempfile.NamedTemporaryFile("rt") as f: + self.launch( + program, console="integratedTerminal", stdio=[None, f.name, None] + ) self.continue_to_exit() lines = f.readlines() self.assertIn( diff --git a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py index bb835af..1f4afab 100644 --- a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py +++ b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py @@ -23,15 +23,15 @@ class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase): self.continue_to_breakpoints(breakpoint_ids) # We're now stopped at breakpoint 1 before the dlopen. Flush all the module events. - event = self.dap_server.wait_for_event(["module"], 0.25) + event = self.dap_server.wait_for_event(["module"]) while event is not None: - event = self.dap_server.wait_for_event(["module"], 0.25) + event = self.dap_server.wait_for_event(["module"]) # Continue to the second breakpoint, before the dlclose. self.continue_to_breakpoints(breakpoint_ids) # Make sure we got a module event for libother. - event = self.dap_server.wait_for_event(["module"], 5) + event = self.dap_server.wait_for_event(["module"]) self.assertIsNotNone(event, "didn't get a module event") module_name = event["body"]["module"]["name"] module_id = event["body"]["module"]["id"] @@ -42,7 +42,7 @@ class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase): self.continue_to_breakpoints(breakpoint_ids) # Make sure we got a module event for libother. - event = self.dap_server.wait_for_event(["module"], 5) + event = self.dap_server.wait_for_event(["module"]) self.assertIsNotNone(event, "didn't get a module event") reason = event["body"]["reason"] self.assertEqual(reason, "removed") @@ -55,8 +55,4 @@ class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase): self.assertListEqual(list(module_data.keys()), required_keys) self.assertEqual(module_data["name"], "", "expects empty name.") - # Make sure we do not send another event - event = self.dap_server.wait_for_event(["module"], 3) - self.assertIsNone(event, "expects no events.") - self.continue_to_exit() diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py index c5a6837..0ed53da 100644 --- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py +++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py @@ -67,7 +67,7 @@ class TestDAP_module(lldbdap_testcase.DAPTestCaseBase): # Collect all the module names we saw as events. module_new_names = [] module_changed_names = [] - module_event = self.dap_server.wait_for_event(["module"], 1) + module_event = self.dap_server.wait_for_event(["module"]) while module_event is not None: reason = module_event["body"]["reason"] if reason == "new": @@ -75,7 +75,7 @@ class TestDAP_module(lldbdap_testcase.DAPTestCaseBase): elif reason == "changed": module_changed_names.append(module_event["body"]["module"]["name"]) - module_event = self.dap_server.wait_for_event(["module"], 1) + module_event = self.dap_server.wait_for_event(["module"]) # Make sure we got an event for every active module. self.assertNotEqual(len(module_new_names), 0) diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py index fe978a9..0065258 100644 --- a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -29,7 +29,7 @@ class TestDAP_output(lldbdap_testcase.DAPTestCaseBase): self.continue_to_breakpoints(breakpoint_ids) # Ensure partial messages are still sent. - output = self.collect_stdout(timeout=1.0, pattern="abcdef") + output = self.collect_stdout(pattern="abcdef") self.assertTrue(output and len(output) > 0, "expect program stdout") self.continue_to_exit() diff --git a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py index 6748379..e1ad142 100644 --- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py +++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py @@ -105,7 +105,7 @@ class TestDAP_restart_console(lldbdap_testcase.DAPTestCaseBase): # Restart and check that we still get a stopped event before reaching # main. self.dap_server.request_restart() - stopped_events = self.dap_server.wait_for_stopped(timeout=20) + stopped_events = self.dap_server.wait_for_stopped() self.verify_stopped_on_entry(stopped_events) # continue to main diff --git a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py index 13a69460..977d6ce 100644 --- a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py +++ b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py @@ -65,6 +65,11 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): self.assertNotIn( key, actual, 'key "%s" is not expected in %s' % (key, actual) ) + isReadOnly = verify_dict.get("readOnly", False) + attributes = actual.get("presentationHint", {}).get("attributes", []) + self.assertEqual( + isReadOnly, "readOnly" in attributes, "%s %s" % (verify_dict, actual) + ) hasVariablesReference = "variablesReference" in actual varRef = None if hasVariablesReference: @@ -179,8 +184,9 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "children": { "x": {"equals": {"type": "int", "value": "11"}}, "y": {"equals": {"type": "int", "value": "22"}}, - "buffer": {"children": buffer_children}, + "buffer": {"children": buffer_children, "readOnly": True}, }, + "readOnly": True, }, "x": {"equals": {"type": "int"}}, } @@ -444,8 +450,10 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "buffer": { "children": buffer_children, "equals": {"indexedVariables": 16}, + "readOnly": True, }, }, + "readOnly": True, }, "x": { "equals": {"type": "int"}, @@ -528,7 +536,7 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "children": { "x": {"equals": {"type": "int", "value": "11"}}, "y": {"equals": {"type": "int", "value": "22"}}, - "buffer": {"children": buffer_children}, + "buffer": {"children": buffer_children, "readOnly": True}, }, } @@ -622,11 +630,17 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): # "[raw]" child. raw_child_count = 1 if enableSyntheticChildDebugging else 0 verify_locals = { - "small_array": {"equals": {"indexedVariables": 5}}, - "large_array": {"equals": {"indexedVariables": 200}}, - "small_vector": {"equals": {"indexedVariables": 5 + raw_child_count}}, - "large_vector": {"equals": {"indexedVariables": 200 + raw_child_count}}, - "pt": {"missing": ["indexedVariables"]}, + "small_array": {"equals": {"indexedVariables": 5}, "readOnly": True}, + "large_array": {"equals": {"indexedVariables": 200}, "readOnly": True}, + "small_vector": { + "equals": {"indexedVariables": 5 + raw_child_count}, + "readOnly": True, + }, + "large_vector": { + "equals": {"indexedVariables": 200 + raw_child_count}, + "readOnly": True, + }, + "pt": {"missing": ["indexedVariables"], "readOnly": True}, } self.verify_variables(verify_locals, locals) @@ -640,7 +654,10 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): "[4]": {"equals": {"type": "int", "value": "0"}}, } if enableSyntheticChildDebugging: - verify_children["[raw]"] = ({"contains": {"type": ["vector"]}},) + verify_children["[raw]"] = { + "contains": {"type": ["vector"]}, + "readOnly": True, + } children = self.dap_server.request_variables(locals[2]["variablesReference"])[ "body" @@ -660,7 +677,7 @@ class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): return_name: {"equals": {"type": "int", "value": "300"}}, "argc": {}, "argv": {}, - "pt": {}, + "pt": {"readOnly": True}, "x": {}, "return_result": {"equals": {"type": "int"}}, } diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp index 7738913..e7d9b89 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp @@ -57,7 +57,7 @@ SetupIORedirection(const std::vector<std::optional<std::string>> &stdio, size_t n = std::max(stdio.size(), static_cast<size_t>(3)); for (size_t i = 0; i < n; i++) { std::optional<std::string> path; - if (stdio.size() < i) + if (stdio.size() <= i) path = stdio.back(); else path = stdio[i]; @@ -107,7 +107,7 @@ RunInTerminal(DAP &dap, const protocol::LaunchRequestArguments &arguments) { llvm::json::Object reverse_request = CreateRunInTerminalReverseRequest( arguments.configuration.program, arguments.args, arguments.env, - arguments.cwd, comm_file.m_path, debugger_pid, + arguments.cwd, comm_file.m_path, debugger_pid, arguments.stdio, arguments.console == protocol::eConsoleExternalTerminal); dap.SendReverseRequest<LogFailureResponseHandler>("runInTerminal", std::move(reverse_request)); diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 4f26599..71e91f8 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -866,7 +866,8 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit) { llvm::json::Object CreateRunInTerminalReverseRequest( llvm::StringRef program, const std::vector<std::string> &args, const llvm::StringMap<std::string> &env, llvm::StringRef cwd, - llvm::StringRef comm_file, lldb::pid_t debugger_pid, bool external) { + llvm::StringRef comm_file, lldb::pid_t debugger_pid, + const std::vector<std::optional<std::string>> &stdio, bool external) { llvm::json::Object run_in_terminal_args; if (external) { // This indicates the IDE to open an external terminal window. @@ -885,6 +886,18 @@ llvm::json::Object CreateRunInTerminalReverseRequest( } req_args.push_back("--launch-target"); req_args.push_back(program.str()); + if (!stdio.empty()) { + req_args.push_back("--stdio"); + std::stringstream ss; + for (const std::optional<std::string> &file : stdio) { + if (file) + ss << *file; + ss << ":"; + } + std::string files = ss.str(); + files.pop_back(); + req_args.push_back(std::move(files)); + } req_args.insert(req_args.end(), args.begin(), args.end()); run_in_terminal_args.try_emplace("args", req_args); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index e9094f6..0c865a3 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -388,6 +388,10 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit); /// launcher uses it on Linux tell the kernel that it should allow the /// debugger process to attach. /// +/// \param[in] stdio +/// An array of file paths for redirecting the program's standard IO +/// streams. +/// /// \param[in] external /// If set to true, the program will run in an external terminal window /// instead of IDE's integrated terminal. @@ -398,7 +402,8 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit); llvm::json::Object CreateRunInTerminalReverseRequest( llvm::StringRef program, const std::vector<std::string> &args, const llvm::StringMap<std::string> &env, llvm::StringRef cwd, - llvm::StringRef comm_file, lldb::pid_t debugger_pid, bool external); + llvm::StringRef comm_file, lldb::pid_t debugger_pid, + const std::vector<std::optional<std::string>> &stdio, bool external); /// Create a "Terminated" JSON object that contains statistics /// diff --git a/lldb/tools/lldb-dap/Options.td b/lldb/tools/lldb-dap/Options.td index c8492c6..5e9dd7a 100644 --- a/lldb/tools/lldb-dap/Options.td +++ b/lldb/tools/lldb-dap/Options.td @@ -47,6 +47,12 @@ def debugger_pid: S<"debugger-pid">, HelpText<"The PID of the lldb-dap instance that sent the launchInTerminal " "request when using --launch-target.">; +def stdio: S<"stdio">, + MetaVarName<"<stdin:stdout:stderr:...>">, + HelpText<"An array of file paths for redirecting the program's standard IO " + "streams. A colon-separated list of entries. Empty value means no " + "redirection.">; + def repl_mode : S<"repl-mode">, MetaVarName<"<mode>">, diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 92dada2..a85a68b 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -300,6 +300,7 @@ struct LaunchRequestArguments { /// terminal or external terminal. Console console = eConsoleInternal; + /// An array of file paths for redirecting the program's standard IO streams. std::vector<std::optional<std::string>> stdio; /// @} diff --git a/lldb/tools/lldb-dap/ProtocolUtils.cpp b/lldb/tools/lldb-dap/ProtocolUtils.cpp index 775c82f..868c67c 100644 --- a/lldb/tools/lldb-dap/ProtocolUtils.cpp +++ b/lldb/tools/lldb-dap/ProtocolUtils.cpp @@ -301,6 +301,14 @@ Variable CreateVariable(lldb::SBValue v, int64_t var_ref, bool format_hex, if (lldb::addr_t addr = v.GetLoadAddress(); addr != LLDB_INVALID_ADDRESS) var.memoryReference = addr; + bool is_readonly = v.GetType().IsAggregateType() || + v.GetValueType() == lldb::eValueTypeRegisterSet; + if (is_readonly) { + if (!var.presentationHint) + var.presentationHint = {VariablePresentationHint()}; + var.presentationHint->attributes.push_back("readOnly"); + } + return var; } diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index e961c2e..3f0f150 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -626,7 +626,10 @@ "stdio": { "type": "array", "items": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": "The stdio property specifies the redirection targets for the debuggee's stdio streams. A null value redirects a stream to the default debug terminal. String can be a path to file, named pipe or TTY device. If less than three values are provided, the list will be padded with the last value. Specifying more than three values will create additional file descriptors (4, 5, etc.).", "default": [] diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp b/lldb/tools/lldb-dap/tool/lldb-dap.cpp index 93446c0..45caa1a 100644 --- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp @@ -16,15 +16,19 @@ #include "lldb/API/SBStream.h" #include "lldb/Host/Config.h" #include "lldb/Host/File.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/MainLoop.h" #include "lldb/Host/MainLoopBase.h" #include "lldb/Host/MemoryMonitor.h" #include "lldb/Host/Socket.h" +#include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/UriParser.h" #include "lldb/lldb-forward.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/Arg.h" @@ -42,8 +46,10 @@ #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <condition_variable> +#include <cstddef> #include <cstdio> #include <cstdlib> +#include <exception> #include <fcntl.h> #include <map> #include <memory> @@ -69,6 +75,7 @@ typedef int socklen_t; #include <netinet/in.h> #include <sys/socket.h> #include <sys/un.h> +#include <termios.h> #include <unistd.h> #endif @@ -143,6 +150,74 @@ static void PrintVersion() { llvm::outs() << "liblldb: " << lldb::SBDebugger::GetVersionString() << '\n'; } +#if not defined(_WIN32) +struct FDGroup { + int GetFlags() const { + if (read && write) + return O_NOCTTY | O_CREAT | O_RDWR; + if (read) + return O_NOCTTY | O_RDONLY; + return O_NOCTTY | O_CREAT | O_WRONLY | O_TRUNC; + } + + std::vector<int> fds; + bool read = false; + bool write = false; +}; + +static llvm::Error RedirectToFile(const FDGroup &fdg, llvm::StringRef file) { + if (!fdg.read && !fdg.write) + return llvm::Error::success(); + int target_fd = lldb_private::FileSystem::Instance().Open( + file.str().c_str(), fdg.GetFlags(), 0666); + if (target_fd == -1) + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + for (int fd : fdg.fds) { + if (target_fd == fd) + continue; + if (::dup2(target_fd, fd) == -1) + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + } + ::close(target_fd); + return llvm::Error::success(); +} + +static llvm::Error +SetupIORedirection(const llvm::SmallVectorImpl<llvm::StringRef> &files) { + llvm::SmallDenseMap<llvm::StringRef, FDGroup> groups; + for (size_t i = 0; i < files.size(); i++) { + if (files[i].empty()) + continue; + auto group = groups.find(files[i]); + if (group == groups.end()) + group = groups.insert({files[i], {{static_cast<int>(i)}}}).first; + else + group->second.fds.push_back(i); + switch (i) { + case 0: + group->second.read = true; + break; + case 1: + case 2: + group->second.write = true; + break; + default: + group->second.read = true; + group->second.write = true; + break; + } + } + for (const auto &[file, group] : groups) { + if (llvm::Error err = RedirectToFile(group, file)) + return llvm::createStringError( + llvm::formatv("{0}: {1}", file, llvm::toString(std::move(err)))); + } + return llvm::Error::success(); +} +#endif + // If --launch-target is provided, this instance of lldb-dap becomes a // runInTerminal launcher. It will ultimately launch the program specified in // the --launch-target argument, which is the original program the user wanted @@ -165,6 +240,7 @@ static void PrintVersion() { static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg, llvm::StringRef comm_file, lldb::pid_t debugger_pid, + llvm::StringRef stdio, char *argv[]) { #if defined(_WIN32) return llvm::createStringError( @@ -179,6 +255,25 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg, (void)prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0); #endif + lldb_private::FileSystem::Initialize(); + if (!stdio.empty()) { + llvm::SmallVector<llvm::StringRef, 3> files; + stdio.split(files, ':'); + while (files.size() < 3) + files.push_back(files.back()); + if (llvm::Error err = SetupIORedirection(files)) + return err; + } else if ((isatty(STDIN_FILENO) != 0) && + llvm::StringRef(getenv("TERM")).starts_with_insensitive("xterm")) { + // Clear the screen. + llvm::outs() << ANSI_CSI_RESET_CURSOR ANSI_CSI_ERASE_VIEWPORT + ANSI_CSI_ERASE_SCROLLBACK; + // VS Code will reuse the same terminal for the same debug configuration + // between runs. Clear the input buffer prior to starting the new process so + // prior input is not carried forward to the new debug session. + tcflush(STDIN_FILENO, TCIFLUSH); + } + RunInTerminalLauncherCommChannel comm_channel(comm_file); if (llvm::Error err = comm_channel.NotifyPid()) return err; @@ -484,9 +579,10 @@ int main(int argc, char *argv[]) { break; } } + llvm::StringRef stdio = input_args.getLastArgValue(OPT_stdio); if (llvm::Error err = LaunchRunInTerminalTarget(*target_arg, comm_file->getValue(), pid, - argv + target_args_pos)) { + stdio, argv + target_args_pos)) { llvm::errs() << llvm::toString(std::move(err)) << '\n'; return EXIT_FAILURE; } diff --git a/lldb/unittests/Utility/XcodeSDKTest.cpp b/lldb/unittests/Utility/XcodeSDKTest.cpp index de9f91a..a8a597b 100644 --- a/lldb/unittests/Utility/XcodeSDKTest.cpp +++ b/lldb/unittests/Utility/XcodeSDKTest.cpp @@ -27,6 +27,7 @@ TEST(XcodeSDKTest, ParseTest) { EXPECT_EQ(XcodeSDK("AppleTVOS.sdk").GetType(), XcodeSDK::AppleTVOS); EXPECT_EQ(XcodeSDK("WatchSimulator.sdk").GetType(), XcodeSDK::WatchSimulator); EXPECT_EQ(XcodeSDK("WatchOS.sdk").GetType(), XcodeSDK::watchOS); + EXPECT_EQ(XcodeSDK("BridgeOS.sdk").GetType(), XcodeSDK::BridgeOS); EXPECT_EQ(XcodeSDK("XRSimulator.sdk").GetType(), XcodeSDK::XRSimulator); EXPECT_EQ(XcodeSDK("XROS.sdk").GetType(), XcodeSDK::XROS); EXPECT_EQ(XcodeSDK("Linux.sdk").GetType(), XcodeSDK::Linux); diff --git a/lldb/utils/lui/lldbutil.py b/lldb/utils/lui/lldbutil.py index 140317a..589acae 100644 --- a/lldb/utils/lui/lldbutil.py +++ b/lldb/utils/lui/lldbutil.py @@ -951,7 +951,7 @@ def get_GPRs(frame): from lldbutil import get_GPRs regs = get_GPRs(frame) for reg in regs: - print "%s => %s" % (reg.GetName(), reg.GetValue()) + print("%s => %s" % (reg.GetName(), reg.GetValue())) ... """ return get_registers(frame, "general purpose") @@ -965,7 +965,7 @@ def get_FPRs(frame): from lldbutil import get_FPRs regs = get_FPRs(frame) for reg in regs: - print "%s => %s" % (reg.GetName(), reg.GetValue()) + print("%s => %s" % (reg.GetName(), reg.GetValue())) ... """ return get_registers(frame, "floating point") |