diff options
Diffstat (limited to 'lldb')
20 files changed, 301 insertions, 130 deletions
diff --git a/lldb/cmake/modules/LLDBFramework.cmake b/lldb/cmake/modules/LLDBFramework.cmake index c6f00ed..23d9d49 100644 --- a/lldb/cmake/modules/LLDBFramework.cmake +++ b/lldb/cmake/modules/LLDBFramework.cmake @@ -68,8 +68,6 @@ if(NOT APPLE_EMBEDDED) ) endif() -find_program(unifdef_EXECUTABLE unifdef) - # Wrap output in a target, so lldb-framework can depend on it. add_custom_target(liblldb-resource-headers DEPENDS lldb-sbapi-dwarf-enums ${lldb_staged_headers}) set_target_properties(liblldb-resource-headers PROPERTIES FOLDER "LLDB/Resources") diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index fec9fde..1a7db8f 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -130,6 +130,8 @@ FLAGS_ENUM(LaunchFlags){ eLaunchFlagInheritTCCFromParent = (1u << 12), ///< Don't make the inferior responsible for its own TCC ///< permissions but instead inherit them from its parent. + eLaunchFlagMemoryTagging = + (1u << 13), ///< Launch process with memory tagging explicitly enabled. }; /// Thread Run Modes. diff --git a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py index 53e991a..1a2860a 100644 --- a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py +++ b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py @@ -1,3 +1,4 @@ +from abc import ABC, abstractmethod import ctypes import errno import io @@ -5,6 +6,7 @@ import threading import socket import traceback from lldbsuite.support import seven +from typing import Optional, List, Tuple def checksum(message): @@ -86,7 +88,7 @@ class MockGDBServerResponder: handles any packet not recognized in the common packet handling code. """ - registerCount = 40 + registerCount: int = 40 class RESPONSE_DISCONNECT: pass @@ -95,7 +97,7 @@ class MockGDBServerResponder: pass def __init__(self): - self.packetLog = [] + self.packetLog: List[str] = [] def respond(self, packet): """ @@ -241,7 +243,7 @@ class MockGDBServerResponder: def qHostInfo(self): return "ptrsize:8;endian:little;" - def qEcho(self): + def qEcho(self, num: int): return "E04" def qQueryGDBServer(self): @@ -262,10 +264,10 @@ class MockGDBServerResponder: def D(self, packet): return "OK" - def readRegisters(self): + def readRegisters(self) -> str: return "00000000" * self.registerCount - def readRegister(self, register): + def readRegister(self, register: int) -> str: return "00000000" def writeRegisters(self, registers_hex): @@ -305,7 +307,9 @@ class MockGDBServerResponder: # SIGINT is 2, return type is 2 digit hex string return "S02" - def qXferRead(self, obj, annex, offset, length): + def qXferRead( + self, obj: str, annex: str, offset: int, length: int + ) -> Tuple[Optional[str], bool]: return None, False def _qXferResponse(self, data, has_more): @@ -373,15 +377,17 @@ class MockGDBServerResponder: pass -class ServerChannel: +class ServerChannel(ABC): """ A wrapper class for TCP or pty-based server. """ - def get_connect_address(self): + @abstractmethod + def get_connect_address(self) -> str: """Get address for the client to connect to.""" - def get_connect_url(self): + @abstractmethod + def get_connect_url(self) -> str: """Get URL suitable for process connect command.""" def close_server(self): @@ -393,10 +399,12 @@ class ServerChannel: def close_connection(self): """Close all resources used by the accepted connection.""" - def recv(self): + @abstractmethod + def recv(self) -> bytes: """Receive a data packet from the connected client.""" - def sendall(self, data): + @abstractmethod + def sendall(self, data: bytes) -> None: """Send the data to the connected client.""" @@ -427,11 +435,11 @@ class ServerSocket(ServerChannel): self._connection.close() self._connection = None - def recv(self): + def recv(self) -> bytes: assert self._connection is not None return self._connection.recv(4096) - def sendall(self, data): + def sendall(self, data: bytes) -> None: assert self._connection is not None return self._connection.sendall(data) @@ -443,10 +451,10 @@ class TCPServerSocket(ServerSocket): )[0] super().__init__(family, type, proto, addr) - def get_connect_address(self): + def get_connect_address(self) -> str: return "[{}]:{}".format(*self._server_socket.getsockname()) - def get_connect_url(self): + def get_connect_url(self) -> str: return "connect://" + self.get_connect_address() @@ -454,10 +462,10 @@ class UnixServerSocket(ServerSocket): def __init__(self, addr): super().__init__(socket.AF_UNIX, socket.SOCK_STREAM, 0, addr) - def get_connect_address(self): + def get_connect_address(self) -> str: return self._server_socket.getsockname() - def get_connect_url(self): + def get_connect_url(self) -> str: return "unix-connect://" + self.get_connect_address() @@ -471,7 +479,7 @@ class PtyServerSocket(ServerChannel): self._primary = io.FileIO(primary, "r+b") self._secondary = io.FileIO(secondary, "r+b") - def get_connect_address(self): + def get_connect_address(self) -> str: libc = ctypes.CDLL(None) libc.ptsname.argtypes = (ctypes.c_int,) libc.ptsname.restype = ctypes.c_char_p @@ -484,7 +492,7 @@ class PtyServerSocket(ServerChannel): self._secondary.close() self._primary.close() - def recv(self): + def recv(self) -> bytes: try: return self._primary.read(4096) except OSError as e: @@ -493,8 +501,8 @@ class PtyServerSocket(ServerChannel): return b"" raise - def sendall(self, data): - return self._primary.write(data) + def sendall(self, data: bytes) -> None: + self._primary.write(data) class MockGDBServer: @@ -527,18 +535,21 @@ class MockGDBServer: self._thread.join() self._thread = None - def get_connect_address(self): + def get_connect_address(self) -> str: + assert self._socket is not None return self._socket.get_connect_address() - def get_connect_url(self): + def get_connect_url(self) -> str: + assert self._socket is not None return self._socket.get_connect_url() def run(self): + assert self._socket is not None # For testing purposes, we only need to worry about one client # connecting just one time. try: self._socket.accept() - except: + except Exception: traceback.print_exc() return self._shouldSendAck = True @@ -553,7 +564,7 @@ class MockGDBServer: self._receive(data) except self.TerminateConnectionException: pass - except Exception as e: + except Exception: print( "An exception happened when receiving the response from the gdb server. Closing the client..." ) @@ -586,7 +597,9 @@ class MockGDBServer: Once a complete packet is found at the front of self._receivedData, its data is removed form self._receivedData. """ + assert self._receivedData is not None data = self._receivedData + assert self._receivedDataOffset is not None i = self._receivedDataOffset data_len = len(data) if data_len == 0: @@ -639,10 +652,13 @@ class MockGDBServer: self._receivedDataOffset = 0 return packet - def _sendPacket(self, packet): - self._socket.sendall(seven.bitcast_to_bytes(frame_packet(packet))) + def _sendPacket(self, packet: str): + assert self._socket is not None + framed_packet = seven.bitcast_to_bytes(frame_packet(packet)) + self._socket.sendall(framed_packet) def _handlePacket(self, packet): + assert self._socket is not None if packet is self.PACKET_ACK: # Ignore ACKs from the client. For the future, we can consider # adding validation code to make sure the client only sends ACKs diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp index 21d94d6..8ae20bd 100644 --- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp +++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp @@ -127,6 +127,10 @@ Status CommandOptionsProcessLaunch::SetOptionValue( break; } + case 'M': + launch_info.GetFlags().Set(eLaunchFlagMemoryTagging); + break; + case 'c': if (!option_arg.empty()) launch_info.SetShell(FileSpec(option_arg)); diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 595b3d0..a9f054e 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -1173,6 +1173,11 @@ let Command = "process launch" in { Arg<"Boolean">, Desc<"Set whether to shell expand arguments to the process when " "launching.">; + def process_launch_memory_tagging + : Option<"memory-tagging", "M">, + Desc<"Set whether to explicitly enable memory tagging when launching " + "the process. Requires hardware support. " + "(Only supported on Darwin.)">; } let Command = "process attach" in { diff --git a/lldb/source/Host/freebsd/Host.cpp b/lldb/source/Host/freebsd/Host.cpp index fa7efad..dfdbfea 100644 --- a/lldb/source/Host/freebsd/Host.cpp +++ b/lldb/source/Host/freebsd/Host.cpp @@ -18,8 +18,6 @@ #include <dlfcn.h> #include <execinfo.h> -#include "llvm/Object/ELF.h" - #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -32,6 +30,7 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Object/ELF.h" #include "llvm/TargetParser/Host.h" namespace lldb_private { diff --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm index 3c1d117..7120892 100644 --- a/lldb/source/Host/macosx/objcxx/Host.mm +++ b/lldb/source/Host/macosx/objcxx/Host.mm @@ -1210,6 +1210,39 @@ static Status LaunchProcessPosixSpawn(const char *exe_path, } } + if (launch_info.GetFlags().Test(eLaunchFlagMemoryTagging)) { + // The following function configures the spawn attributes to launch the + // process with memory tagging explicitly enabled. We look it up + // dynamically since it is only available on newer OS. Does nothing on + // hardware which does not support MTE. + // + // int posix_spawnattr_set_use_sec_transition_shims_np( + // posix_spawnattr_t *attr, uint32_t flags); + // + 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 = + (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 (error.Fail()) { + LLDB_LOG(log, + "error: {0}, " + "posix_spawnattr_set_use_sec_transition_shims_np(&attr, 0)", + error); + return error; + } + } else { + LLDB_LOG(log, + "error: posix_spawnattr_set_use_sec_transition_shims_np not " + "available", + error); + } + } + // Don't set the binpref if a shell was provided. After all, that's only // going to affect what version of the shell is launched, not what fork of // the binary is launched. We insert "arch --arch <ARCH> as part of the diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp index c0b1079..9b7df10 100644 --- a/lldb/source/Host/windows/MainLoopWindows.cpp +++ b/lldb/source/Host/windows/MainLoopWindows.cpp @@ -55,11 +55,7 @@ public: if (m_monitor_thread.joinable()) { m_stopped = true; SetEvent(m_ready); - // Keep trying to cancel ReadFile() until the thread exits. - do { - CancelIoEx(m_handle, /*lpOverlapped=*/NULL); - } while (WaitForSingleObject(m_monitor_thread.native_handle(), 1) == - WAIT_TIMEOUT); + CancelIoEx(m_handle, /*lpOverlapped=*/NULL); m_monitor_thread.join(); } CloseHandle(m_event); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 4b183a8..5588208 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -52,7 +52,7 @@ private: ValueObject *m_tree = nullptr; size_t m_num_elements = 0; ValueObject *m_next_element = nullptr; - std::vector<std::pair<ValueObject *, uint64_t>> m_elements_cache; + std::vector<ValueObject *> m_elements_cache; }; class LibCxxUnorderedMapIteratorSyntheticFrontEnd @@ -192,26 +192,25 @@ lldb::ValueObjectSP lldb_private::formatters:: return nullptr; } } - m_elements_cache.push_back( - {value_sp.get(), hash_sp->GetValueAsUnsigned(0)}); + m_elements_cache.push_back(value_sp.get()); m_next_element = node_sp->GetChildMemberWithName("__next_").get(); if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0) m_next_element = nullptr; } - std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx]; - if (!val_hash.first) + ValueObject *val_hash = m_elements_cache[idx]; + if (!val_hash) return lldb::ValueObjectSP(); StreamString stream; stream.Printf("[%" PRIu64 "]", (uint64_t)idx); DataExtractor data; Status error; - val_hash.first->GetData(data, error); + val_hash->GetData(data, error); if (error.Fail()) return lldb::ValueObjectSP(); const bool thread_and_frame_only_if_stopped = true; - ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock( - thread_and_frame_only_if_stopped); + ExecutionContext exe_ctx = + val_hash->GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped); return CreateValueObjectFromData(stream.GetString(), data, exe_ctx, m_element_type); } diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp index c871861..020ba1016 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlAtomic.cpp @@ -50,7 +50,7 @@ llvm::Expected<uint32_t> lldb_private::formatters:: lldb::ValueObjectSP lldb_private::formatters::MsvcStlAtomicSyntheticFrontEnd::GetChildAtIndex( uint32_t idx) { - if (idx == 0) + if (idx == 0 && m_storage && m_element_type.IsValid()) return m_storage->Cast(m_element_type)->Clone(ConstString("Value")); return nullptr; } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index cc0c9e7..6d8f41a 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -14,6 +14,7 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/lldb-enumerations.h" +#include "llvm/ADT/Sequence.h" using namespace lldb; using namespace lldb_private; @@ -266,22 +267,47 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process, return true; } -bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr, - lldb::addr_t relative_selector_base_addr, - bool is_small, bool has_direct_sel) { - size_t ptr_size = process->GetAddressByteSize(); - size_t size = GetSize(process, is_small); +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_private::Process *process = m_runtime.GetProcess(); + if (!process) + return {}; - DataBufferHeap buffer(size, '\0'); - Status error; + const size_t size = method_t::GetSize(process, is_small); + const size_t num_methods = addresses.size(); - process->ReadMemory(addr, buffer.GetBytes(), size, error); - if (error.Fail()) { - return false; + llvm::SmallVector<uint8_t, 0> buffer(num_methods * size, 0); + llvm::DenseSet<uint32_t> failed_indices; + + for (auto [idx, addr] : llvm::enumerate(addresses)) { + Status error; + process->ReadMemory(addr, buffer.data() + idx * size, size, error); + if (error.Fail()) + failed_indices.insert(idx); } - DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), - ptr_size); + llvm::SmallVector<method_t, 0> methods; + methods.reserve(num_methods); + for (auto [idx, addr] : llvm::enumerate(addresses)) { + if (failed_indices.contains(idx)) + continue; + DataExtractor extractor(buffer.data() + idx * size, size, + process->GetByteOrder(), + process->GetAddressByteSize()); + methods.push_back(method_t()); + methods.back().Read(extractor, process, addr, relative_selector_base_addr, + is_small, has_direct_sel); + } + + return methods; +} + +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::offset_t cursor = 0; if (is_small) { @@ -291,11 +317,11 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr, m_name_ptr = addr + nameref_offset; + Status error; if (!has_direct_sel) { // The SEL offset points to a SELRef. We need to dereference twice. - m_name_ptr = process->ReadUnsignedIntegerFromMemory(m_name_ptr, ptr_size, - 0, error); - if (!error.Success()) + 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; @@ -308,13 +334,13 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr, m_imp_ptr = extractor.GetAddress_unchecked(&cursor); } + Status error; process->ReadCStringFromMemory(m_name_ptr, m_name, error); - if (error.Fail()) { + if (error.Fail()) return false; - } process->ReadCStringFromMemory(m_types_ptr, m_types, error); - return !error.Fail(); + return error.Success(); } bool ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr) { @@ -447,17 +473,19 @@ ClassDescriptorV2::GetMethodList(Process *process, bool ClassDescriptorV2::ProcessMethodList( std::function<bool(const char *, const char *)> const &instance_method_func, ClassDescriptorV2::method_list_t &method_list) const { - lldb_private::Process *process = m_runtime.GetProcess(); - auto method = std::make_unique<method_t>(); - lldb::addr_t relative_selector_base_addr = - m_runtime.GetRelativeSelectorBaseAddr(); - for (uint32_t i = 0, e = method_list.m_count; i < e; ++i) { - method->Read(process, method_list.m_first_ptr + (i * method_list.m_entsize), - relative_selector_base_addr, method_list.m_is_small, - method_list.m_has_direct_selector); - if (instance_method_func(method->m_name.c_str(), method->m_types.c_str())) + auto idx_to_method_addr = [&](uint32_t idx) { + return method_list.m_first_ptr + (idx * method_list.m_entsize); + }; + llvm::SmallVector<addr_t> addresses = llvm::to_vector(llvm::map_range( + llvm::seq<uint32_t>(method_list.m_count), idx_to_method_addr)); + + llvm::SmallVector<method_t, 0> methods = + ReadMethods(addresses, m_runtime.GetRelativeSelectorBaseAddr(), + method_list.m_is_small, method_list.m_has_direct_selector); + + for (const auto &method : methods) + if (instance_method_func(method.m_name.c_str(), method.m_types.c_str())) break; - } return true; } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h index 920a5eb..78b3311 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h @@ -172,11 +172,16 @@ private: + field_size; // IMP imp; } - bool Read(Process *process, lldb::addr_t addr, + bool Read(DataExtractor &extractor, Process *process, lldb::addr_t addr, lldb::addr_t relative_selector_base_addr, bool is_small, bool has_direct_sel); }; + 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; + struct ivar_list_t { uint32_t m_entsize; uint32_t m_count; diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp index e0f3971..c361b2a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp @@ -9,6 +9,7 @@ #include "RegisterContextFreeBSD_x86_64.h" #include "RegisterContextFreeBSD_i386.h" #include "RegisterContextPOSIX_x86.h" +#include "llvm/Support/Threading.h" #include <vector> using namespace lldb_private; @@ -69,40 +70,34 @@ struct UserArea { #include "RegisterInfos_x86_64.h" #undef DECLARE_REGISTER_INFOS_X86_64_STRUCT -static std::vector<lldb_private::RegisterInfo> &GetSharedRegisterInfoVector() { - static std::vector<lldb_private::RegisterInfo> register_infos; - return register_infos; -} - -static const RegisterInfo * -GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) { - static std::vector<lldb_private::RegisterInfo> g_register_infos( - GetSharedRegisterInfoVector()); - - // Allocate RegisterInfo only once - if (g_register_infos.empty()) { - // Copy the register information from base class - std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface( - new RegisterContextFreeBSD_i386(arch)); - const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); - g_register_infos.insert(g_register_infos.end(), &base_info[0], - &base_info[k_num_registers_i386]); +static std::vector<lldb_private::RegisterInfo> & +GetSharedRegisterInfoVector_i386(const lldb_private::ArchSpec &arch) { + static std::vector<lldb_private::RegisterInfo> g_register_infos; + static llvm::once_flag g_initialized; + llvm::call_once(g_initialized, [&]() { + if (g_register_infos.empty()) { + // Copy the register information from base class + std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface( + new RegisterContextFreeBSD_i386(arch)); + const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); + g_register_infos.insert(g_register_infos.end(), &base_info[0], + &base_info[k_num_registers_i386]); // Include RegisterInfos_x86_64 to update the g_register_infos structure // with x86_64 offsets. #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS #include "RegisterInfos_x86_64.h" #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS - } - - return &g_register_infos[0]; + } + }); + return g_register_infos; } static const RegisterInfo * PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { case llvm::Triple::x86: - return GetRegisterInfo_i386(target_arch); + return &GetSharedRegisterInfoVector_i386(target_arch)[0]; case llvm::Triple::x86_64: return g_register_infos_x86_64; default: @@ -116,9 +111,10 @@ PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { case llvm::Triple::x86: // This vector should have already been filled. - assert(!GetSharedRegisterInfoVector().empty() && + assert(!GetSharedRegisterInfoVector_i386(target_arch).empty() && "i386 register info vector not filled."); - return static_cast<uint32_t>(GetSharedRegisterInfoVector().size()); + return static_cast<uint32_t>( + GetSharedRegisterInfoVector_i386(target_arch).size()); case llvm::Triple::x86_64: return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 888bd89..6c66d86 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -946,17 +946,21 @@ lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::Complex64: return lldb::eBasicTypeDoubleComplex; case SimpleTypeKind::Complex32: + case SimpleTypeKind::Complex32PartialPrecision: return lldb::eBasicTypeFloatComplex; - case SimpleTypeKind::Float128: case SimpleTypeKind::Float80: return lldb::eBasicTypeLongDouble; + case SimpleTypeKind::Float128: + return lldb::eBasicTypeFloat128; case SimpleTypeKind::Float64: return lldb::eBasicTypeDouble; case SimpleTypeKind::Float32: + case SimpleTypeKind::Float32PartialPrecision: return lldb::eBasicTypeFloat; case SimpleTypeKind::Float16: return lldb::eBasicTypeHalf; case SimpleTypeKind::Int128: + case SimpleTypeKind::Int128Oct: return lldb::eBasicTypeInt128; case SimpleTypeKind::Int64: case SimpleTypeKind::Int64Quad: @@ -967,6 +971,7 @@ lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::Int16Short: return lldb::eBasicTypeShort; case SimpleTypeKind::UInt128: + case SimpleTypeKind::UInt128Oct: return lldb::eBasicTypeUnsignedInt128; case SimpleTypeKind::UInt64: case SimpleTypeKind::UInt64Quad: @@ -985,16 +990,27 @@ lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) { return lldb::eBasicTypeVoid; case SimpleTypeKind::WideCharacter: return lldb::eBasicTypeWChar; - default: + + // Not supported. + case SimpleTypeKind::Float48: + case SimpleTypeKind::Complex16: + case SimpleTypeKind::Complex48: + case SimpleTypeKind::Complex128: + case SimpleTypeKind::NotTranslated: + case SimpleTypeKind::None: return lldb::eBasicTypeInvalid; } + return lldb::eBasicTypeInvalid; } size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { switch (kind) { case SimpleTypeKind::Boolean128: + case SimpleTypeKind::Complex128: case SimpleTypeKind::Int128: + case SimpleTypeKind::Int128Oct: case SimpleTypeKind::UInt128: + case SimpleTypeKind::UInt128Oct: case SimpleTypeKind::Float128: return 16; case SimpleTypeKind::Complex80: @@ -1008,10 +1024,15 @@ size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::Int64: case SimpleTypeKind::Int64Quad: return 8; + case SimpleTypeKind::Complex48: + case SimpleTypeKind::Float48: + return 6; case SimpleTypeKind::Boolean32: case SimpleTypeKind::Character32: case SimpleTypeKind::Complex32: + case SimpleTypeKind::Complex32PartialPrecision: case SimpleTypeKind::Float32: + case SimpleTypeKind::Float32PartialPrecision: case SimpleTypeKind::Int32: case SimpleTypeKind::Int32Long: case SimpleTypeKind::UInt32Long: @@ -1020,6 +1041,7 @@ size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { return 4; case SimpleTypeKind::Boolean16: case SimpleTypeKind::Character16: + case SimpleTypeKind::Complex16: case SimpleTypeKind::Float16: case SimpleTypeKind::Int16: case SimpleTypeKind::Int16Short: @@ -1035,10 +1057,13 @@ size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) { case SimpleTypeKind::SByte: case SimpleTypeKind::Character8: return 1; + case SimpleTypeKind::Void: - default: + case SimpleTypeKind::None: + case SimpleTypeKind::NotTranslated: return 0; } + return 0; } PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 7e275f1..ecd3188 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -152,14 +152,24 @@ static bool IsFunctionEpilogue(const CompilandIndexItem &cci, return false; } +// See llvm::codeview::TypeIndex::simpleTypeName as well as strForPrimitiveTi +// from the original pdbdump: +// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/pdbdump/pdbdump.cpp#L1896-L1974 +// +// For 64bit integers we use "long long" like DIA instead of "__int64". static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) { switch (kind) { case SimpleTypeKind::Boolean128: - case SimpleTypeKind::Boolean16: - case SimpleTypeKind::Boolean32: + return "__bool128"; case SimpleTypeKind::Boolean64: + return "__bool64"; + case SimpleTypeKind::Boolean32: + return "__bool32"; + case SimpleTypeKind::Boolean16: + return "__bool16"; case SimpleTypeKind::Boolean8: return "bool"; + case SimpleTypeKind::Byte: case SimpleTypeKind::UnsignedCharacter: return "unsigned char"; @@ -168,57 +178,81 @@ static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) { case SimpleTypeKind::SignedCharacter: case SimpleTypeKind::SByte: return "signed char"; - case SimpleTypeKind::Character16: - return "char16_t"; case SimpleTypeKind::Character32: return "char32_t"; + case SimpleTypeKind::Character16: + return "char16_t"; case SimpleTypeKind::Character8: return "char8_t"; + + case SimpleTypeKind::Complex128: + return "_Complex __float128"; case SimpleTypeKind::Complex80: + return "_Complex long double"; case SimpleTypeKind::Complex64: + return "_Complex double"; + case SimpleTypeKind::Complex48: + return "_Complex __float48"; case SimpleTypeKind::Complex32: - return "complex"; + case SimpleTypeKind::Complex32PartialPrecision: + return "_Complex float"; + case SimpleTypeKind::Complex16: + return "_Complex _Float16"; + case SimpleTypeKind::Float128: + return "__float128"; case SimpleTypeKind::Float80: return "long double"; case SimpleTypeKind::Float64: return "double"; + case SimpleTypeKind::Float48: + return "__float48"; case SimpleTypeKind::Float32: + case SimpleTypeKind::Float32PartialPrecision: return "float"; case SimpleTypeKind::Float16: - return "single"; + return "_Float16"; + + case SimpleTypeKind::Int128Oct: case SimpleTypeKind::Int128: return "__int128"; case SimpleTypeKind::Int64: case SimpleTypeKind::Int64Quad: - return "int64_t"; + return "long long"; + case SimpleTypeKind::Int32Long: + return "long"; case SimpleTypeKind::Int32: return "int"; case SimpleTypeKind::Int16: + case SimpleTypeKind::Int16Short: return "short"; + + case SimpleTypeKind::UInt128Oct: case SimpleTypeKind::UInt128: return "unsigned __int128"; case SimpleTypeKind::UInt64: case SimpleTypeKind::UInt64Quad: - return "uint64_t"; - case SimpleTypeKind::HResult: - return "HRESULT"; + return "unsigned long long"; case SimpleTypeKind::UInt32: return "unsigned"; case SimpleTypeKind::UInt16: case SimpleTypeKind::UInt16Short: return "unsigned short"; - case SimpleTypeKind::Int32Long: - return "long"; case SimpleTypeKind::UInt32Long: return "unsigned long"; + + case SimpleTypeKind::HResult: + return "HRESULT"; case SimpleTypeKind::Void: return "void"; case SimpleTypeKind::WideCharacter: return "wchar_t"; - default: + + case SimpleTypeKind::None: + case SimpleTypeKind::NotTranslated: return ""; } + return ""; } static bool IsClassRecord(TypeLeafKind kind) { @@ -598,8 +632,8 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false)); if (ti == TypeIndex::NullptrT()) { Declaration decl; - return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, + return MakeType(uid, ConstString("decltype(nullptr)"), std::nullopt, + nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); } diff --git a/lldb/test/API/macosx/mte/Makefile b/lldb/test/API/macosx/mte/Makefile index cb20942..d614e0f 100644 --- a/lldb/test/API/macosx/mte/Makefile +++ b/lldb/test/API/macosx/mte/Makefile @@ -1,12 +1,15 @@ C_SOURCES := main.c -EXE := uaf_mte +EXE := uaf -all: uaf_mte sign +binary-plain: uaf +binary-entitled: uaf sign + +all: binary-entitled include Makefile.rules -sign: mte-entitlements.plist uaf_mte +sign: mte-entitlements.plist uaf ifeq ($(OS),Darwin) codesign -s - -f --entitlements $^ endif diff --git a/lldb/test/API/macosx/mte/TestDarwinMTE.py b/lldb/test/API/macosx/mte/TestDarwinMTE.py index 489e24a..a70b4b4 100644 --- a/lldb/test/API/macosx/mte/TestDarwinMTE.py +++ b/lldb/test/API/macosx/mte/TestDarwinMTE.py @@ -7,13 +7,25 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil import lldbsuite.test.cpu_feature as cpu_feature -exe_name = "uaf_mte" # Must match Makefile +exe_name = "uaf" # Must match Makefile class TestDarwinMTE(TestBase): NO_DEBUG_INFO_TESTCASE = True @skipUnlessFeature(cpu_feature.AArch64.MTE) + def test_process_launch_memory_tagging(self): + self.build(make_targets=["binary-plain"]) + self.createTestTarget(self.getBuildArtifact(exe_name)) + + self.expect("process launch", substrs=["exited with status = 0"]) + + self.expect( + "process launch --memory-tagging", + substrs=["stopped", "stop reason = EXC_ARM_MTE_TAG_FAULT"], + ) + + @skipUnlessFeature(cpu_feature.AArch64.MTE) def test_tag_fault(self): self.build() exe = self.getBuildArtifact(exe_name) diff --git a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py index 08c225b..6008a0c 100644 --- a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py +++ b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py @@ -29,7 +29,7 @@ class TestDAP_stackTraceMissingSourcePath(lldbdap_testcase.DAPTestCaseBase): """ Build the program and run until the breakpoint is hit, and return the stack frames. """ - other_source_file = "other.c" + other_source_file = self.getBuildArtifact("other.c") with delete_file_on_exit(other_source_file): with open(other_source_file, "w") as f: f.write(OTHER_C_SOURCE_CODE) @@ -169,3 +169,4 @@ class TestDAP_stackTraceMissingSourcePath(lldbdap_testcase.DAPTestCaseBase): self.verify_frames_source( frames, main_frame_assembly=False, other_frame_assembly=False ) + self.continue_to_exit() diff --git a/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s index fe2f397..b44b99a 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s +++ b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s @@ -578,12 +578,12 @@ main: # @main # CHECK: (lldb) image lookup -a 0x14000104e -v # CHECK: LineEntry: [0x000000014000104e-0x0000000140001050): C:\src\test\a.cpp:1004 # CHECK-NEXT: Symbol: id = {{.*}}, range = [0x0000000140001011-0x0000000140001050), name="main" -# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "int64_t", valid ranges = <block>, location = [0x000000014000104e, 0x000000014000104f) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_reg24 XMM7, DW_OP_piece 0x4 +# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "long long", valid ranges = <block>, location = [0x000000014000104e, 0x000000014000104f) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_reg24 XMM7, DW_OP_piece 0x4 # CHECK-EMPTY: # CHECK: (lldb) image lookup -a 0x14000104f -v # CHECK: LineEntry: [0x000000014000104e-0x0000000140001050): C:\src\test\a.cpp:1004 # CHECK-NEXT: Symbol: id = {{.*}}, range = [0x0000000140001011-0x0000000140001050), name="main" -# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "int64_t", valid ranges = <block>, location = [0x000000014000104f, 0x0000000140001050) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_piece 0x4 +# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "long long", valid ranges = <block>, location = [0x000000014000104f, 0x0000000140001050) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_piece 0x4 # CHECK-EMPTY: .Ltmp26: diff --git a/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp index 403cd29..3781194 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/simple-types.cpp @@ -58,20 +58,28 @@ int main() { MyStruct my_struct; + _Float16 f16; + + _Complex float cf; + _Complex double cd; + + __int128 i128; + unsigned __int128 ui128; + decltype(nullptr) np; } -// CHECK-DAG: Type{{.*}} , name = "std::nullptr_t", size = 0, compiler_type = 0x{{[0-9a-f]+}} nullptr_t +// CHECK-DAG: Type{{.*}} , name = "decltype(nullptr)", compiler_type = 0x{{[0-9a-f]+}} nullptr_t // CHECK-DAG: Type{{.*}} , name = "bool", size = 1, compiler_type = 0x{{[0-9a-f]+}} _Bool // CHECK-DAG: Type{{.*}} , name = "char", size = 1, compiler_type = 0x{{[0-9a-f]+}} char // CHECK-DAG: Type{{.*}} , name = "unsigned char", size = 1, compiler_type = 0x{{[0-9a-f]+}} unsigned char // CHECK-DAG: Type{{.*}} , name = "char8_t", size = 1, compiler_type = 0x{{[0-9a-f]+}} char8_t -// CHECK-DAG: Type{{.*}} , size = 2, compiler_type = 0x{{[0-9a-f]+}} short -// CHECK-DAG: Type{{.*}} , name = "const volatile ", size = 2, compiler_type = 0x{{[0-9a-f]+}} const volatile short -// CHECK-DAG: Type{{.*}} , name = "const ", size = 2, compiler_type = 0x{{[0-9a-f]+}} const short -// CHECK-DAG: Type{{.*}} , name = "volatile ", size = 2, compiler_type = 0x{{[0-9a-f]+}} volatile short +// CHECK-DAG: Type{{.*}} , name = "short", size = 2, compiler_type = 0x{{[0-9a-f]+}} short +// CHECK-DAG: Type{{.*}} , name = "const volatile short", size = 2, compiler_type = 0x{{[0-9a-f]+}} const volatile short +// CHECK-DAG: Type{{.*}} , name = "const short", size = 2, compiler_type = 0x{{[0-9a-f]+}} const short +// CHECK-DAG: Type{{.*}} , name = "volatile short", size = 2, compiler_type = 0x{{[0-9a-f]+}} volatile short // CHECK-DAG: Type{{.*}} , name = "unsigned short", size = 2, compiler_type = 0x{{[0-9a-f]+}} unsigned short // CHECK-DAG: Type{{.*}} , name = "wchar_t", size = 2, compiler_type = 0x{{[0-9a-f]+}} wchar_t @@ -83,12 +91,19 @@ int main() { // CHECK-DAG: Type{{.*}} , name = "unsigned long", size = 4, compiler_type = 0x{{[0-9a-f]+}} unsigned long // CHECK-DAG: Type{{.*}} , name = "char32_t", size = 4, compiler_type = 0x{{[0-9a-f]+}} char32_t -// CHECK-DAG: Type{{.*}} , name = "int64_t", size = 8, compiler_type = 0x{{[0-9a-f]+}} long long -// CHECK-DAG: Type{{.*}} , name = "uint64_t", size = 8, compiler_type = 0x{{[0-9a-f]+}} unsigned long long +// CHECK-DAG: Type{{.*}} , name = "long long", size = 8, compiler_type = 0x{{[0-9a-f]+}} long long +// CHECK-DAG: Type{{.*}} , name = "unsigned long long", size = 8, compiler_type = 0x{{[0-9a-f]+}} unsigned long long +// CHECK-DAG: Type{{.*}} , name = "__int128", size = 16, compiler_type = 0x{{[0-9a-f]+}} __int128 +// CHECK-DAG: Type{{.*}} , name = "unsigned __int128", size = 16, compiler_type = 0x{{[0-9a-f]+}} unsigned __int128 + +// CHECK-DAG: Type{{.*}} , name = "_Float16", size = 2, compiler_type = 0x{{[0-9a-f]+}} __fp16 // CHECK-DAG: Type{{.*}} , name = "float", size = 4, compiler_type = 0x{{[0-9a-f]+}} float // CHECK-DAG: Type{{.*}} , name = "const float", size = 4, compiler_type = 0x{{[0-9a-f]+}} const float +// CHECK-DAG: Type{{.*}} , name = "_Complex float", size = 4, compiler_type = 0x{{[0-9a-f]+}} _Complex float +// CHECK-DAG: Type{{.*}} , name = "_Complex double", size = 8, compiler_type = 0x{{[0-9a-f]+}} _Complex double + // CHECK-DAG: Type{{.*}} , name = "ReturnedStruct1", size = 1, decl = simple-types.cpp:21, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct1 { // CHECK-DAG: Type{{.*}} , name = "ReturnedStruct2", size = 1, decl = simple-types.cpp:22, compiler_type = 0x{{[0-9a-f]+}} struct ReturnedStruct2 { // CHECK-DAG: Type{{.*}} , name = "MyStruct", size = 1, decl = simple-types.cpp:24, compiler_type = 0x{{[0-9a-f]+}} struct MyStruct { |